diff options
| author | tv <tv@krebsco.de> | 2026-10-21 04:08:26 +0200 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-21 04:08:26 +0200 |
| commit | c9559af92ba2e3d27188d0a8efd1861180613840 (patch) | |
| tree | ccbe7d41607cebff29002b9080d448549b100a38 /src/remake/quarantine.rs | |
| parent | 812eb0b3b714a16584c058de4b6a1de84a8e8dd7 (diff) | |
turn compaction into a kind of remake
Diffstat (limited to 'src/remake/quarantine.rs')
| -rw-r--r-- | src/remake/quarantine.rs | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/src/remake/quarantine.rs b/src/remake/quarantine.rs index 5643549..deed8cd 100644 --- a/src/remake/quarantine.rs +++ b/src/remake/quarantine.rs @@ -14,6 +14,7 @@ use std::convert::Infallible; +use automerge::AutoCommit; use axum::{ extract::{Path, State}, http::{header, StatusCode}, @@ -22,12 +23,16 @@ use axum::{ }; use serde::Serialize; use serde_json::{json, Value as JsonValue}; -use tracing::info; +use tracing::{info, warn}; +use uuid::Uuid; use super::api::error_response; use super::delta; +use super::kind::Translator; use super::local::Quarantined; +use super::records::unix_millis; use super::Host; +use crate::document::replica::Epoch; use crate::document::store; #[derive(Debug, Serialize)] @@ -58,6 +63,41 @@ fn not_found() -> Response { error_response(StatusCode::NOT_FOUND, "no such quarantine entry", None) } +/// Puts writes a remake had no place for into quarantine, with `document` (the old +/// epoch's) to read them from. Returns the entry's ID, or None if there is nothing. +pub(super) fn add<H: Host>( + host: &H, + epoch: Epoch, + target: Epoch, + document: &AutoCommit, + quarantined: Vec<(Vec<String>, String)>, +) -> Option<String> { + if quarantined.is_empty() { + return None; + } + let mut reasons: Vec<&str> = quarantined + .iter() + .map(|(_, reason)| reason.as_str()) + .collect(); + reasons.sort_unstable(); + reasons.dedup(); + let reason = reasons.join("; "); + let paths: Vec<Vec<String>> = quarantined.into_iter().map(|(path, _)| path).collect(); + + let id = Uuid::new_v4().to_string(); + warn!(quarantine = %id, epoch = %epoch, paths = paths.len(), reason = %reason, "Quarantined writes the remake has no place for"); + host.remake().add_quarantine(Quarantined { + id: id.clone(), + epoch, + target, + created_at: unix_millis(), + reason, + paths, + document: document.clone(), + }); + Some(id) +} + pub(crate) async fn list<H: Host>(State(host): State<H>) -> Response { Json(host.remake().list_quarantine(summary)).into_response() } @@ -129,7 +169,9 @@ pub(crate) async fn replay<H: Host>(State(host): State<H>, Path(id): Path<String let (stats, entry) = host .commit_doc(move |doc| { - let stats = delta::replay_paths(&entry.document, doc, &entry.paths); + // As they are: the operator decided they belong at their old paths. + let stats = + delta::replay_paths(&entry.document, doc, &entry.paths, &Translator::default()); Ok::<_, Infallible>((stats, entry)) }) .await |
