Skip to main content

AutomergeStore

Struct AutomergeStore 

Source
pub struct AutomergeStore { /* private fields */ }

Implementations§

Source§

impl AutomergeStore

Source

pub fn open(path: impl AsRef<Path>) -> Result<AutomergeStore, Error>

Open or create storage at the given path

Source

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.

Source

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.

Source

pub fn is_in_memory(&self) -> bool

Check if the store is running in memory-only mode

Source

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.

Source

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.

Source

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 ‘:’).

Source

pub fn get(&self, key: &str) -> Result<Option<Automerge>, Error>

Load an Automerge document

Source

pub fn delete(&self, key: &str) -> Result<(), Error>

Delete a document

Source

pub fn scan_prefix( &self, prefix: &str, ) -> Result<Vec<(String, Automerge)>, Error>

Scan documents with prefix

Source

pub fn count(&self) -> usize

Count total documents

Source

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);
}
Source

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.

Source

pub fn collection(self: &Arc<AutomergeStore>, name: &str) -> Arc<dyn Collection>

Get a collection handle for a specific namespace

Source

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)

Source

pub fn get_tombstone( &self, collection: &str, document_id: &str, ) -> Result<Option<Tombstone>, Error>

Get a tombstone by collection and document ID

Source

pub fn get_tombstones_for_collection( &self, collection: &str, ) -> Result<Vec<Tombstone>, Error>

Get all tombstones for a collection

Source

pub fn get_all_tombstones(&self) -> Result<Vec<Tombstone>, Error>

Get all tombstones across all collections

Source

pub fn remove_tombstone( &self, collection: &str, document_id: &str, ) -> Result<bool, Error>

Remove a tombstone

Source

pub fn has_tombstone( &self, collection: &str, document_id: &str, ) -> Result<bool, Error>

Check if a tombstone exists

Source

pub fn list_collections(&self) -> Result<Vec<String>, Error>

Get list of all collections (by scanning document key prefixes)

Source

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.

Source

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.

Source

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/after
  • Ok(None) - Document not found
  • Err(_) - 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));
}
Source

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);
Source

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)

Source

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"])
Source

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).

Source

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).

Source

pub fn typed_collection<T>( self: &Arc<AutomergeStore>, name: &str, ) -> TypedCollection<T>

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")?;
Source

pub fn document_size(&self, key: &str) -> Result<Option<usize>, Error>

Get the serialized size of a document (for monitoring)

Trait Implementations§

Source§

impl GcStore for AutomergeStore

Source§

fn get_all_tombstones(&self) -> Result<Vec<Tombstone>, Error>

Get all tombstones
Source§

fn remove_tombstone( &self, collection: &str, document_id: &str, ) -> Result<bool, Error>

Remove a tombstone
Source§

fn has_tombstone( &self, collection: &str, document_id: &str, ) -> Result<bool, Error>

Check if a tombstone exists
Source§

fn get_expired_documents( &self, collection: &str, cutoff: SystemTime, ) -> Result<Vec<String>, Error>

Get document IDs in a collection that are older than the cutoff time
Source§

fn hard_delete(&self, collection: &str, document_id: &str) -> Result<(), Error>

Hard delete a document (permanent removal, no tombstone)
Source§

fn list_collections(&self) -> Result<Vec<String>, Error>

Get list of collections

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more