v0.9.0-rc.29
·
46 commits
to main
since this release
subscribe_to_observer_changes now fires on tombstone-driven deletes — closes the documented "fires for ALL document changes" contract on the CDC channel. Single landed PR (peat-mesh#203) closes peat-mesh#202. Pre-rc.29 AutomergeStore::delete silently removed from disk + cache without firing any of the three broadcast channels, so a CDC consumer subscribed to the documented channel saw inserts and updates from any peer but never saw deletes from any peer. Blocked the operator-visible peat observe-with-peat delete cross-CLI flow (peat-node ADR-001 Open Question §7).
Fixed
AutomergeStore::deletefires the same broadcast pipeline asput(peat-mesh#203, closes peat-mesh#202).delete(&self, key)now routes through a newdelete_inner(key, notify, origin)private path that firesobserver_tx(CDC) +change_tx(local sync-out trigger) +gossip_tx(origin-tagged), mirroring the existingput/put_with_originchannel-gating matrix exactly. The contract repair is observable: a CDC consumer subscribed tosubscribe_to_observer_changesnow seesOk(None)fromstore.get(key)on the event when the delete originated from any source (local or remote-via-tombstone), making the "Some → insert/update, None → delete" detection pattern (peat-cli'scli/observe.rs:94-102shape) work end-to-end.
Added
AutomergeStore::delete_with_origin(&self, key, origin: ChangeOrigin)(peat-mesh#203). Mirrorsput_with_origin:ChangeOrigin::Localfireschange_tx(sync-out trigger);ChangeOrigin::Remote(peer)suppresses it per the peat-mesh#115 ping-pong invariant and tagsgossip_txwith the peer attribution for transitive-gossip drivers to skip the source.observer_txalways fires.
Changed
AutomergeSyncCoordinator::apply_tombstonenow routes the post-tombstone document removal throughdelete_with_origin(.., Remote(peer))instead of the silentdelete()call. Same observable behaviour forchange_tx(suppressed per peat-mesh#115); new observable behaviour forobserver_tx+gossip_tx(Remote(peer))— CDC consumers see remote-driven deletes; transitive-gossip pushers see the peer attribution.AutomergeStore::subscribe_to_observer_changesdoc-comment updated to reflect the post-#202 contract: explicitly lists tombstone-driven deletes among the events the channel fires, and adds the subscriber-side detection pattern (store.getreturningOk(Some(_))→ insert/update;Ok(None)→ delete) inline. The contrast withsubscribe_to_changesshifts from "local puts vs. all changes" to "local writes (puts and deletes) vs. all writes."AutomergeStore::ttl_managerTTL eviction sites now carry inline comments naming peat-mesh#202: eachstore.deletecall in the synchronous eviction path and the background cleanup task wakeschange_txper the rc.29 contract, so a TTL eviction wakes the sync-coordinator's local-only outbound pusher as a side-effect (the document is gone by the time the pusher runs — wakeup, not propagation). Comments give future readers an in-place diagnostic hook if they trace a steady-state wakeup rate back to TTL expiry cadence.
Added — regression tests
tests/observer_fires_on_delete.rs(peat-mesh#203): 4 integration pins through the public surface —delete_fires_observer_tx,delete_fires_local_change_observer_and_gossip_channels,delete_with_remote_origin_suppresses_change_tx_and_tags_gossip,delete_of_missing_key_still_fires_observer.src/storage/automerge_sync.rs::tests::persistent_stream_wire_format_peat_mesh_175::tombstone_receive_fires_observer_tx: dispatch-tier in-tree pin. Seeds a doc on the receiver's store, drives a real Tombstone v2 frame throughhandle_incoming_sync_stream, asserts (a) the doc is removed AND (b) the observer channel wakes with the doc key. Catches a future regression whereapply_tombstonereverts to the silentdelete()call or bypasses the observer broadcast some other way.