diff options
| author | tv <tv@krebsco.de> | 2026-10-24 18:18:29 +0200 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-24 18:18:29 +0200 |
| commit | 09f2dfd083c4fcdce4c5ca7376353906eb025c42 (patch) | |
| tree | e13141f10e3854408bd70d18d1bf31581abe5458 /src/remake/api.rs | |
| parent | 371e52cb48bae99232547f6fae6a0487a85c2d04 (diff) | |
put remake content into blobs
Diffstat (limited to 'src/remake/api.rs')
| -rw-r--r-- | src/remake/api.rs | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/src/remake/api.rs b/src/remake/api.rs index de8166c..3345086 100644 --- a/src/remake/api.rs +++ b/src/remake/api.rs @@ -29,8 +29,9 @@ //! `{ "document": {…store root…}, "rules": [{"from": "a", "to": "b"}, {"from": "c", "drop": true}] }` //! (see `kind::Replace`), or `import`, whose spec is //! `{ "document": "<base64 of an Automerge document>", "rules": […] }` (see -//! `kind::Import`; `GET /admin/document` exports one). Reports leave the document out -//! (`contentBytes`). Requests may be up to 64 MiB. +//! `kind::Import`; `GET /admin/document` exports one). The document stays on the +//! coordinator; the proposal refers to it by hash (`proposal.content`), and every voter +//! downloads it (`content`). Requests may be up to 64 MiB. //! //! An import can also be uploaded as is, with `Content-Type: application/octet-stream`; //! then `rules` (JSON), `baseHeads` (comma-separated), `settleSecs` and @@ -61,7 +62,8 @@ use uuid::Uuid; use super::coordinator; use super::local::LocalStatus; use super::records::{ - self, AbortRequest, EpochRecord, Phase, Policy, Proposal, Record, Retention, Vote, unix_millis, + self, AbortRequest, ContentRef, EpochRecord, Phase, Policy, Proposal, Record, Retention, Vote, + unix_millis, }; use super::{Host, kind, vote}; use crate::document::store::StoreError; @@ -160,10 +162,6 @@ struct Report { phase: Phase, #[serde(flatten)] record: Record, - /// Size of the kind's build input (e.g. a replacement document), which reports - /// leave out. - #[serde(skip_serializing_if = "Option::is_none")] - content_bytes: Option<usize>, /// What happened to this remake on the node answering the request. #[serde(skip_serializing_if = "Option::is_none")] local: Option<LocalStatus>, @@ -195,12 +193,10 @@ fn grace<H: Host>(host: &H) -> u64 { host.dormant_after().as_millis() as u64 } -fn report<H: Host>(host: &H, id: String, mut record: Record) -> Report { - let content = std::mem::take(&mut record.proposal.content); +fn report<H: Host>(host: &H, id: String, record: Record) -> Report { Report { phase: record.phase(unix_millis(), grace(host)), local: host.remake().status(&id), - content_bytes: (!content.is_null()).then(|| content.to_string().len()), id, record, } @@ -394,7 +390,7 @@ async fn start_kind<H: Host>( let id = Uuid::new_v4().to_string(); let grace = grace(&host); - let proposal = Proposal { + let mut proposal = Proposal { coordinator: host.node_id(), from_epoch: host.current_epoch().into(), base_heads: Vec::new(), @@ -414,9 +410,17 @@ async fn start_kind<H: Host>( electorate: Vec::new(), quorum: 0, kind: kind.name().to_owned(), - content: prepared.content, + content: None, translation: prepared.translation, }; + // The content stays here, referred to by hash; voters fetch it from us. + if let Some(bytes) = prepared.content { + let reference = ContentRef::of(&bytes); + if let Some(hash) = reference.hash() { + host.remake().put_content(hash, std::sync::Arc::new(bytes)); + } + proposal.content = Some(reference); + } // From here on, nothing depends on the client: writing the proposal and starting the // coordinator run in their own task, so a client that disconnects mid-request can't |
