From 727f1be11c828d96befe2d565987ad69d83ef60e Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Thu, 5 Feb 2026 13:11:45 +0300 Subject: [PATCH 1/2] hint_sender: Switch to sender group on stop either Currently sender only switches group for hints sending on start. It's worth doing the same on stop too for consistency. There's nothing to compete with at this point. Signed-off-by: Pavel Emelyanov --- db/hints/internal/hint_sender.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/db/hints/internal/hint_sender.cc b/db/hints/internal/hint_sender.cc index 20b520aab4..2dc0a3edfa 100644 --- a/db/hints/internal/hint_sender.cc +++ b/db/hints/internal/hint_sender.cc @@ -154,7 +154,10 @@ hint_sender::~hint_sender() { future<> hint_sender::stop(drain should_drain) noexcept { - return seastar::async([this, should_drain] { + seastar::thread_attributes attr; + + attr.sched_group = _hints_cpu_sched_group; + return seastar::async(std::move(attr), [this, should_drain] { set_stopping(); _stop_as.request_abort(); _stopped.get(); From 83e64b516a8ade524c3eecb82300b642bebc8b79 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Thu, 5 Feb 2026 06:17:11 +0300 Subject: [PATCH 2/2] hint: Don't switch group in database::apply_hint() The method is called from storage_proxy::mutate_hint() which is in turn called from hint_mutation::apply_locally(). The latter is either called from directly by hint sender, which already runs in streaming group, or via RPC HINT_MUTATION handler which uses index 1 that negotiates streaming group as well. To be sure, add a debugging check for current group being the expected one. Signed-off-by: Pavel Emelyanov --- replica/database.cc | 4 +--- service/storage_proxy.cc | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/replica/database.cc b/replica/database.cc index e73e63f690..4e926d9e9a 100644 --- a/replica/database.cc +++ b/replica/database.cc @@ -2417,9 +2417,7 @@ future<> database::apply_hint(schema_ptr s, const frozen_mutation& m, tracing::t if (!s->is_synced()) { on_internal_error(dblog, format("attempted to apply hint using not synced schema of {}.{}, version={}", s->ks_name(), s->cf_name(), s->version())); } - return with_scheduling_group(_dbcfg.streaming_scheduling_group, [this, s = std::move(s), &m, tr_state = std::move(tr_state), timeout] () mutable { - return _apply_stage(this, std::move(s), seastar::cref(m), std::move(tr_state), timeout, db::commitlog::force_sync::no, std::monostate{}); - }); + return _apply_stage(this, std::move(s), seastar::cref(m), std::move(tr_state), timeout, db::commitlog::force_sync::no, std::monostate{}); } keyspace::config diff --git a/service/storage_proxy.cc b/service/storage_proxy.cc index 967cb9586e..a6accd9212 100644 --- a/service/storage_proxy.cc +++ b/service/storage_proxy.cc @@ -94,6 +94,7 @@ #include "locator/util.hh" #include "tools/build_info.hh" #include "utils/labels.hh" +#include "debug.hh" namespace bi = boost::intrusive; @@ -1410,6 +1411,9 @@ public: virtual future<> apply_locally(storage_proxy& sp, storage_proxy::clock_type::time_point timeout, tracing::trace_state_ptr tr_state, db::per_partition_rate_limit::info rate_limit_info, const locator::effective_replication_map& erm) override { + if (current_scheduling_group() != debug::streaming_scheduling_group) { + on_internal_error(dblog, format("attempted to apply hint in {} scheduling group", current_scheduling_group().name())); + } // A hint will be sent to all relevant endpoints when the endpoint it was originally intended for // becomes unavailable - this might include the current node return sp.mutate_hint(_schema, *_mutation, std::move(tr_state), timeout);