Skip to content

Commit db55a1e

Browse files
Merge pull request #31046 from redpanda-data/stephan/repl-monitor
ssx,raft: rework repeat_until_gate_closed as a coroutine
2 parents cc52bc1 + 361ddd1 commit db55a1e

2 files changed

Lines changed: 75 additions & 46 deletions

File tree

src/v/raft/replication_monitor.cc

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,19 @@ namespace raft {
2121

2222
replication_monitor::replication_monitor(consensus* r)
2323
: _raft(r) {
24-
ssx::repeat_until_gate_closed(_gate, [this] {
25-
return do_notify_replicated().handle_exception(
26-
[this](const std::exception_ptr& e) {
27-
if (!ssx::is_shutdown_exception(e)) {
28-
vlog(
29-
_raft->_ctxlog.error,
30-
"Exception running replication monitor, ignoring: {}",
31-
e);
32-
}
33-
});
34-
});
35-
36-
ssx::repeat_until_gate_closed(_gate, [this] {
37-
return do_notify_committed().handle_exception(
38-
[this](const std::exception_ptr& e) {
39-
if (!ssx::is_shutdown_exception(e)) {
40-
vlog(
41-
_raft->_ctxlog.error,
42-
"Exception running replication monitor, ignoring: {}",
43-
e);
44-
}
45-
});
46-
});
24+
auto exception_handler = [this](const std::exception_ptr& e) {
25+
if (!ssx::is_shutdown_exception(e)) {
26+
vlog(
27+
_raft->_ctxlog.error,
28+
"Exception running replication monitor, ignoring: {}",
29+
e);
30+
}
31+
};
32+
ssx::repeat_until_gate_closed(
33+
_gate, [this] { return do_notify_replicated(); }, exception_handler);
34+
35+
ssx::repeat_until_gate_closed(
36+
_gate, [this] { return do_notify_committed(); }, exception_handler);
4737
}
4838

4939
fmt::iterator replication_monitor::format_to(fmt::iterator it) const {
@@ -211,14 +201,14 @@ ss::future<> replication_monitor::do_notify_committed() {
211201
}
212202

213203
void replication_monitor::notify_replicated() {
214-
if (_gate.is_closed()) {
204+
if (_gate.is_closed() || _pending_majority_replication_waiters == 0) {
215205
return;
216206
}
217207
_replicated_event_cv.signal();
218208
}
219209

220210
void replication_monitor::notify_committed() {
221-
if (_gate.is_closed()) {
211+
if (_gate.is_closed() || _waiters.empty()) {
222212
return;
223213
}
224214
_committed_event_cv.signal();

src/v/ssx/future-util.h

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <seastar/core/abort_source.hh>
1919
#include <seastar/core/condition-variable.hh>
20+
#include <seastar/core/coroutine.hh>
2021
#include <seastar/core/future-util.hh>
2122
#include <seastar/core/future.hh>
2223
#include <seastar/core/gate.hh>
@@ -352,17 +353,35 @@ inline void spawn_with_gate(seastar::gate& g, Func&& func) noexcept {
352353
template<class Func>
353354
inline void
354355
repeat_until_gate_closed(seastar::gate& gate, Func&& func) noexcept {
355-
spawn_with_gate(gate, [&gate, func = std::forward<Func>(func)]() mutable {
356-
return ss::do_until(
357-
[&gate] { return gate.is_closed(); },
358-
[func = std::forward<Func>(func)]() mutable {
359-
return ss::futurize_invoke(func).handle_exception(
360-
[](const std::exception_ptr&) {
361-
// A generic catch all to avoid exceptional futures.
362-
// The input func may include it's own exception handling.
363-
});
364-
});
365-
});
356+
repeat_until_gate_closed(
357+
gate, std::forward<Func>(func), [](const std::exception_ptr&) {});
358+
}
359+
360+
/// \brief Repeats the passed func in a detached fiber until the gate is closed,
361+
/// invoking exception_handler on any exception.
362+
///
363+
/// \param gate Gate object to use.
364+
/// \param func function to invoke.
365+
/// \param exception_handler called with any exception thrown by func.
366+
template<class Func, class ExceptionHandler>
367+
inline void repeat_until_gate_closed(
368+
seastar::gate& gate,
369+
Func&& func,
370+
ExceptionHandler&& exception_handler) noexcept {
371+
spawn_with_gate(
372+
gate,
373+
[&gate,
374+
func = std::forward<Func>(func),
375+
exception_handler = std::forward<ExceptionHandler>(exception_handler)](
376+
this auto) -> seastar::future<> {
377+
while (!gate.is_closed()) {
378+
try {
379+
co_await seastar::futurize_invoke(func);
380+
} catch (...) {
381+
exception_handler(std::current_exception());
382+
}
383+
}
384+
});
366385
}
367386

368387
/// \brief Repeats the passed func in a detached fiber until the gate is closed
@@ -374,17 +393,37 @@ repeat_until_gate_closed(seastar::gate& gate, Func&& func) noexcept {
374393
template<class Func>
375394
inline void repeat_until_gate_closed_or_aborted(
376395
ss::gate& gate, ss::abort_source& as, Func&& func) noexcept {
396+
repeat_until_gate_closed_or_aborted(
397+
gate, as, std::forward<Func>(func), [](const std::exception_ptr&) {});
398+
}
399+
400+
/// \brief Repeats the passed func in a detached fiber until the gate is closed
401+
/// or abort is triggered, invoking exception_handler on any exception.
402+
///
403+
/// \param gate Gate object to use.
404+
/// \param as Abort source to use.
405+
/// \param func function to invoke.
406+
/// \param exception_handler called with any exception thrown by func.
407+
template<class Func, class ExceptionHandler>
408+
inline void repeat_until_gate_closed_or_aborted(
409+
ss::gate& gate,
410+
ss::abort_source& as,
411+
Func&& func,
412+
ExceptionHandler&& exception_handler) noexcept {
377413
spawn_with_gate(
378-
gate, [&gate, &as, func = std::forward<Func>(func)]() mutable {
379-
return ss::do_until(
380-
[&gate, &as] { return as.abort_requested() || gate.is_closed(); },
381-
[func = std::forward<Func>(func)]() mutable {
382-
return ss::futurize_invoke(func).handle_exception(
383-
[](const std::exception_ptr&) {
384-
// A generic catch all to avoid exceptional futures.
385-
// The input func may include it's own exception handling.
386-
});
387-
});
414+
gate,
415+
[&gate,
416+
&as,
417+
func = std::forward<Func>(func),
418+
exception_handler = std::forward<ExceptionHandler>(exception_handler)](
419+
this auto) -> seastar::future<> {
420+
while (!as.abort_requested() && !gate.is_closed()) {
421+
try {
422+
co_await seastar::futurize_invoke(func);
423+
} catch (...) {
424+
exception_handler(std::current_exception());
425+
}
426+
}
388427
});
389428
}
390429

0 commit comments

Comments
 (0)