strong_consistency: optimize wait_for_groups_to_start

instead of iterating over all raft groups in wait_for_groups_to_start
and check if we need to wait for them, maintain a list of only the raft
groups that are starting and need to be waited.
This commit is contained in:
Michael Litvak
2026-03-03 16:14:34 +01:00
parent 5a5c7c6241
commit e568ca2bd8
2 changed files with 7 additions and 13 deletions

View File

@@ -227,18 +227,9 @@ void groups_manager::schedule_raft_groups_deletion(bool all) {
}
future<> groups_manager::wait_for_groups_to_start(lowres_clock::time_point timeout) {
while (true) {
const auto it = std::ranges::find_if(_raft_groups, [](const auto& p) {
auto& state = p.second;
return !state.gate->is_closed() && !state.server_control_op.available();
});
if (it == _raft_groups.end()) {
break;
}
const auto& [id, state] = *it;
logger.info("waiting for group {} to start", id);
co_await state.server_control_op.get_future(timeout);
while (!_starting_groups.empty()) {
auto& state = _starting_groups.front();
co_await state.server_control_op.get_future(timeout); // the state is unlinked when this completes
}
}
@@ -388,11 +379,13 @@ void groups_manager::update(token_metadata_ptr new_tm) {
logger.info("update(): starting raft server for tablet {}, group id {}", tablet, id);
state.gate = make_lw_shared<gate>();
_starting_groups.push_back(state);
state.server_control_op = futurize_invoke([&state, this, tablet, id, new_tm](this auto) -> future<> {
co_await state.server_control_op.get_future();
co_await start_raft_group(tablet, id, std::move(new_tm));
state.server = &_raft_gr.get_server(id);
state.leader_info_updater = leader_info_updater(state, tablet, id);
_starting_groups.erase(_starting_groups.iterator_to(state));
logger.info("update(): raft server for tablet {} and group id {} is started", tablet, id);
});
});

View File

@@ -57,7 +57,7 @@ class groups_manager : public peering_sharded_service<groups_manager> {
api::timestamp_type last_timestamp;
};
struct raft_group_state {
struct raft_group_state : public boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>> {
bool has_tablet = false;
lw_shared_ptr<gate> gate = nullptr;
raft::server* server = nullptr;
@@ -84,6 +84,7 @@ class groups_manager : public peering_sharded_service<groups_manager> {
gms::feature_service& _features;
gms::gossiper& _gossiper;
std::unordered_map<raft::group_id, raft_group_state> _raft_groups = {};
boost::intrusive::list<raft_group_state, boost::intrusive::constant_time_size<false>> _starting_groups;
locator::token_metadata_ptr _pending_tm = nullptr;
bool _started = false;