service: Don't use new tablet_resize_finalization state until supported
In a rolling upgrade, nodes that weren't upgraded yet will not recognize
the new tablet_resize_finalization state, that serves both split and
merges, leading to a crash. To fix that, coordinator will pick the
old tablet_split_finalization state for serving split finalization,
until the cluster agrees on merge, so it can start using the new
generic state for resize finalization introduced in merge series.
Regression was introduced in e00798f.
Fixes #22840.
Reported-by: Tomasz Grabiec <tgrabiec@scylladb.com>
Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
Closes scylladb/scylladb#22845
This commit is contained in:
committed by
Avi Kivity
parent
de8de50fb9
commit
d78f57e94a
@@ -744,6 +744,8 @@ future<> storage_service::topology_state_load(state_change_hint hint) {
|
||||
[[fallthrough]];
|
||||
case topology::transition_state::tablet_migration:
|
||||
[[fallthrough]];
|
||||
case topology::transition_state::tablet_split_finalization:
|
||||
[[fallthrough]];
|
||||
case topology::transition_state::tablet_resize_finalization:
|
||||
[[fallthrough]];
|
||||
case topology::transition_state::commit_cdc_generation:
|
||||
|
||||
@@ -2338,6 +2338,8 @@ class topology_coordinator : public endpoint_lifecycle_subscriber {
|
||||
case topology::transition_state::tablet_migration:
|
||||
co_await handle_tablet_migration(std::move(guard), false);
|
||||
break;
|
||||
case topology::transition_state::tablet_split_finalization:
|
||||
[[fallthrough]];
|
||||
case topology::transition_state::tablet_resize_finalization:
|
||||
co_await handle_tablet_resize_finalization(std::move(guard));
|
||||
break;
|
||||
@@ -2918,11 +2920,15 @@ future<bool> topology_coordinator::maybe_start_tablet_resize_finalization(group0
|
||||
co_return false;
|
||||
}
|
||||
|
||||
auto resize_finalization_transition_state = [this] {
|
||||
return _db.features().tablet_merge ? topology::transition_state::tablet_resize_finalization : topology::transition_state::tablet_split_finalization;
|
||||
};
|
||||
|
||||
std::vector<canonical_mutation> updates;
|
||||
|
||||
updates.emplace_back(
|
||||
topology_mutation_builder(guard.write_timestamp())
|
||||
.set_transition_state(topology::transition_state::tablet_resize_finalization)
|
||||
.set_transition_state(resize_finalization_transition_state())
|
||||
.set_version(_topo_sm._topology.version + 1)
|
||||
.build());
|
||||
|
||||
|
||||
@@ -148,6 +148,7 @@ static std::unordered_map<topology::transition_state, sstring> transition_state_
|
||||
{topology::transition_state::write_both_read_old, "write both read old"},
|
||||
{topology::transition_state::write_both_read_new, "write both read new"},
|
||||
{topology::transition_state::tablet_migration, "tablet migration"},
|
||||
{topology::transition_state::tablet_split_finalization, "tablet split finalization"},
|
||||
{topology::transition_state::tablet_resize_finalization, "tablet resize finalization"},
|
||||
{topology::transition_state::tablet_draining, "tablet draining"},
|
||||
{topology::transition_state::left_token_ring, "left token ring"},
|
||||
@@ -156,21 +157,12 @@ static std::unordered_map<topology::transition_state, sstring> transition_state_
|
||||
{topology::transition_state::lock, "lock"},
|
||||
};
|
||||
|
||||
// Allows old deprecated names to be recognized and point to the correct transition.
|
||||
static std::unordered_map<sstring, topology::transition_state> deprecated_name_to_transition_state = {
|
||||
{"tablet split finalization", topology::transition_state::tablet_resize_finalization},
|
||||
};
|
||||
|
||||
topology::transition_state transition_state_from_string(const sstring& s) {
|
||||
for (auto&& e : transition_state_to_name_map) {
|
||||
if (e.second == s) {
|
||||
return e.first;
|
||||
}
|
||||
}
|
||||
auto it = deprecated_name_to_transition_state.find(s);
|
||||
if (it != deprecated_name_to_transition_state.end()) {
|
||||
return it->second;
|
||||
}
|
||||
on_internal_error(tsmlogger, format("cannot map name {} to transition_state", s));
|
||||
}
|
||||
|
||||
|
||||
@@ -117,6 +117,7 @@ struct topology {
|
||||
write_both_read_new,
|
||||
tablet_migration,
|
||||
tablet_resize_finalization,
|
||||
tablet_split_finalization, // deprecated in favor of tablet_resize_finalization, kept for backward compatibility.
|
||||
left_token_ring,
|
||||
rollback_to_normal,
|
||||
truncate_table,
|
||||
|
||||
@@ -3490,7 +3490,7 @@ SEASTAR_TEST_CASE(test_explicit_tablets_disable) {
|
||||
|
||||
SEASTAR_TEST_CASE(test_recognition_of_deprecated_name_for_resize_transition) {
|
||||
using transition_state = service::topology::transition_state;
|
||||
BOOST_REQUIRE_EQUAL(service::transition_state_from_string("tablet split finalization"), transition_state::tablet_resize_finalization);
|
||||
BOOST_REQUIRE_EQUAL(service::transition_state_from_string("tablet split finalization"), transition_state::tablet_split_finalization);
|
||||
BOOST_REQUIRE_EQUAL(service::transition_state_from_string("tablet resize finalization"), transition_state::tablet_resize_finalization);
|
||||
return make_ready_future<>();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user