-
Notifications
You must be signed in to change notification settings - Fork 568
Implement blocking fan_out_request #2132
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
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2132 +/- ##
==========================================
+ Coverage 72.03% 72.08% +0.05%
==========================================
Files 633 634 +1
Lines 30662 30780 +118
Branches 3322 3328 +6
==========================================
+ Hits 22088 22189 +101
- Misses 6667 6676 +9
- Partials 1907 1915 +8 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
fdfc890 to
3b6770a
Compare
3b6770a to
15d06f6
Compare
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.
Pull Request Overview
This PR adds fan-out request support for blocking actors, enabling them to send requests to multiple actors simultaneously and handle their responses according to a specified policy (select_all or select_any).
- Adds
blocking_fan_out_response_handleandblocking_fan_out_delayed_response_handleclasses for managing fan-out responses - Implements
fan_out_requestmethods for both scheduled and synchronous blocking mail - Extracts
expected_builderhelper into a separate header for reuse
Reviewed Changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| libcaf_core/caf/fwd.hpp | Adds forward declarations for new blocking fan-out response handle template classes |
| libcaf_core/caf/detail/expected_builder.hpp | New header file extracting expected_builder utility for building expected results from response handlers |
| libcaf_core/caf/blocking_response_handle.hpp | Removes expected_builder (moved to separate header) and adds include for new header |
| libcaf_core/caf/blocking_mail.hpp | Adds fan_out_request methods to both scheduled and synchronous blocking mail classes |
| libcaf_core/caf/blocking_fan_out_response_handle.hpp | New header implementing fan-out response handle classes for blocking actors with policy-based response aggregation |
| libcaf_core/caf/blocking_fan_out_request.test.cpp | Comprehensive test suite for fan-out request functionality covering various scenarios |
| libcaf_core/caf/blocking_actor.hpp | Adds include for expected_builder header |
| libcaf_core/caf/abstract_blocking_actor.hpp | Adds friend declaration for blocking_fan_out_response_handle template class |
| libcaf_core/CMakeLists.txt | Adds new test file to build configuration |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// `request(...).receive(...)`. | ||
| template <class Policy, class... Results> | ||
| class blocking_fan_out_response_handle { | ||
| public: |
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.
static constexpr bool is_select_all = ...;
static constexpr bool is_select_any = ...;
static_assert(is_select_all || is_select_any);Then use requires to dispatch instead of using if constexpr inside the function. Makes it IMHO easier to follow what's going than two big if-else branches.
| detail::expected_builder<Results...> bld; | ||
| std::move(*this).receive( | ||
| [&bld](Results... args) { bld.set_value(std::move(args)...); }, | ||
| [&bld](error& err) { bld.set_error(std::move(err)); }); | ||
| return std::move(bld.result); |
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.
I'm not convinced that we need expected_builder. In fact, I'd like to see that go.
| detail::expected_builder<Results...> bld; | |
| std::move(*this).receive( | |
| [&bld](Results... args) { bld.set_value(std::move(args)...); }, | |
| [&bld](error& err) { bld.set_error(std::move(err)); }); | |
| return std::move(bld.result); | |
| expected<Results...> result; | |
| std::move(*this).receive( | |
| [&bld](Results&... args) { result.emplace(std::move(args)...); }, | |
| [&bld](error& err) { result = std::move(err)); }); | |
| return result; |
The only special case we would need to worry about is constructing expected<void>. That can be done in a utility function, though:
static auto make_expected() {
if constexpr (sizeof...(Ts) == 0) {
return expected<void>{};
}
...
}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.
Another case is that having multiple results requires an tuple<Results...>, which the builder solves. But I'll refactor to account for it.
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.
I still need to remove the expected builder from blocking_response_handle, but since that class still uses a specialization for that will be a follow-up.
c6e5ef7 to
09d87fd
Compare
09d87fd to
b1648b5
Compare
|
Aside the review comments I added the dynamically typed receive member. |
Implemented the blocking stuff.
There was a small issue I've had with
do_receive, since it receives a single message. It behaved weirdly withtimespans, so I switched to usingtime_points. Alternatively, I could've implemented a newreceive_condthat awaitsnmessages, but then I'd have to move fromabstract_blocking_actor*to the concreteblocking_actor*implementation.Relates #2009.