migration_manager: also reload schema on enabling digest_insensitive_to_expiry

Currently, when said feature is enabled, we recalcuate the schema
digest. But this feature also influences how table versions are
calculated, so it has to trigger a recalculation of all table versions,
so that we can guarantee correct versions.
Before, this used to happen by happy accident. Another feature --
table_digest_insensitive_to_expiry -- used to take care of this, by
triggering a table version recalulation. However this feature only takes
effect if digest_insensitive_to_expiry is also enabled. This used to be
the case incidently, by the time the reload triggered by
table_digest_insensitive_to_expiry ran, digest_insensitive_to_expiry was
already enabled. But this was not guaranteed whatsoever and as we've
recently seen, any change to the feature list, which changes the order
in which features are enabled, can cause this intricate balance to
break.
This patch makes digest_insensitive_to_expiry also kick off a schema
reload, to eliminate our dependence on (unguaranteed) feature order, and
to guarantee that table schemas have a correct version after all features
are enabled. In fact, all schema feature notification handlers now kick
off a full schema reload, to ensure bugs like this don't creep in, in
the future.

Fixes: #16004

Closes scylladb/scylladb#16013

(cherry picked from commit 22381441b0)
(cherry picked from commit e31f2224f5)
This commit is contained in:
Botond Dénes
2023-11-09 05:30:36 -05:00
committed by Tomasz Grabiec
parent 2ea211db69
commit c9fa077c82

View File

@@ -86,27 +86,26 @@ future<> migration_manager::drain()
void migration_manager::init_messaging_service()
{
auto update_schema = [this] {
//FIXME: future discarded.
(void)with_gate(_background_tasks, [this] {
mlogger.debug("features changed, recalculating schema version");
return db::schema_tables::recalculate_schema_version(_sys_ks, _storage_proxy.container(), _feat);
auto reload_schema_in_bg = [this] {
(void) with_gate(_background_tasks, [this] {
return reload_schema().handle_exception([] (std::exception_ptr ep) {
// Due to features being unordered, reload might fail because
// some tables still have the wrong version and looking up e.g.
// the base-table of a view will fail.
mlogger.debug("Failed to reload schema: {}", ep);
});
});
};
if (this_shard_id() == 0) {
_feature_listeners.push_back(_feat.view_virtual_columns.when_enabled(update_schema));
_feature_listeners.push_back(_feat.digest_insensitive_to_expiry.when_enabled(update_schema));
_feature_listeners.push_back(_feat.cdc.when_enabled(update_schema));
_feature_listeners.push_back(_feat.per_table_partitioners.when_enabled(update_schema));
_feature_listeners.push_back(_feat.computed_columns.when_enabled(update_schema));
_feature_listeners.push_back(_feat.view_virtual_columns.when_enabled(reload_schema_in_bg));
_feature_listeners.push_back(_feat.digest_insensitive_to_expiry.when_enabled(reload_schema_in_bg));
_feature_listeners.push_back(_feat.cdc.when_enabled(reload_schema_in_bg));
_feature_listeners.push_back(_feat.per_table_partitioners.when_enabled(reload_schema_in_bg));
_feature_listeners.push_back(_feat.computed_columns.when_enabled(reload_schema_in_bg));
if (!_feat.table_digest_insensitive_to_expiry) {
_feature_listeners.push_back(_feat.table_digest_insensitive_to_expiry.when_enabled([this] {
(void) with_gate(_background_tasks, [this] {
return reload_schema();
});
}));
_feature_listeners.push_back(_feat.table_digest_insensitive_to_expiry.when_enabled(reload_schema_in_bg));
}
}