-
Notifications
You must be signed in to change notification settings - Fork 0
First proposed release #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughIntroduces typed per-function timeout configs and FunctionList refinements; makes AsyncFunctionExecutor connect() return int; adds timeout-aware idle strategy and client wait APIs; updates AeronClient error handling; removes nlohmann_json; splits examples into producer/consumer/driver; and updates CMake/test wiring and docs. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor App
participant Exec as AsyncFunctionExecutor
participant Client as ClientInterface / AeronClient
participant Net as Transport
rect rgb(250,250,255)
note right of App: Initialization & connect
App->>Exec: new AsyncFunctionExecutor(Config{..., functionConfigs}, FunctionList, [client])
App->>Exec: connect()
Exec->>Client: connect(...)
Client-->>Exec: int status
end
rect rgb(245,255,245)
note right of App: Producer flow (per-fn timeout)
App->>Exec: callFunc(FunctionDef fn, args...)
Exec->>Client: sendMessage(callChannel, encodedArgs)
Exec->>Client: waitForMessage(returnChannel, timeout = fn.timeout || default)
alt message received
Client-->>Exec: span(bytes)
Exec-->>App: return decoded result
else timeout / empty
Client-->>Exec: empty span
Exec-->>App: throws / error
end
end
sequenceDiagram
autonumber
actor App
participant Exec as AsyncFunctionExecutor (Consumer)
participant Client as ClientInterface
participant Handler as UserCode
App->>Exec: connect()
loop poll loop
Exec->>Client: waitForMessage(callChannel, timeout)
alt got call
Client-->>Exec: span(call bytes)
Exec->>Handler: getFunctionArgs -> decoded args
Handler-->>Exec: sendReturnMessage(fnId, retVal)
Exec->>Client: sendMessage(returnChannel, encodedRet)
else no message / timeout
Note over Exec: idle and continue
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
include/bringauto/async_function_execution/clients/AeronClient.hpp (2)
109-114
: Unchecked map access may dereference null publication.operator[] inserts a default‑constructed shared_ptr and
->offer
will crash if the key is unknown. Check presence.- return aeronPublications_[channelId]->offer(srcBuffer, 0, messageBytes.size()); + const auto it = aeronPublications_.find(channelId); + if (it == aeronPublications_.end() || !it->second) { + std::cerr << "Unknown or null publication for channel " << channelId << std::endl; + return -1; + } + return it->second->offer(srcBuffer, 0, messageBytes.size());
124-136
: Guard missing subscription/message entries in waitForMessage.operator[] will create null entries; dereference causes UB. Validate keys and message presence.
- aeronPolling_[channelId] = true; + if (aeronSubscriptions_.find(channelId) == aeronSubscriptions_.end()) { + std::cerr << "Unknown subscription for channel " << channelId << std::endl; + return {}; + } + aeronPolling_[channelId] = true; @@ - const auto& msg = aeronMessages_[channelId]; - return std::span<const uint8_t>(msg.data, msg.length); + const auto itMsg = aeronMessages_.find(channelId); + if (itMsg == aeronMessages_.end() || itMsg->second.data == nullptr) { + return {}; + } + return std::span<const uint8_t>(itMsg->second.data, itMsg->second.length);
🧹 Nitpick comments (18)
include/bringauto/async_function_execution/Constants.hpp (1)
13-14
: Consider clarifying the origin of this size limit.The value
65535
(2^16 - 1) is a standard limit. If this relates to Aeron MTU, transport layer constraints, or serialization format requirements, consider adding that context to the documentation for future maintainers.examples/CMakeLists.txt (1)
7-13
: Consider using PRIVATE linkage for executable targets.The three example executables link to async-function-execution-shared with PUBLIC visibility. Since these are final executables (not libraries), PRIVATE linkage is typically more appropriate and prevents unnecessary transitive dependency exposure.
Apply this diff to use PRIVATE linkage:
-TARGET_LINK_LIBRARIES(example_producer PUBLIC async-function-execution-shared) -TARGET_LINK_LIBRARIES(example_consumer PUBLIC async-function-execution-shared) -TARGET_LINK_LIBRARIES(example_driver PUBLIC async-function-execution-shared) +TARGET_LINK_LIBRARIES(example_producer PRIVATE async-function-execution-shared) +TARGET_LINK_LIBRARIES(example_consumer PRIVATE async-function-execution-shared) +TARGET_LINK_LIBRARIES(example_driver PRIVATE async-function-execution-shared)examples/main_driver.cpp (1)
7-11
: Consider adding error handling and documenting shutdown.The example demonstrates minimal usage but lacks error handling for
driver.run()
and provides no shutdown mechanism. For a production-like example, consider:
- Checking the return value of
driver.run()
if it returns an error code- Adding signal handling (SIGINT/SIGTERM) to gracefully stop the driver
- Including comments explaining expected behavior and shutdown
Example enhancement:
+#include <csignal> + +static AeronDriver* globalDriver = nullptr; + +void signalHandler(int signal) { + if (globalDriver) { + globalDriver->stop(); + } +} + int main() { AeronDriver driver; + globalDriver = &driver; + std::signal(SIGINT, signalHandler); + std::signal(SIGTERM, signalHandler); + + std::cout << "Starting Aeron driver (press Ctrl+C to stop)..." << std::endl; driver.run(); + std::cout << "Driver stopped." << std::endl; return 0; }examples/main_producer.cpp (2)
1-6
: Include what you use; avoid transitive headers.Add headers for iostream/chrono/span/string/cstdint used below.
#include <bringauto/async_function_execution/AsyncFunctionExecutor.hpp> +#include <iostream> +#include <string> +#include <span> +#include <chrono> +#include <cstdint>
40-45
: Optional: demonstrate per‑function timeouts in the example config.Since the docs mention functionConfigurations, consider adding 1 example override to mirror tests.
test/include/AsyncFunctionExecutorTests.hpp (3)
6-6
: Add the chrono header.You use std::chrono types below.
#include <gtest/gtest.h> +#include <chrono>
58-65
: Per‑function timeouts (1–5 ms) may be flaky on CI.Nanosecond literals equate to 1–5 ms here, which is tight under load. Consider ≥50 ms unless you’re explicitly testing timeout behavior.
95-97
: Assert connect() succeeds.Turn silent failures into early, actionable test errors.
- executorProducer.connect(); - executorConsumer.connect(); + ASSERT_EQ(0, executorProducer.connect()); + ASSERT_EQ(0, executorConsumer.connect());examples/README.md (1)
22-22
: Add trailing newline at EOF.Minor formatting hygiene for POSIX tools.
examples/main_consumer.cpp (3)
2-2
: Remove unused include.AeronDriver isn’t used here.
-#include <bringauto/async_function_execution/AeronDriver.hpp>
1-6
: Include what you use.Add iostream/string/span/chrono/cstdint to avoid relying on transitive includes.
#include <bringauto/async_function_execution/AsyncFunctionExecutor.hpp> +#include <iostream> +#include <string> +#include <span> +#include <chrono> +#include <cstdint>
48-49
: Check connect() result and handle failure.Prevents spinning in the poll loop after a failed init.
- executor.connect(); + const int rc = executor.connect(); + if (rc != 0) { + std::cerr << "Consumer: connect() failed, rc=" << rc << std::endl; + return rc; + }source/bringauto/async_function_execution/TimeoutIdleStrategy.cpp (2)
28-30
: Reset on timeout to avoid sticky state across calls.Without reset(), subsequent idle() calls may immediately keep returning -1 due to preserved startTime_/state.
- if (std::chrono::duration_cast<std::chrono::nanoseconds>(now - startTime_) >= timeoutNs) { - return -1; - } + if (std::chrono::duration_cast<std::chrono::nanoseconds>(now - startTime_) >= timeoutNs) { + reset(); // ensure next wait starts fresh + return -1; + }
1-4
: Add direct includes for used facilities.std::min, std::this_thread, and chrono are used here; include explicitly.
#include <bringauto/async_function_execution/TimeoutIdleStrategy.hpp> +#include <algorithm> // std::min +#include <thread> // std::this_thread::yield/sleep_for +#include <chrono> // std::chrono::*README.md (3)
39-40
: Show connect() return handling.connect() returns int; demonstrate checking it to guide users.
-executorProducer.connect(); +if (executorProducer.connect() != 0) { + throw std::runtime_error("Failed to connect executorProducer"); +}
42-54
: Clarify duration units and example.Text says “in nanoseconds” but example uses seconds. State “any std::chrono duration convertible to ns” and show a ns example.
-The functionConfigurations parameter accepts an unordered map representing per function configurations. Syntax: +functionConfigurations accepts an unordered_map of per‑function configs. Durations are any std::chrono duration convertible to nanoseconds. Syntax: @@ - - timeout: replaces the default timeout value for that function (in nanoseconds) + - timeout: replaces the default timeout for that function (stored as nanoseconds)Example:
- { 1, { std::chrono::seconds(2) } } + { 1, { std::chrono::nanoseconds{2'000'000'000} } }
24-30
: Fix markdown lint: replace hard tabs and list indentation.Replace tabs with spaces and align the “Supported parameters” list to column 0 (MD010, MD007).
Also applies to: 48-49, 53-53
include/bringauto/async_function_execution/AsyncFunctionExecutor.hpp (1)
343-343
: Clarify size calculation comment.The comment states "Each argument: size bytes + data", but the actual size calculation adds
2 + sizeof(args)
per argument (2 bytes for the size field, plus the argument size). Consider updating the comment to explicitly mention the 2-byte size prefix for clarity.Apply this diff to clarify the comment:
- ((totalSize += 2 + sizeof(args)), ...); // Each argument: size bytes + data + ((totalSize += 2 + sizeof(args)), ...); // Each argument: 2-byte size prefix + data
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (24)
CMakeLists.txt
(3 hunks)README.md
(2 hunks)cmake/Dependencies.cmake
(0 hunks)examples/CMakeLists.txt
(1 hunks)examples/README.md
(1 hunks)examples/main.cpp
(0 hunks)examples/main_consumer.cpp
(1 hunks)examples/main_driver.cpp
(1 hunks)examples/main_producer.cpp
(1 hunks)include/bringauto/async_function_execution/AsyncFunctionExecutor.hpp
(12 hunks)include/bringauto/async_function_execution/Constants.hpp
(1 hunks)include/bringauto/async_function_execution/TimeoutIdleStrategy.hpp
(1 hunks)include/bringauto/async_function_execution/clients/AeronClient.hpp
(5 hunks)include/bringauto/async_function_execution/clients/ClientInterface.hpp
(2 hunks)include/bringauto/async_function_execution/structures/Settings.hpp
(2 hunks)source/bringauto/async_function_execution/TimeoutIdleStrategy.cpp
(1 hunks)test/CMakeLists.txt
(1 hunks)test/README.md
(1 hunks)test/include/AsyncFunctionExecutorTests.hpp
(1 hunks)test/include/MockClient.hpp
(1 hunks)test/integration_tests/main_segfault_consumer.cpp
(2 hunks)test/integration_tests/main_segfault_producer.cpp
(2 hunks)test/integration_tests/main_simple_function.cpp
(2 hunks)test/source/AsyncFunctionExecutorTests.cpp
(1 hunks)
💤 Files with no reviewable changes (2)
- examples/main.cpp
- cmake/Dependencies.cmake
🧰 Additional context used
🧬 Code graph analysis (7)
examples/main_consumer.cpp (2)
examples/main_producer.cpp (3)
reinterpret_cast
(11-13)bytes
(14-16)bytes
(14-14)include/bringauto/async_function_execution/AsyncFunctionExecutor.hpp (4)
bytes
(400-407)bytes
(400-400)funcId
(331-337)funcId
(331-331)
test/include/MockClient.hpp (3)
include/bringauto/async_function_execution/clients/AeronClient.hpp (5)
channelId
(111-114)channelId
(111-111)channelId
(124-136)channelId
(124-124)channelId
(144-163)include/bringauto/async_function_execution/clients/ClientInterface.hpp (2)
channelId
(33-33)channelId
(42-42)include/bringauto/async_function_execution/TimeoutIdleStrategy.hpp (1)
timeout
(69-69)
include/bringauto/async_function_execution/clients/ClientInterface.hpp (3)
include/bringauto/async_function_execution/clients/AeronClient.hpp (5)
channelId
(111-114)channelId
(111-111)channelId
(124-136)channelId
(124-124)channelId
(144-163)test/include/MockClient.hpp (4)
channelId
(22-78)channelId
(22-22)channelId
(80-88)channelId
(80-80)include/bringauto/async_function_execution/TimeoutIdleStrategy.hpp (1)
timeout
(69-69)
source/bringauto/async_function_execution/TimeoutIdleStrategy.cpp (1)
include/bringauto/async_function_execution/TimeoutIdleStrategy.hpp (2)
workCount
(47-47)timeout
(69-69)
examples/main_producer.cpp (3)
examples/main_consumer.cpp (3)
reinterpret_cast
(13-15)bytes
(16-18)bytes
(16-16)include/bringauto/async_function_execution/AsyncFunctionExecutor.hpp (2)
bytes
(400-407)bytes
(400-400)test/include/MockClient.hpp (4)
bytes
(113-127)bytes
(113-113)bytes
(130-143)bytes
(130-130)
include/bringauto/async_function_execution/clients/AeronClient.hpp (3)
include/bringauto/async_function_execution/clients/ClientInterface.hpp (3)
subscriptionIds
(24-24)channelId
(33-33)channelId
(42-42)test/include/MockClient.hpp (6)
subscriptionIds
(17-20)subscriptionIds
(17-17)channelId
(22-78)channelId
(22-22)channelId
(80-88)channelId
(80-80)include/bringauto/async_function_execution/TimeoutIdleStrategy.hpp (1)
timeout
(69-69)
include/bringauto/async_function_execution/AsyncFunctionExecutor.hpp (1)
test/include/MockClient.hpp (4)
funcId
(146-153)funcId
(146-146)funcId
(156-167)funcId
(156-156)
🪛 markdownlint-cli2 (0.18.1)
README.md
24-24: Hard tabs
Column: 1
(MD010, no-hard-tabs)
25-25: Hard tabs
Column: 1
(MD010, no-hard-tabs)
26-26: Hard tabs
Column: 1
(MD010, no-hard-tabs)
27-27: Hard tabs
Column: 1
(MD010, no-hard-tabs)
28-28: Hard tabs
Column: 1
(MD010, no-hard-tabs)
29-29: Hard tabs
Column: 1
(MD010, no-hard-tabs)
30-30: Hard tabs
Column: 1
(MD010, no-hard-tabs)
48-48: Hard tabs
Column: 1
(MD010, no-hard-tabs)
53-53: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
🔇 Additional comments (31)
include/bringauto/async_function_execution/Constants.hpp (4)
1-8
: LGTM!Header structure is clean with appropriate include guard and minimal dependencies. The namespace declaration is correct.
9-10
: Clarify the rationale for the polling limit value.The value
10
appears arbitrary. Consider documenting why this specific limit was chosen (e.g., based on Aeron best practices, performance testing, or latency requirements). If this value may need tuning in different deployment scenarios, consider making it configurable rather than a hard-coded constant.
11-12
: Document assumptions about function ID ranges to prevent collisions.The offset value assumes function IDs remain below a certain range to avoid collision between request and return channels. Consider documenting the expected range of function IDs (e.g., "Assumes function IDs are in range [0, 999]") or implementing validation to ensure
functionId + MESSAGE_RETURN_CHANNEL_OFFSET
doesn't collide with existing channel IDs.
16-17
: LGTM!The Aeron IPC connection string is correct, and using
std::string_view
for a compile-time string constant is appropriate. The documentation clearly indicates this is for shared memory communication.test/CMakeLists.txt (1)
6-8
: LGTM! Good guard to enforce correct build workflow.The target existence check ensures tests are built as part of the main project, preventing misconfiguration. The error message is clear and actionable.
test/README.md (1)
9-14
: LGTM! Documentation correctly reflects the integrated build approach.The simplified build instructions align with the CMakeLists.txt target check and make the process clearer for developers.
include/bringauto/async_function_execution/clients/ClientInterface.hpp (2)
6-6
: LGTM! Include added to support timeout parameter.
39-42
: All waitForMessage call sites include the timeout parameter.
No missing invocations detected across source, header, or test files.examples/CMakeLists.txt (1)
3-5
: LGTM! Consistent guard with test/CMakeLists.txt.The target existence check is consistent with the test configuration and ensures examples are built correctly.
test/integration_tests/main_segfault_consumer.cpp (2)
32-34
: LGTM! Simplified FunctionList initialization.The removal of the std::tuple wrapper makes the initialization cleaner and aligns with the refactored FunctionList type system.
60-60
: LGTM! Added missing end-of-file newline.test/include/MockClient.hpp (1)
80-88
: LGTM! Timeout parameter correctly added to match updated interface.The method signature now correctly overrides
ClientInterface::waitForMessage
with the timeout parameter. The test assertion at line 82 validates that per-function timeout values are correctly calculated based on channel ID, which is appropriate for a mock in test scenarios.test/integration_tests/main_segfault_producer.cpp (1)
33-35
: LGTM! Updated FunctionList initialization aligns with API refactor.The direct braced initialization is clearer and more idiomatic than the previous tuple-based approach.
CMakeLists.txt (3)
7-7
: LGTM! Version bumped to 1.0.0 for release.The major version bump appropriately signals API maturity and the timeout configuration changes introduced in this PR.
60-60
: LGTM! Using ADD_SUBDIRECTORY for tests is standard practice.This provides better encapsulation and allows the test directory to manage its own CMake scope.
82-82
: LGTM! Examples path normalized.Removing the trailing slash is a minor cleanup with no functional impact.
test/integration_tests/main_simple_function.cpp (2)
20-22
: LGTM! Updated FunctionList initialization for producer.The direct braced initialization aligns with the API refactor and improves code clarity.
29-31
: LGTM! Updated FunctionList initialization for consumer.Consistent with the producer initialization, maintaining code uniformity.
test/source/AsyncFunctionExecutorTests.cpp (1)
113-128
: Connect verification already implemented: AsyncFunctionExecutorTests::SetUpTestSuite callsexecutorProducer.connect()
andexecutorConsumer.connect()
(lines 95–96), so the suggestion can be removed.include/bringauto/async_function_execution/clients/AeronClient.hpp (2)
124-131
: UseTimeoutIdleStrategy
as the default IdleStrategy
AeronClient.hpp currently defaults toaeron::BackoffIdleStrategy
, which does not support the callidle(fragmentsRead, timeout)
. Change the template default toTimeoutIdleStrategy
or introduce an adapter that provides bothidle(int, timeout)
andidle(int)
overloads to avoid compilation errors.
152-155
: idle(fragmentsRead) already respects the configured timeout – it calls idle(fragmentsRead, std::chrono::nanoseconds{0}), which falls back to the default timeout in TimeoutIdleStrategy; no change needed.Likely an incorrect or invalid review comment.
include/bringauto/async_function_execution/structures/Settings.hpp (2)
18-26
: LGTM! Clean refactor to structured configuration.The introduction of
FunctionConfigs
as a typed wrapper around the configuration map is a solid improvement over JSON string parsing. The move semantics in the constructor are correctly applied.
38-42
: LGTM! Constructor signature is clear and idiomatic.The updated
Settings
constructor correctly acceptsFunctionConfigs
by const reference with a sensible default, maintaining good API ergonomics.include/bringauto/async_function_execution/TimeoutIdleStrategy.hpp (3)
16-37
: LGTM! Constructor documentation is clear.The updated documentation accurately describes the constructor parameters and their defaults.
39-52
: LGTM! Public API is well-designed.The new
idle(int workCount, std::chrono::nanoseconds timeout)
signature provides a clean interface for timeout-aware idling, and thereset()
method allows state reinitialization.
54-69
: Good encapsulation by moving IdleState to private scope.Moving the
IdleState
enum to the private section is a positive change that reduces the public API surface and prevents external dependencies on internal state representation.include/bringauto/async_function_execution/AsyncFunctionExecutor.hpp (5)
22-22
: LGTM! Consistent with Settings.hpp refactor.The change to
structures::FunctionConfigs
aligns with the structured configuration approach introduced in Settings.hpp.
89-126
: LGTM! Well-designed type traits and deduction guide.The
is_function_definition
trait,IsFunctionDefinition
concept, and the deduction guide forFunctionList
provide strong compile-time guarantees and improve API usability.
143-161
: LGTM! Constructor validation improves robustness.The constructor correctly validates that all function IDs in the configuration are defined in the FunctionList, catching configuration errors early. The optional client parameter adds useful flexibility for testing and custom implementations.
172-185
: LGTM! Return type change improves error handling.Changing
connect()
to returnint
allows callers to detect connection failures, which is a significant improvement over the previous void return.
212-216
: Zero timeout yields infinite wait (no fallback to defaultTimeout). Verified that whenFunctionConfig.timeout
is zero,waitForMessage
passes nanoseconds(0) toTimeoutIdleStrategy
, which skips the timeout check and idles indefinitely (per its docs and implementation).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
test/integration_tests/main_simple_function.cpp (1)
1-6
: Include what you use: add and .This TU uses std::thread and std::this_thread::sleep_for but doesn’t include their headers. Add explicit includes to avoid transitive‑include breakage.
#include <bringauto/async_function_execution/AsyncFunctionExecutor.hpp> #include <bringauto/async_function_execution/AeronDriver.hpp> #include <iostream> +#include <thread> +#include <chrono>test/integration_tests/main_segfault_producer.cpp (1)
1-6
: Include what you use: add and .This TU launches a std::thread and sleeps.
#include <bringauto/async_function_execution/AsyncFunctionExecutor.hpp> #include <bringauto/async_function_execution/AeronDriver.hpp> #include <iostream> +#include <thread> +#include <chrono> namespace baafe = bringauto::async_function_execution;Also applies to: 9-14
include/bringauto/async_function_execution/clients/AeronClient.hpp (1)
19-20
: Default IdleStrategy mismatches idle(fragmentsRead, timeout); set to TimeoutIdleStrategy.BackoffIdleStrategy typically lacks idle(int, std::chrono::nanoseconds) and returns void. Using it as default can cause compile errors if instantiated. Make TimeoutIdleStrategy the default.
-template<typename IdleStrategy = aeron::BackoffIdleStrategy> +template<typename IdleStrategy = bringauto::async_function_execution::TimeoutIdleStrategy>include/bringauto/async_function_execution/AsyncFunctionExecutor.hpp (1)
143-161
: Verify function config validation logic.Lines 156-160 validate that all function IDs in the configuration are defined in the FunctionList. However, the error message (line 158) says "Warning:" but then throws an exception, which is contradictory.
Apply this diff to make the error message consistent:
- throw std::runtime_error("Warning: Function ID " + std::to_string(funcId) + " in configuration is not defined in FunctionList."); + throw std::runtime_error("Function ID " + std::to_string(funcId) + " in configuration is not defined in FunctionList.");
♻️ Duplicate comments (2)
examples/main_consumer.cpp (1)
58-73
: Return type fixed to SerializableString.Calls to sendReturnMessage now pass SerializableString as required. Resolves prior review.
include/bringauto/async_function_execution/clients/AeronClient.hpp (1)
69-99
: Bounded waits in connect() are a solid improvement.Timeouts with early returns and logging address the previous busy‑wait risk.
🧹 Nitpick comments (10)
README.md (1)
15-31
: Replace hard tabs with spaces to satisfy markdownlint.The new blocks introduced literal tab characters and a mis-indented bullet, triggering MD010/MD007 from markdownlint-cli2. Swap tabs for spaces (e.g., four spaces) and align the bullet list so the pipeline stays green.
Also applies to: 49-55
include/bringauto/async_function_execution/structures/Settings.hpp (1)
23-26
: Include<utility>
forstd::move
.This header now calls
std::move
, but<utility>
isn’t included. Pull it in here to avoid depending on indirect includes.test/include/AsyncFunctionExecutorTests.hpp (1)
94-97
: Assert connect() success in SetUpTestSuite.connect() now returns int. Assert/FAIL on non‑zero to avoid hidden failures.
static void SetUpTestSuite() { - executorProducer.connect(); - executorConsumer.connect(); + ASSERT_EQ(0, executorProducer.connect()) << "Producer connect failed"; + ASSERT_EQ(0, executorConsumer.connect()) << "Consumer connect failed"; }test/source/AsyncFunctionExecutorTests.cpp (1)
134-138
: ArgumentTooLarge test adds useful boundary coverage.Consider adding a 65535‑byte success case to pin the exact limit.
include/bringauto/async_function_execution/clients/AeronClient.hpp (4)
171-174
: Verify IdleStrategy interface consistency in waitForAnyMessage.Here idle(fragmentsRead) is called (1 arg), but waitForMessage calls idle(fragmentsRead, timeout). Ensure the chosen IdleStrategy supports both or refactor to a single consistent signature.
74-82
: Improve log context for timeouts.Include pub/sub IDs to aid diagnosis.
- std::cerr << "Aeron connection error: Timeout while waiting for publication" << std::endl; + std::cerr << "Aeron connection error: Timeout while waiting for publication id=" << pubId << std::endl; @@ - std::cerr << "Aeron connection error: Timeout while waiting for subscription" << std::endl; + std::cerr << "Aeron connection error: Timeout while waiting for subscription id=" << subId << std::endl;Also applies to: 89-97
121-129
: Minor: avoid const_cast by constructing AtomicBuffer from a mutable copy.Not critical, but reduces UB risk if the impl writes. Optional.
65-110
: Optional: brief sleep in connect loops to reduce CPU.Yield-only loops can still spin. A tiny sleep (e.g., 1ms) reduces load without hurting latency.
include/bringauto/async_function_execution/AsyncFunctionExecutor.hpp (1)
401-407
: Redundant empty check.Line 401 checks if
bytes.empty()
before accessingbytes[0]
on line 404. However, this check is redundant because:
- In
pollFunction()
(line 244), an empty span is already returned ifrequestBytes.empty()
- The check adds minimal value since callers should validate before calling this private method
Consider removing the redundant check or documenting why it's defensive:
std::tuple<FunctionId, std::span<const uint8_t>> deserializeRequest(const std::span<const uint8_t>& bytes) { - if (bytes.empty()) { - throw std::invalid_argument("Not enough data to deserialize request"); - } + // bytes guaranteed non-empty by pollFunction() FunctionId funcId{ bytes[0] }; std::span<const uint8_t> args(bytes.begin() + 1, bytes.end()); return std::make_tuple(funcId, args); }test/include/MockClient.hpp (1)
80-88
: Derive expected timeout from test configuration instead of hardcoding formula
In MockClient::waitForMessage (test/include/MockClient.hpp:80–82), replace the literal(channelId - 1000) * 1'000'000
with a lookup of the configured timeout for functionId = channelId - 1000. This ensures the EXPECT_EQ compares against the actual test setup and remains correct if timeouts change.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (19)
README.md
(2 hunks)examples/README.md
(1 hunks)examples/main_consumer.cpp
(1 hunks)examples/main_producer.cpp
(1 hunks)include/bringauto/async_function_execution/AeronDriver.hpp
(1 hunks)include/bringauto/async_function_execution/AsyncFunctionExecutor.hpp
(17 hunks)include/bringauto/async_function_execution/TimeoutIdleStrategy.hpp
(1 hunks)include/bringauto/async_function_execution/clients/AeronClient.hpp
(4 hunks)include/bringauto/async_function_execution/clients/ClientInterface.hpp
(2 hunks)include/bringauto/async_function_execution/structures/Settings.hpp
(2 hunks)source/bringauto/async_function_execution/AeronDriver.cpp
(2 hunks)source/bringauto/async_function_execution/TimeoutIdleStrategy.cpp
(1 hunks)test/README.md
(1 hunks)test/include/AsyncFunctionExecutorTests.hpp
(2 hunks)test/include/MockClient.hpp
(6 hunks)test/integration_tests/main_segfault_consumer.cpp
(3 hunks)test/integration_tests/main_segfault_producer.cpp
(4 hunks)test/integration_tests/main_simple_function.cpp
(3 hunks)test/source/AsyncFunctionExecutorTests.cpp
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- examples/README.md
🚧 Files skipped from review as they are similar to previous changes (2)
- examples/main_producer.cpp
- source/bringauto/async_function_execution/TimeoutIdleStrategy.cpp
🧰 Additional context used
🧬 Code graph analysis (8)
test/integration_tests/main_simple_function.cpp (1)
test/include/AsyncFunctionExecutorTests.hpp (1)
executorProducer
(94-97)
include/bringauto/async_function_execution/clients/ClientInterface.hpp (3)
include/bringauto/async_function_execution/clients/AeronClient.hpp (5)
channelId
(121-129)channelId
(121-121)channelId
(139-156)channelId
(139-139)channelId
(164-183)test/include/MockClient.hpp (4)
channelId
(22-78)channelId
(22-22)channelId
(80-88)channelId
(80-80)include/bringauto/async_function_execution/TimeoutIdleStrategy.hpp (1)
timeout
(64-64)
test/source/AsyncFunctionExecutorTests.cpp (1)
test/include/AsyncFunctionExecutorTests.hpp (1)
executorProducer
(94-97)
test/include/MockClient.hpp (4)
include/bringauto/async_function_execution/AsyncFunctionExecutor.hpp (4)
funcId
(331-337)funcId
(331-331)bytes
(400-407)bytes
(400-400)include/bringauto/async_function_execution/clients/AeronClient.hpp (5)
channelId
(121-129)channelId
(121-121)channelId
(139-156)channelId
(139-139)channelId
(164-183)include/bringauto/async_function_execution/clients/ClientInterface.hpp (2)
channelId
(32-32)channelId
(41-41)include/bringauto/async_function_execution/TimeoutIdleStrategy.hpp (1)
timeout
(64-64)
test/integration_tests/main_segfault_producer.cpp (1)
test/include/AsyncFunctionExecutorTests.hpp (1)
executorProducer
(94-97)
include/bringauto/async_function_execution/clients/AeronClient.hpp (3)
include/bringauto/async_function_execution/clients/ClientInterface.hpp (3)
subscriptionIds
(23-23)channelId
(32-32)channelId
(41-41)test/include/MockClient.hpp (6)
subscriptionIds
(17-20)subscriptionIds
(17-17)channelId
(22-78)channelId
(22-22)channelId
(80-88)channelId
(80-80)include/bringauto/async_function_execution/TimeoutIdleStrategy.hpp (1)
timeout
(64-64)
examples/main_consumer.cpp (2)
include/bringauto/async_function_execution/AsyncFunctionExecutor.hpp (4)
bytes
(400-407)bytes
(400-400)funcId
(331-337)funcId
(331-331)test/include/MockClient.hpp (8)
bytes
(113-127)bytes
(113-113)bytes
(130-143)bytes
(130-130)funcId
(146-153)funcId
(146-146)funcId
(156-167)funcId
(156-156)
include/bringauto/async_function_execution/AsyncFunctionExecutor.hpp (2)
test/include/MockClient.hpp (8)
funcId
(146-153)funcId
(146-146)funcId
(156-167)funcId
(156-156)bytes
(113-127)bytes
(113-113)bytes
(130-143)bytes
(130-130)include/bringauto/async_function_execution/clients/AeronClient.hpp (1)
buffer
(186-191)
🪛 markdownlint-cli2 (0.18.1)
README.md
24-24: Hard tabs
Column: 1
(MD010, no-hard-tabs)
25-25: Hard tabs
Column: 1
(MD010, no-hard-tabs)
26-26: Hard tabs
Column: 1
(MD010, no-hard-tabs)
27-27: Hard tabs
Column: 1
(MD010, no-hard-tabs)
28-28: Hard tabs
Column: 1
(MD010, no-hard-tabs)
29-29: Hard tabs
Column: 1
(MD010, no-hard-tabs)
30-30: Hard tabs
Column: 1
(MD010, no-hard-tabs)
49-49: Hard tabs
Column: 1
(MD010, no-hard-tabs)
54-54: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
🔇 Additional comments (35)
source/bringauto/async_function_execution/AeronDriver.cpp (3)
3-3
: Good modernization: C++ header preferred.Replacing
<signal.h>
with<csignal>
aligns with modern C++ best practices.
29-29
: Good modernization: nullptr is type-safe.Using
nullptr
instead ofNULL
is a C++11 best practice that provides better type safety.
37-42
: Const-correctness applied logically.Marking
run()
asconst
is technically valid since it doesn't modify the observable state of theAeronDriver
wrapper object itself. The underlyingaeron_driver_t
state modifications are external to this wrapper's members.This design treats the wrapper as a handle to the driver rather than the driver itself—a reasonable approach for RAII/wrapper classes.
include/bringauto/async_function_execution/AeronDriver.hpp (2)
27-27
: Declaration matches implementation.The
const
qualifier aligns with the implementation inAeronDriver.cpp
and correctly reflects that this method doesn't modify the wrapper object's observable state.
33-33
: [[nodiscard]] appropriately applied.Adding
[[nodiscard]]
toisRunning()
is correct since this is a pure query method with no side effects. Ignoring its return value would be a logic error that this attribute helps catch at compile time.test/integration_tests/main_simple_function.cpp (2)
20-23
: FunctionList brace-init looks good.Also applies to: 29-32
65-72
: Good: handle connect() failures.Checking the int return and failing fast improves test reliability.
test/include/AsyncFunctionExecutorTests.hpp (3)
15-15
: Explicit SerializableString ctor is appropriate.
58-66
: Typed per‑function timeouts wired correctly.Config uses FunctionConfigs with nanoseconds per ID; consistent with MockClient timeout checks.
67-74
: FunctionList brace-init update is fine.test/integration_tests/main_segfault_consumer.cpp (1)
39-43
: Good: handle connect() failure.test/integration_tests/main_segfault_producer.cpp (2)
54-57
: Good: connect() error handling.
64-65
: Good: pass SerializableString to callFunc.test/source/AsyncFunctionExecutorTests.cpp (2)
118-126
: Undefined function config test updated correctly.
30-38
: Potential flakiness: PollFunction has no arranged request.If no producer request is sent before this test, pollFunction may block or return empty. Ensure the test sends a request (or uses a mock setup) within this test.
include/bringauto/async_function_execution/clients/AeronClient.hpp (2)
139-151
: Channel existence checks and timeout-aware idle are good.Nice guard on missing channel and timeout return path.
1-207
: Ignore unintended default‐instantiation warning: allAeronClient
usages (e.g., inAsyncFunctionExecutor
) explicitly specify<TimeoutIdleStrategy>
, so no default template argument is ever used.Likely an incorrect or invalid review comment.
test/include/MockClient.hpp (7)
12-12
: LGTM!Marking the mock class as
final
is appropriate and enables compiler optimizations since this is a leaf test class with no intended inheritance.
45-78
: Const-correctness improvements look good.The addition of
const
qualifiers to local variables (funcId
,args
,sum
,product
) improves code clarity and prevents accidental mutations. The logic remains unchanged and correct.
113-127
: Const-correctness improvements look good.The parameter is now
const std::span<const uint8_t> &bytes
(line 113), and local variablesargCount
(line 115) andargSize
(line 119) are markedconst
. This prevents accidental mutations and improves readability.
130-143
: Const-correctness improvements look good.Similar to
deserializeIntRequest
, the parameter and local variables (argCount
at line 132,argSize
at line 136) are now properly const-qualified.
146-153
: Const-correctness improvements look good.The parameters
funcId
andreturnValue
are now const-qualified (line 146), and the local variable at line 149 is markedconst
. The serialization logic remains correct.
156-167
: Const-correctness improvements look good.The parameters are const-qualified (line 156), and local size calculation (lines 162-164) is properly const. The validation at lines 159-161 correctly prevents oversized strings from being serialized.
91-109
: No action needed: size encoding matches AsyncFunctionExecutor’s little-endian 16-bit format.include/bringauto/async_function_execution/AsyncFunctionExecutor.hpp (11)
22-23
: LGTM!The Config structure now uses
structures::FunctionConfigs
instead of a raw type, providing better type safety and structure for per-function timeout configurations.
28-32
: Document supported range for FunctionId.Line 28 documents that the supported range is 0-255, which is appropriate given
value
isuint8_t
. This is a helpful clarification for users.
46-72
: Explicit constructors improve type safety.The
Return<T>
(line 51),Return<void>
(line 60), andArguments<Args...>
(line 71) constructors are nowexplicit
, preventing implicit conversions and improving type safety. The addedvalue
andvalues
members (lines 50, 70) make the structures more self-documenting.
77-127
: Strong typing for FunctionDefinition and FunctionList.The additions provide compile-time guarantees:
- Lines 89-108: Type trait
is_function_definition
and conceptIsFunctionDefinition
ensure only validFunctionDefinition
types are used- Lines 115-119:
FunctionList
is now constrained byIsFunctionDefinition
and uses an explicit constructor- Lines 122-126: Deduction guide simplifies construction
These changes strengthen the type system and improve compile-time safety.
176-179
: Const-correctness in lambda captures looks good.Lines 176 and 179 now use
const auto&
in lambda captures withinstd::apply
, preventing unnecessary copies and accidental mutations.
212-216
: Per-function timeout lookup is correct.Lines 212-216 implement per-function timeout resolution:
- First checks if the function ID exists in
functionConfigs.configs
- Falls back to
defaultTimeout
if not found- Uses the ternary operator for concise selection
The logic is correct and handles the fallback case properly.
243-250
: Const-correctness improvements look good.Line 243 adds
const
torequestBytes
, preventing accidental modification. The rest of the method remains unchanged.
271-303
: Const-correctness and validation improvements.Line 271 adds an
empty()
check before accessingargBytes[pos]
, preventing potential out-of-bounds access. Line 285 marks the length variableconst
. These changes improve safety and code clarity.
333-337
: Const-correctness in lambda captures looks good.Lines 333 and 335 use
const auto&
in lambda captures, consistent with the changes at lines 176-179.
343-381
: Const-correctness in serialization helpers looks good.Lines 343, 355, 370, 372, 376, and 378 add
const
qualifiers to size calculations and intermediate variables. This prevents accidental mutations and improves code clarity without changing behavior.
412-412
: Documentation improvement acknowledged.The comment clarifies that
client_
can be a customClientInterface
implementation, which is helpful for users extending the library.
Summary by CodeRabbit
New Features
Breaking Changes
Documentation
Chores
Tests