The three documents every device shares and the household's hub holds the master copy of: what Whiskers remembers, the grown-ups' choices with the day's time, and the one running chat.
A hub is not get/put. A device does not fetch the master copy, change it and write it back;
it hands over what it knows and is given what the hub now knows. That one verb, merge, is the
whole write side, and the adapter must make it atomic in whatever way its platform allows (a mutex
and an atomic file replace natively; a Durable Object's single thread of execution in a Worker).
A get/put pair would make atomicity every caller's problem and every adapter's silent gap: two
devices syncing at once would each read, merge locally and write, and one would lose.
The merge rule is not the adapter's either. It is a pure function of the two documents that
lives in whiskers-core (MemoryDoc::merge, Household::merge, ChatState::merge), so every
backend converges to the same document and the adapter only decides where the result is kept.
15use whiskers_core::{ChatState, Household, MemorySnapshot};
17use crate::error::StoreError;
The hub's document once theirs is in: what the caller should now hold.
23 pub document: D,
How much of the hub's document changed because of this merge. Zero means the hub already held everything the caller sent, so repeating the same merge must always report zero.
A convergent document held by the household's hub.
Contract, for every adapter (the conformance suite in whiskers-conformance asserts it):
- Atomic. Two merges, however they overlap, behave as if one ran entirely before the other.
- Convergent. Merging the same set of documents in any order gives the same document (up to the hub's own numbering, which is not part of the document's meaning), and merging one in a second time changes nothing.
- Durable once it returns. A merge that reported
Oksurvives the hub restarting. A merge that reportedErrleft the stored document as it was, andcurrentreports that document too: an adapter keeps a copy before it adopts it, never the other way round.
Takes theirs in and returns the hub's document as it now stands.
45 async fn merge(&self, theirs: Self::Document) -> Result<Merged<Self::Document>, StoreError>;
The hub's document as it stands, changing nothing. For decisions that read a choice (the
token window, the voice allowance) and never for a read-modify-write: that is merge.
What Whiskers remembers. The document on the wire is a snapshot: facts and the identities of those the parents forgot (a forgotten fact wins over its own copy on any device).
The grown-ups' choices and the day's time.