calternal_collab::history::write
Shared admission and batching for Canvas and Notes (DESIGN §60–61, #975).
Consecutive updates by one author merge for at most one second. A foreign edit closes that batch: grouping all of an author’s edits across foreign edits would change the history order and break selective undo. The queue retains failed appends and bounds pending memory. Files quota reservations cover pending writes, and durable Index counters survive process restarts.
Source: crates/calternal-collab/src/history/write.rs
Structs
Section titled “Structs”Admission
Section titled “Admission”pub struct AdmissionHolds admission through the document mutation. Dropping a rejected or unchanged update releases pending quota; the decode budget stays charged.
Implements: Drop
Admission::commit
Section titled “Admission::commit”pub fn commit(mut self, update_v1: &[u8], at_ms: i64) -> Result<()>Capture the accepted v1 update before the server broadcasts it. Store failures happen at flush and cannot silently discard this queued update.
Source: crates/calternal-collab/src/history/write.rs:312
ClientBindings
Section titled “ClientBindings”pub struct ClientBindingsClient IDs are connection-owned, while their author survives reconnects. Existing foreign structs may be echoed in sync; only new clocks are claims.
Implements: Default
ClientBindings::unbound_presence
Section titled “ClientBindings::unbound_presence”pub fn unbound_presence(&self, announced: &[ClientID]) -> Vec<ClientID>Only first presence needs an Index lookup. Later cursor updates use the active connection map and cause no history or Security-state write.
ClientBindings::claim
Section titled “ClientBindings::claim”pub fn claim( &mut self, connection: u64, author: &Author, server: ClientID, live: &impl ReadTxn, updates: &[Vec<u8>], announced: &[ClientID], ) -> Result<Vec<(ClientID, Option<Author>)>>Validate all IDs before inserting claims, so a refused mixed update cannot steal fresh IDs. Server IDs are never client-writable (#975).
ClientBindings::release
Section titled “ClientBindings::release”pub fn release(&mut self, connection: u64)Release active ownership. SQL retains durable author binding; without a store, written IDs stay in memory. Presence-only claims never persist.
Source: crates/calternal-collab/src/history/write.rs:395
HistoryWriter
Section titled “HistoryWriter”pub struct HistoryWriterDocument-neutral write layer; Canvas can use the same admission and capture calls without introducing another writer or filesystem path (#975).
HistoryWriter::new
Section titled “HistoryWriter::new”pub async fn new( root: Root, db: Db, store: Arc<dyn HistoryStore>, limits: WriteLimits, ) -> Result<Arc<Self>>Install the durable budget before accepting history-enabled rooms.
HistoryWriter::seed
Section titled “HistoryWriter::seed”pub async fn seed(self: &Arc<Self>, doc: &DocKey, state_v1: &[u8], at_ms: i64) -> Result<()>Add the initial Yrs state once, before any incremental updates. The room caller serializes this with edits, so replay always has a seed.
HistoryWriter::admit
Section titled “HistoryWriter::admit”pub async fn admit( self: &Arc<Self>, doc: &DocKey, author: &Author, bytes: usize, at_ms: i64, ) -> Result<Admission>Reserve growth and daily budget before mutating a live document. Charge input bytes (including duplicate traffic), so retries cannot turn small effective updates into unbounded decode work or disk growth.
HistoryWriter::load_bindings
Section titled “HistoryWriter::load_bindings”pub async fn load_bindings(&self, doc: &DocKey, server: ClientID) -> Result<ClientBindings>Restore client ownership from Security state, not from untrusted Yjs structs. Active connection leases remain local to the loaded room.
HistoryWriter::verify_presence
Section titled “HistoryWriter::verify_presence”pub async fn verify_presence( &self, doc: &DocKey, author: &Author, clients: &[ClientID], ) -> Result<()>Presence alone cannot take an existing author’s client ID. Missing IDs stay ephemeral, so a Viewer cannot grow Security state with cursors.
HistoryWriter::persist_bindings
Section titled “HistoryWriter::persist_bindings”pub async fn persist_bindings( &self, doc: &DocKey, claims: &[(ClientID, Option<Author>)], ) -> Result<()>Commit new identity claims before applying their first update. SQL’s conflict check also refuses races between separate Hub instances.
HistoryWriter::flush
Section titled “HistoryWriter::flush”pub async fn flush(&self) -> Result<()>Drain in acceptance order. On failure keep the front batch and its quota reservation; the next flush retries it before all later batches.
Source: crates/calternal-collab/src/history/write.rs:92
WriteLimits
Section titled “WriteLimits”pub struct WriteLimitsPer-collaborator limits, independent of the owner’s Home quota (#975).
Fields
pub daily_bytes: u64pub pending_bytes: usize
Implements: Clone, Copy, Debug, Default
Source: crates/calternal-collab/src/history/write.rs:32
Functions
Section titled “Functions”migrations
Section titled “migrations”pub fn migrations() -> MigrationSetSecurity-state migration owned by collaboration, separate from Notes.
Source: crates/calternal-collab/src/history/write.rs:47
Constants
Section titled “Constants”BATCH_WINDOW
Section titled “BATCH_WINDOW”pub const BATCH_WINDOW: DurationOne-second batching is within the owner-approved 1–2 second window.