forked from scylladb/scylladb
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge 'Add an API to trigger snapshot in Raft servers' from Kamil Braun
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#16683. In 5.4 the logic of initial group 0 setup was changed to start the Raft log with a snapshot at index 1 (ff386e7) 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#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 commit d202d32) Backport note: the HTTP API is only started if raft_group_registry is started.
- Loading branch information
1 parent
e83c4cc
commit 26b8120
Showing
17 changed files
with
597 additions
and
200 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
{ | ||
"apiVersion":"0.0.1", | ||
"swaggerVersion":"1.2", | ||
"basePath":"{{Protocol}}://{{Host}}", | ||
"resourcePath":"/raft", | ||
"produces":[ | ||
"application/json" | ||
], | ||
"apis":[ | ||
{ | ||
"path":"/raft/trigger_snapshot/{group_id}", | ||
"operations":[ | ||
{ | ||
"method":"POST", | ||
"summary":"Triggers snapshot creation and log truncation for the given Raft group", | ||
"type":"string", | ||
"nickname":"trigger_snapshot", | ||
"produces":[ | ||
"application/json" | ||
], | ||
"parameters":[ | ||
{ | ||
"name":"group_id", | ||
"description":"The ID of the group which should get snapshotted", | ||
"required":true, | ||
"allowMultiple":false, | ||
"type":"string", | ||
"paramType":"path" | ||
}, | ||
{ | ||
"name":"timeout", | ||
"description":"Timeout in seconds after which the endpoint returns a failure. If not provided, 60s is used.", | ||
"required":false, | ||
"allowMultiple":false, | ||
"type":"long", | ||
"paramType":"query" | ||
} | ||
] | ||
} | ||
] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* Copyright (C) 2024-present ScyllaDB | ||
*/ | ||
|
||
/* | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
#include <seastar/core/coroutine.hh> | ||
|
||
#include "api/api.hh" | ||
#include "api/api-doc/raft.json.hh" | ||
|
||
#include "service/raft/raft_group_registry.hh" | ||
|
||
using namespace seastar::httpd; | ||
|
||
extern logging::logger apilog; | ||
|
||
namespace api { | ||
|
||
namespace r = httpd::raft_json; | ||
using namespace json; | ||
|
||
void set_raft(http_context&, httpd::routes& r, sharded<service::raft_group_registry>& raft_gr) { | ||
r::trigger_snapshot.set(r, [&raft_gr] (std::unique_ptr<http::request> req) -> future<json_return_type> { | ||
raft::group_id gid{utils::UUID{req->param["group_id"]}}; | ||
auto timeout_dur = std::invoke([timeout_str = req->get_query_param("timeout")] { | ||
if (timeout_str.empty()) { | ||
return std::chrono::seconds{60}; | ||
} | ||
auto dur = std::stoll(timeout_str); | ||
if (dur <= 0) { | ||
throw std::runtime_error{"Timeout must be a positive number."}; | ||
} | ||
return std::chrono::seconds{dur}; | ||
}); | ||
|
||
std::atomic<bool> found_srv{false}; | ||
co_await raft_gr.invoke_on_all([gid, timeout_dur, &found_srv] (service::raft_group_registry& raft_gr) -> future<> { | ||
auto* srv = raft_gr.find_server(gid); | ||
if (!srv) { | ||
co_return; | ||
} | ||
|
||
found_srv = true; | ||
abort_on_expiry aoe(lowres_clock::now() + timeout_dur); | ||
apilog.info("Triggering Raft group {} snapshot", gid); | ||
auto result = co_await srv->trigger_snapshot(&aoe.abort_source()); | ||
if (result) { | ||
apilog.info("New snapshot for Raft group {} created", gid); | ||
} else { | ||
apilog.info("Could not create new snapshot for Raft group {}, no new entries applied", gid); | ||
} | ||
}); | ||
|
||
if (!found_srv) { | ||
throw std::runtime_error{fmt::format("Server for group ID {} not found", gid)}; | ||
} | ||
|
||
co_return json_void{}; | ||
}); | ||
} | ||
|
||
void unset_raft(http_context&, httpd::routes& r) { | ||
r::trigger_snapshot.unset(r); | ||
} | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* | ||
* Copyright (C) 2023-present ScyllaDB | ||
*/ | ||
|
||
/* | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include "api_init.hh" | ||
|
||
namespace api { | ||
|
||
void set_raft(http_context& ctx, httpd::routes& r, sharded<service::raft_group_registry>& raft_gr); | ||
void unset_raft(http_context& ctx, httpd::routes& r); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.