diff options
| author | tv <tv@krebsco.de> | 2026-10-26 20:47:15 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-26 20:47:15 +0100 |
| commit | 53baaff5d7c1c9fd62cf0e94bcb86120edd699b6 (patch) | |
| tree | f2904948a02fdaf1e473f686fadda135a8b7b74c /src/api | |
| parent | 88417aa0660b0766f3c75bf5846361528537e0b9 (diff) | |
permit at most one document export at a time
Diffstat (limited to 'src/api')
| -rw-r--r-- | src/api/document.rs | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/src/api/document.rs b/src/api/document.rs index 6c10c38..20bbc7b 100644 --- a/src/api/document.rs +++ b/src/api/document.rs @@ -5,6 +5,8 @@ //! it came from is in headers: `X-Continuum-Swarm`, `X-Continuum-Epoch` //! (`<generation>:<id hex>`) and `X-Continuum-Heads` (hex, comma-separated). +use std::sync::atomic::{AtomicBool, Ordering}; + use axum::{ extract::State, http::{HeaderName, HeaderValue, StatusCode, header}, @@ -15,10 +17,31 @@ use tracing::{info, warn}; use crate::state::AppState; +/// An export in progress: each holds a copy of the whole document and its saved bytes, +/// so one at a time. +static EXPORTING: AtomicBool = AtomicBool::new(false); + +/// Clears `EXPORTING` when the export ends, however it ends. +struct Exporting; + +impl Drop for Exporting { + fn drop(&mut self) { + EXPORTING.store(false, Ordering::Release); + } +} + pub(crate) async fn get_document(State(state): State<AppState>) -> Response { if !state.is_ready().await { return (StatusCode::SERVICE_UNAVAILABLE, "node is not ready\n").into_response(); } + if EXPORTING.swap(true, Ordering::AcqRel) { + return ( + StatusCode::TOO_MANY_REQUESTS, + "another export is in progress; try again when it is done\n", + ) + .into_response(); + } + let _exporting = Exporting; let swarm_id = state.swarm_id().await.unwrap_or_default(); let start = Instant::now(); |
