From 504435444c65efc59c0f7c6881991296258538a7 Mon Sep 17 00:00:00 2001 From: tv Date: Mon, 26 Oct 2026 05:35:40 +0100 Subject: allow humand-friendly durations in API --- src/remake/api.rs | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'src/remake/api.rs') diff --git a/src/remake/api.rs b/src/remake/api.rs index 41d72ad..f5063e0 100644 --- a/src/remake/api.rs +++ b/src/remake/api.rs @@ -19,11 +19,12 @@ //! Request body for POST (all optional; `baseHeads` not for `compact`, whose base is //! fixed when it commits): //! `{ "kind": "compact", "spec": null, "baseHeads": ["", …], -//! "replayWindow": {"epochs": 1, "seconds": 604800}, -//! "archiveRetention": {"epochs": 2, "seconds": 2592000}, +//! "replayWindow": {"epochs": 1, "age": "7d"}, +//! "archiveRetention": {"epochs": 2, "age": "30d"}, //! "settle": "8m", "switchDelay": "1m" }` //! -//! `settle` and `switchDelay` are durations (`units`: seconds, or e.g. `500ms`, `8m`). +//! `settle`, `switchDelay` and the retentions' `age` are durations (`units`: seconds, +//! or e.g. `500ms`, `8m`, `7d`). //! //! `?force=` overrides checks: `true` all of them, or a comma-separated list of //! * `switchDelay`: accept one below a keepalive interval (for tests and debugging, @@ -164,8 +165,8 @@ struct StartRequest { /// them are carried over. The current heads if absent. For a remake derived from /// a read, use the heads that read returned (`GET /store?heads=true`). base_heads: Option>, - replay_window: Option, - archive_retention: Option, + replay_window: Option, + archive_retention: Option, /// How long votes are collected; twice the dormancy threshold if absent. #[serde(default, with = "crate::units::optional_duration")] settle: Option, @@ -175,6 +176,26 @@ struct StartRequest { switch_delay: Option, } +/// A retention as a request gives it: the age as a duration. +#[derive(Debug, Default, Deserialize)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +struct RetentionRequest { + epochs: Option, + #[serde(default, with = "crate::units::optional_duration")] + age: Option, +} + +impl From for Retention { + fn from(request: RetentionRequest) -> Self { + Retention { + epochs: request.epochs, + age_ms: request + .age + .map(|age| u64::try_from(age.as_millis()).unwrap_or(u64::MAX)), + } + } +} + /// What `?force=` may override on a proposal (`force`). const FORCE: &[&str] = &["switchDelay", "supersede", "coordinatorActive"]; /// What `?force=` may override on an abort. @@ -488,10 +509,10 @@ async fn start_kind( policy: Policy { replay_window: request .replay_window - .unwrap_or_else(Policy::default_replay_window), + .map_or_else(Policy::default_replay_window, Retention::from), archive_retention: request .archive_retention - .unwrap_or_else(Policy::default_archive_retention), + .map_or_else(Policy::default_archive_retention, Retention::from), }, settle_ms, proposed_at: now, -- cgit v1.3.1