From 31dddb08e4f36392ed9b033f78efd00c243c46bb Mon Sep 17 00:00:00 2001 From: tv Date: Tue, 20 Oct 2026 01:32:12 +0200 Subject: add force param to POST /admin/compaction --- src/compaction/api.rs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'src/compaction') diff --git a/src/compaction/api.rs b/src/compaction/api.rs index a2fde13..9a77e4d 100644 --- a/src/compaction/api.rs +++ b/src/compaction/api.rs @@ -2,7 +2,8 @@ //! //! * `POST /admin/compaction` proposes a compaction of the current epoch. The receiving //! node becomes its coordinator. `202` with the report, or with `?wait=true` the final -//! report once decided. A dropped request does not abort anything. +//! report once decided. A dropped request does not abort anything. `?force=true` +//! accepts a `settleSecs` below the dormancy threshold (tests, single-site clusters). //! * `GET /admin/compactions` lists all compactions. //! * `GET /admin/compactions/{id}` reports one; `?wait=true` long-polls until decided //! (bounded by the proposal's own expiry). @@ -29,7 +30,7 @@ use axum::{ use serde::{Deserialize, Serialize}; use serde_json::{json, Value as JsonValue}; use tokio::sync::broadcast; -use tracing::{error, info}; +use tracing::{error, info, warn}; use uuid::Uuid; use super::coordinator; @@ -46,6 +47,15 @@ pub(crate) struct WaitQuery { wait: bool, } +#[derive(Debug, Default, Deserialize)] +pub(crate) struct StartQuery { + #[serde(default)] + wait: bool, + /// Allows a settle period shorter than the dormancy threshold. + #[serde(default)] + force: bool, +} + #[derive(Debug, Default, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] struct StartRequest { @@ -128,7 +138,7 @@ async fn wait_until_final(host: &H, id: &str) -> Option { pub(crate) async fn start( State(host): State, - Query(query): Query, + Query(query): Query, body: Bytes, ) -> Response { if !host.is_node_ready().await { @@ -155,11 +165,17 @@ pub(crate) async fn start( .settle_secs .map(Duration::from_secs) .unwrap_or(dormant_after * 2); - if settle < dormant_after { + if settle < dormant_after && query.force { + warn!( + settle_secs = settle.as_secs_f64(), + dormant_after_secs = dormant_after.as_secs(), + "Forced settle period shorter than the dormancy threshold; a partition may go unnoticed" + ); + } else if settle < dormant_after { return error_response( StatusCode::BAD_REQUEST, format!( - "settleSecs must be at least {} (the dormancy threshold), so a partition is detected before deciding", + "settleSecs must be at least {} (the dormancy threshold), so a partition is detected before deciding; add ?force=true to override", dormant_after.as_secs() ), None, -- cgit v1.3.1