pub struct AutomergeStore { /* private fields */ }Implementations§
Source§impl AutomergeStore
impl AutomergeStore
Sourcepub fn open(path: impl AsRef<Path>) -> Result<AutomergeStore, Error>
pub fn open(path: impl AsRef<Path>) -> Result<AutomergeStore, Error>
Open or create storage at the given path
Sourcepub fn in_memory() -> AutomergeStore
pub fn in_memory() -> AutomergeStore
Create an in-memory store (no disk persistence)
Documents are stored only in the LRU cache. This mode is useful for high-throughput testing where persistence is not required.
Note: Cache size is 10,000 documents in memory mode (vs 1,000 for disk mode) to accommodate larger working sets.
Sourcepub fn lock_doc(&self, key: &str) -> MutexGuard<'_, ()>
pub fn lock_doc(&self, key: &str) -> MutexGuard<'_, ()>
Acquire the striped lock for a document key.
Returns a MutexGuard that serializes read-modify-write operations
on documents hashing to the same stripe. Hold this guard across
the entire get→modify→put sequence.
Used by compact() and AutomergeSyncCoordinator::receive_sync_message()
to prevent concurrent modifications from silently dropping changes.
Sourcepub fn is_in_memory(&self) -> bool
pub fn is_in_memory(&self) -> bool
Check if the store is running in memory-only mode
Sourcepub fn put(&self, key: &str, doc: &Automerge) -> Result<(), Error>
pub fn put(&self, key: &str, doc: &Automerge) -> Result<(), Error>
Save an Automerge document
§Change Notifications (Phase 6.3)
This method emits a change notification after successfully persisting the document. Subscribers will receive the document key to trigger automatic sync.
Sourcepub fn put_without_notify(
&self,
key: &str,
doc: &Automerge,
) -> Result<(), Error>
pub fn put_without_notify( &self, key: &str, doc: &Automerge, ) -> Result<(), Error>
Save an Automerge document without emitting change notification (Issue #346)
Use this method when storing documents received via sync to avoid triggering a sync-back that would be blocked by cooldown and waste resources. The sending peer already has this document, so syncing back is unnecessary.
Sourcepub fn put_with_ttl(
&self,
key: &str,
doc: &Automerge,
ttl_manager: &TtlManager,
) -> Result<(), Error>
pub fn put_with_ttl( &self, key: &str, doc: &Automerge, ttl_manager: &TtlManager, ) -> Result<(), Error>
Save an Automerge document with TTL-based expiration.
Delegates to put() and then schedules TTL cleanup via the TtlManager
if the collection has a configured TTL. The collection name is extracted
from the key prefix (before the first ‘/’ or ‘:’).
Sourcepub fn scan_prefix(
&self,
prefix: &str,
) -> Result<Vec<(String, Automerge)>, Error>
pub fn scan_prefix( &self, prefix: &str, ) -> Result<Vec<(String, Automerge)>, Error>
Scan documents with prefix
Sourcepub fn subscribe_to_changes(&self) -> Receiver<String>
pub fn subscribe_to_changes(&self) -> Receiver<String>
Subscribe to document change notifications (Phase 6.3)
Returns a receiver that will receive document keys whenever documents are modified. Multiple subscribers are supported - each gets their own receiver.
§Example
let store = AutomergeStore::open("./data")?;
let mut rx = store.subscribe_to_changes();
while let Ok(doc_key) = rx.recv().await {
println!("Document changed: {}", doc_key);
}Sourcepub fn subscribe_to_observer_changes(&self) -> Receiver<String>
pub fn subscribe_to_observer_changes(&self) -> Receiver<String>
Subscribe to observer notifications (Issue #377)
Returns a receiver that receives document keys for ALL changes, including documents received via sync. Use this for hierarchical aggregation where you need to react to remotely synced documents (e.g., company commander reacting to platoon summaries synced from platoon leaders).
Unlike subscribe_to_changes() which only fires for local puts,
this fires for ALL document changes.
Sourcepub fn collection(self: &Arc<AutomergeStore>, name: &str) -> Arc<dyn Collection>
pub fn collection(self: &Arc<AutomergeStore>, name: &str) -> Arc<dyn Collection>
Get a collection handle for a specific namespace
Sourcepub fn put_tombstone(&self, tombstone: &Tombstone) -> Result<(), Error>
pub fn put_tombstone(&self, tombstone: &Tombstone) -> Result<(), Error>
Store a tombstone
Tombstones are stored with key format “collection:document_id” In memory-only mode, this is a no-op (tombstones aren’t needed without persistence)
Sourcepub fn get_tombstone(
&self,
collection: &str,
document_id: &str,
) -> Result<Option<Tombstone>, Error>
pub fn get_tombstone( &self, collection: &str, document_id: &str, ) -> Result<Option<Tombstone>, Error>
Get a tombstone by collection and document ID
Sourcepub fn get_tombstones_for_collection(
&self,
collection: &str,
) -> Result<Vec<Tombstone>, Error>
pub fn get_tombstones_for_collection( &self, collection: &str, ) -> Result<Vec<Tombstone>, Error>
Get all tombstones for a collection
Sourcepub fn get_all_tombstones(&self) -> Result<Vec<Tombstone>, Error>
pub fn get_all_tombstones(&self) -> Result<Vec<Tombstone>, Error>
Get all tombstones across all collections
Sourcepub fn remove_tombstone(
&self,
collection: &str,
document_id: &str,
) -> Result<bool, Error>
pub fn remove_tombstone( &self, collection: &str, document_id: &str, ) -> Result<bool, Error>
Remove a tombstone
Sourcepub fn has_tombstone(
&self,
collection: &str,
document_id: &str,
) -> Result<bool, Error>
pub fn has_tombstone( &self, collection: &str, document_id: &str, ) -> Result<bool, Error>
Check if a tombstone exists
Sourcepub fn list_collections(&self) -> Result<Vec<String>, Error>
pub fn list_collections(&self) -> Result<Vec<String>, Error>
Get list of all collections (by scanning document key prefixes)
Sourcepub fn get_expired_documents(
&self,
collection: &str,
cutoff: SystemTime,
) -> Result<Vec<String>, Error>
pub fn get_expired_documents( &self, collection: &str, cutoff: SystemTime, ) -> Result<Vec<String>, Error>
Get documents in a collection that were created before the cutoff time
This checks the _created_at field stored in the Automerge document. Used for ImplicitTTL garbage collection.
Sourcepub fn hard_delete(
&self,
collection: &str,
document_id: &str,
) -> Result<(), Error>
pub fn hard_delete( &self, collection: &str, document_id: &str, ) -> Result<(), Error>
Hard delete a document (permanent removal, no tombstone created)
Used by garbage collection for ImplicitTTL collections where tombstones are not needed.
Sourcepub fn compact(&self, key: &str) -> Result<Option<(usize, usize)>, Error>
pub fn compact(&self, key: &str) -> Result<Option<(usize, usize)>, Error>
Compact a document by discarding CRDT history
Automerge documents accumulate operation history with every change. This method replaces the document with a forked copy that contains only the current state, freeing memory used by historical operations.
§When to use
- After many updates to high-frequency documents (beacons, node_states)
- When memory pressure is detected
- Periodically for long-running simulations
§Returns
Ok(Some(old_size, new_size))- Document was compacted, returns sizes before/afterOk(None)- Document not foundErr(_)- Compaction failed
§Example
let store = AutomergeStore::open("./data")?;
if let Some((old, new)) = store.compact("node_states:soldier-1")? {
tracing::info!("Compacted {} -> {} bytes ({}% reduction)", old, new, 100 - (new * 100 / old));
}Sourcepub fn compact_prefix(
&self,
prefix: &str,
) -> Result<(usize, usize, usize), Error>
pub fn compact_prefix( &self, prefix: &str, ) -> Result<(usize, usize, usize), Error>
Compact all documents with a given prefix
Useful for batch-compacting all documents in a collection.
§Returns
(documents_compacted, total_bytes_before, total_bytes_after)
§Example
let store = AutomergeStore::open("./data")?;
let (count, before, after) = store.compact_prefix("node_states:")?;
tracing::info!("Compacted {} documents: {} -> {} bytes", count, before, after);Sourcepub fn compact_all(&self) -> Result<(usize, usize, usize), Error>
pub fn compact_all(&self) -> Result<(usize, usize, usize), Error>
Compact all documents in the store
§Returns
(documents_compacted, total_bytes_before, total_bytes_after)
Sourcepub fn start_background_compaction(
self: &Arc<AutomergeStore>,
interval: Duration,
size_threshold_bytes: usize,
collections: Vec<String>,
token: CancellationToken,
)
pub fn start_background_compaction( self: &Arc<AutomergeStore>, interval: Duration, size_threshold_bytes: usize, collections: Vec<String>, token: CancellationToken, )
Start a background task that periodically compacts documents in specific collections that exceed a size threshold.
Only LatestOnly sync-mode collections should be compacted — compacting
FullHistory collections destroys change history needed for delta sync.
interval: How often to run compaction (default: 5 minutes)size_threshold_bytes: Only compact documents larger than this (default: 64 KiB)collections: Collection prefixes to compact (e.g.,["beacons", "platforms"])
Sourcepub fn compact_collections_above_threshold(
&self,
collections: &[String],
threshold_bytes: usize,
) -> Result<(usize, usize, usize), Error>
pub fn compact_collections_above_threshold( &self, collections: &[String], threshold_bytes: usize, ) -> Result<(usize, usize, usize), Error>
Compact documents in specific collections that exceed a size threshold.
Only scans documents matching the given collection prefixes (e.g.,
"beacons" matches "beacons:beacon-1", "beacons:beacon-2", etc.).
Returns (documents_compacted, total_bytes_before, total_bytes_after).
Sourcepub fn compact_above_threshold(
&self,
threshold_bytes: usize,
) -> Result<(usize, usize, usize), Error>
pub fn compact_above_threshold( &self, threshold_bytes: usize, ) -> Result<(usize, usize, usize), Error>
Compact only documents exceeding a size threshold.
Returns (documents_compacted, total_bytes_before, total_bytes_after).
Sourcepub fn typed_collection<T>(
self: &Arc<AutomergeStore>,
name: &str,
) -> TypedCollection<T>where
T: Serialize + DeserializeOwned,
pub fn typed_collection<T>(
self: &Arc<AutomergeStore>,
name: &str,
) -> TypedCollection<T>where
T: Serialize + DeserializeOwned,
Get a typed collection handle for serde-based access.
Returns a TypedCollection<T> that provides automatic serde
serialization/deserialization, integrated queries, and
prefix-filtered change subscriptions.
§Example
let sensors = store.typed_collection::<SensorReading>("sensors");
sensors.upsert("r001", &reading)?;
let result = sensors.get("r001")?;Trait Implementations§
Source§impl GcStore for AutomergeStore
impl GcStore for AutomergeStore
Source§fn remove_tombstone(
&self,
collection: &str,
document_id: &str,
) -> Result<bool, Error>
fn remove_tombstone( &self, collection: &str, document_id: &str, ) -> Result<bool, Error>
Source§fn has_tombstone(
&self,
collection: &str,
document_id: &str,
) -> Result<bool, Error>
fn has_tombstone( &self, collection: &str, document_id: &str, ) -> Result<bool, Error>
Source§fn get_expired_documents(
&self,
collection: &str,
cutoff: SystemTime,
) -> Result<Vec<String>, Error>
fn get_expired_documents( &self, collection: &str, cutoff: SystemTime, ) -> Result<Vec<String>, Error>
Auto Trait Implementations§
impl Freeze for AutomergeStore
impl !RefUnwindSafe for AutomergeStore
impl Send for AutomergeStore
impl Sync for AutomergeStore
impl Unpin for AutomergeStore
impl UnsafeUnpin for AutomergeStore
impl !UnwindSafe for AutomergeStore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more