diff options
| author | tv <tv@krebsco.de> | 2026-11-01 19:35:20 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-01 19:35:20 +0100 |
| commit | 1f3be9d059876f7f3994056b1ac8ce307628a52a (patch) | |
| tree | 8f1ca7e7d4b5c1b317d6191b44f0c580aa90acbc /src/state/read.rs | |
| parent | a9838a756fa7730e887598592a2f1b5b294e68a7 (diff) | |
document: allow writes during rejoin
Diffstat (limited to 'src/state/read.rs')
| -rw-r--r-- | src/state/read.rs | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/src/state/read.rs b/src/state/read.rs index a9b3116..e325e61 100644 --- a/src/state/read.rs +++ b/src/state/read.rs @@ -1,4 +1,5 @@ -//! Serving reads: from the live document, or from the pre-rejoin copy while rejoining. +//! Serving reads: from the live document, or from the pre-rejoin document while +//! rejoining. use std::sync::Arc; @@ -7,10 +8,13 @@ use crate::document::replica::Epoch; use crate::document::{ChangeHash, Document}; use crate::locks::RwLockExt; -/// A read-only view of the document the node served before it started rejoining. +/// The document the node served before it started rejoining, of the epoch it left: +/// reads are answered from it (marked stale), and writes go into it +/// (`AppState::mutate_doc`), until the rejoin replays them into the new epoch or +/// restores this document (`Host::finish_rejoin`, `Host::abandon_rejoin`). pub(crate) struct StaleView { pub(crate) epoch: Epoch, - pub(crate) doc: Arc<Document>, + pub(crate) doc: Arc<std::sync::RwLock<Document>>, } /// Where a read was served from. @@ -57,9 +61,12 @@ impl AppState { return Err(axum::http::StatusCode::SERVICE_UNAVAILABLE); }; - let rendered = tokio::task::spawn_blocking(move || finish(read(&doc))) - .await - .expect("document read task panicked"); + let rendered = tokio::task::spawn_blocking(move || { + let data = read(&doc.read_or_recover()); + finish(data) + }) + .await + .expect("document read task panicked"); Ok((rendered, ReadSource::Stale(epoch), None)) } @@ -93,4 +100,12 @@ impl AppState { pub(super) fn set_stale(&self, view: Option<StaleView>) { *self.stale.write_or_recover() = view; } + + /// The stale view's document and epoch, if there is one. + pub(crate) fn stale_document(&self) -> Option<(Epoch, Arc<std::sync::RwLock<Document>>)> { + self.stale + .read_or_recover() + .as_ref() + .map(|view| (view.epoch, Arc::clone(&view.doc))) + } } |
