This allows the user of `raft::server` to cause it to create a snapshot and truncate the Raft log (leaving no trailing entries; in the future we may extend the API to specify number of trailing entries left if needed). In a later commit we'll add a REST endpoint to Scylla to trigger group 0 snapshots. One use case for this API is to create group 0 snapshots in Scylla deployments which upgraded to Raft in version 5.2 and started with an empty Raft log with no snapshot at the beginning. This causes problems, e.g. when a new node bootstraps to the cluster, it will not receive a snapshot that would contain both schema and group 0 history, which would then lead to inconsistent schema state and trigger assertion failures as observed in scylladb/scylladb#16683. In 5.4 the logic of initial group 0 setup was changed to start the Raft log with a snapshot at index 1 (ff386e7a44) but a problem remains with these existing deployments coming from 5.2, we need a way to trigger a snapshot in them (other than performing 1000 arbitrary schema changes). Another potential use case in the future would be to trigger snapshots based on external memory pressure in tablet Raft groups (for strongly consistent tables). The PR adds the API to `raft::server` and a HTTP endpoint that uses it. In a follow-up PR, we plan to modify group 0 server startup logic to automatically call this API if it sees that no snapshot is present yet (to automatically fix the aforementioned 5.2 deployments once they upgrade.) Closes scylladb/scylladb#16816 * github.com:scylladb/scylladb: raft: remove `empty()` from `fsm_output` test: add test for manual triggering of Raft snapshots api: add HTTP endpoint to trigger Raft snapshots raft: server: add `trigger_snapshot` API raft: server: track last persisted snapshot descriptor index raft: server: framework for handling server requests raft: server: inline `poll_fsm_output` raft: server: fix indentation raft: server: move `io_fiber`'s processing of `batch` to a separate function raft: move `poll_output()` from `fsm` to `server` raft: move `_sm_events` from `fsm` to `server` raft: fsm: remove constructor used only in tests raft: fsm: move trace message from `poll_output` to `has_output` raft: fsm: extract `has_output()` raft: pass `max_trailing_entries` through `fsm_output` to `store_snapshot_descriptor` raft: server: pass `*_aborted` to `set_exception` call (cherry picked from commitd202d32f81) Backport note: the HTTP API is only started if raft_group_registry is started.
125 lines
4.3 KiB
C++
125 lines
4.3 KiB
C++
/*
|
|
* Copyright 2016 ScylaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
#pragma once
|
|
|
|
#include <seastar/http/httpd.hh>
|
|
#include <seastar/core/future.hh>
|
|
|
|
#include "replica/database_fwd.hh"
|
|
#include "tasks/task_manager.hh"
|
|
#include "seastarx.hh"
|
|
|
|
using request = http::request;
|
|
using reply = http::reply;
|
|
|
|
namespace service {
|
|
|
|
class load_meter;
|
|
class storage_proxy;
|
|
class storage_service;
|
|
class raft_group0_client;
|
|
class raft_group_registry;
|
|
|
|
} // namespace service
|
|
|
|
class sstables_loader;
|
|
|
|
namespace streaming {
|
|
class stream_manager;
|
|
}
|
|
|
|
namespace locator {
|
|
|
|
class token_metadata;
|
|
class shared_token_metadata;
|
|
class snitch_ptr;
|
|
|
|
} // namespace locator
|
|
|
|
namespace cql_transport { class controller; }
|
|
class thrift_controller;
|
|
namespace db {
|
|
class snapshot_ctl;
|
|
class config;
|
|
namespace view {
|
|
class view_builder;
|
|
}
|
|
class system_keyspace;
|
|
}
|
|
namespace netw { class messaging_service; }
|
|
class repair_service;
|
|
|
|
namespace gms {
|
|
|
|
class gossiper;
|
|
|
|
}
|
|
|
|
namespace auth { class service; }
|
|
|
|
namespace api {
|
|
|
|
struct http_context {
|
|
sstring api_dir;
|
|
sstring api_doc;
|
|
httpd::http_server_control http_server;
|
|
distributed<replica::database>& db;
|
|
service::load_meter& lmeter;
|
|
const sharded<locator::shared_token_metadata>& shared_token_metadata;
|
|
sharded<tasks::task_manager>& tm;
|
|
|
|
http_context(distributed<replica::database>& _db,
|
|
service::load_meter& _lm, const sharded<locator::shared_token_metadata>& _stm, sharded<tasks::task_manager>& _tm)
|
|
: db(_db), lmeter(_lm), shared_token_metadata(_stm), tm(_tm) {
|
|
}
|
|
|
|
const locator::token_metadata& get_token_metadata();
|
|
};
|
|
|
|
future<> set_server_init(http_context& ctx);
|
|
future<> set_server_config(http_context& ctx, const db::config& cfg);
|
|
future<> set_server_snitch(http_context& ctx, sharded<locator::snitch_ptr>& snitch);
|
|
future<> unset_server_snitch(http_context& ctx);
|
|
future<> set_server_storage_service(http_context& ctx, sharded<service::storage_service>& ss, service::raft_group0_client&);
|
|
future<> unset_server_storage_service(http_context& ctx);
|
|
future<> set_server_sstables_loader(http_context& ctx, sharded<sstables_loader>& sst_loader);
|
|
future<> unset_server_sstables_loader(http_context& ctx);
|
|
future<> set_server_view_builder(http_context& ctx, sharded<db::view::view_builder>& vb);
|
|
future<> unset_server_view_builder(http_context& ctx);
|
|
future<> set_server_repair(http_context& ctx, sharded<repair_service>& repair);
|
|
future<> unset_server_repair(http_context& ctx);
|
|
future<> set_transport_controller(http_context& ctx, cql_transport::controller& ctl);
|
|
future<> unset_transport_controller(http_context& ctx);
|
|
future<> set_rpc_controller(http_context& ctx, thrift_controller& ctl);
|
|
future<> unset_rpc_controller(http_context& ctx);
|
|
future<> set_server_authorization_cache(http_context& ctx, sharded<auth::service> &auth_service);
|
|
future<> unset_server_authorization_cache(http_context& ctx);
|
|
future<> set_server_snapshot(http_context& ctx, sharded<db::snapshot_ctl>& snap_ctl);
|
|
future<> unset_server_snapshot(http_context& ctx);
|
|
future<> set_server_gossip(http_context& ctx, sharded<gms::gossiper>& g);
|
|
future<> set_server_load_sstable(http_context& ctx, sharded<db::system_keyspace>& sys_ks);
|
|
future<> unset_server_load_sstable(http_context& ctx);
|
|
future<> set_server_messaging_service(http_context& ctx, sharded<netw::messaging_service>& ms);
|
|
future<> unset_server_messaging_service(http_context& ctx);
|
|
future<> set_server_storage_proxy(http_context& ctx, sharded<service::storage_proxy>& proxy);
|
|
future<> unset_server_storage_proxy(http_context& ctx);
|
|
future<> set_server_stream_manager(http_context& ctx, sharded<streaming::stream_manager>& sm);
|
|
future<> unset_server_stream_manager(http_context& ctx);
|
|
future<> set_hinted_handoff(http_context& ctx, sharded<service::storage_proxy>& p);
|
|
future<> unset_hinted_handoff(http_context& ctx);
|
|
future<> set_server_gossip_settle(http_context& ctx, sharded<gms::gossiper>& g);
|
|
future<> set_server_cache(http_context& ctx);
|
|
future<> set_server_compaction_manager(http_context& ctx);
|
|
future<> set_server_done(http_context& ctx);
|
|
future<> set_server_task_manager(http_context& ctx, lw_shared_ptr<db::config> cfg);
|
|
future<> set_server_task_manager_test(http_context& ctx);
|
|
future<> set_server_raft(http_context&, sharded<service::raft_group_registry>&);
|
|
future<> unset_server_raft(http_context&);
|
|
|
|
}
|