diff options
| author | tv <tv@krebsco.de> | 2026-10-31 12:14:12 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-31 12:14:12 +0100 |
| commit | 7bedbda025f03fd5dfca833171c55867d8c0478e (patch) | |
| tree | 81951cc1de4019283ba8a7c1abf08bcafe64b7d9 /src/remake/api.rs | |
| parent | 210e40178082f485d46bdcdaaf433356f7c9919a (diff) | |
remake needs sane clock
Diffstat (limited to 'src/remake/api.rs')
| -rw-r--r-- | src/remake/api.rs | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/src/remake/api.rs b/src/remake/api.rs index f919be7..75d0294 100644 --- a/src/remake/api.rs +++ b/src/remake/api.rs @@ -32,6 +32,8 @@ //! not for real swarms); //! * `supersede`: abort expired remakes of this epoch and propose in their place. //! Without it, an expired remake still holding votes answers `409`; +//! * `clock`: propose although this node's clock is off from its peers' +//! (`swarm::skew`): it would judge the remake's deadlines wrongly. Without it, `409`; //! * for `DELETE`: `coordinatorActive` (abort an expired remake whose coordinator this //! node sees as active) and `coordinatorInactive` (ask for an abort of an undecided //! one whose coordinator this node doesn't reach). @@ -200,7 +202,7 @@ impl From<RetentionRequest> for Retention { } /// What `?force=` may override on a proposal (`force`). -const FORCE: &[&str] = &["switchDelay", "supersede", "coordinatorActive"]; +const FORCE: &[&str] = &["switchDelay", "supersede", "coordinatorActive", "clock"]; /// What `?force=` may override on an abort. const ABORT_FORCE: &[&str] = &["coordinatorActive", "coordinatorInactive"]; @@ -295,6 +297,21 @@ async fn start_kind<H: Host>( Ok(force) => force, Err(reason) => return error_response(StatusCode::BAD_REQUEST, reason, None), }; + // The coordinator stamps and judges the voting period and the deadlines by its + // clock (`trust.md`, "What depends on clocks"). + let skew = host.clock_skew().await; + if skew.off && !force.allows("clock") { + let offset = skew.offset_ms.unwrap_or(0); + return error_response( + StatusCode::CONFLICT, + format!( + "this node's clock is {} {} most of its peers' (more than --clock-skew-warn), so it would judge the remake's deadlines wrongly; fix its time synchronisation, or add ?force=clock", + crate::units::format_duration(Duration::from_millis(offset.unsigned_abs())), + if offset < 0 { "behind" } else { "ahead of" } + ), + Some(json!({ "force": "clock" })), + ); + } let request: StartRequest = if is_octet_stream(headers) { match query.import_request(&body) { |
