Skip to main content

DocStore

Struct DocStore 

pub struct DocStore { /* private fields */ }
Expand description

One Automerge document handled by hand: load it, save or append it, and hand it to a DocWriter for debounced background writes. A thin policy layer over a [DocOwner] on a DurableStore; it owns no file handling of its own.

The launch-environment constructors (DocStore::open, DocStore::open_for, DocStore::open_room, …) join the document’s shared writers on an [FsStore] rooted at the native data directory, so two live instances of one app keep appending to one document, as they always have. DocStore::open_canonical_at takes the exclusive owner.

Implementations§

§

impl DocStore

pub fn open() -> Result<DocStore, StoreError>

Open the store belonging to the running package, via TILO_PACKAGE_ID — no argument by design, since an app doesn’t choose where its state lives.

§Errors

Returns an error if TILO_PACKAGE_ID is not a valid single directory name (see validate_package_id), or if the package’s state directory can’t be created, inspected or locked.

pub fn open_with_manifest_id(manifest_id: &str) -> Result<DocStore, StoreError>

Open the store, falling back to manifest_id when TILO_PACKAGE_ID is unset. The env var always wins; the fallback only covers launcher-less runs (dev binary, tests) that would otherwise share one directory.

§Errors

Returns an error if the resolved id is not a valid single directory name (see validate_package_id), or if the package’s state directory can’t be created, inspected or locked.

pub fn native_store() -> Rc<dyn DurableStore>

The store the native host keeps launch-environment documents in: an [FsStore] over the platform data directory ($XDG_DATA_HOME, else ~/.local/share).

pub fn open_for(package_id: &str) -> Result<DocStore, StoreError>

Open the store for an explicit package id — for tests and migration tools; rejects any id that is not a single, non-traversing directory name.

§Errors

Returns an error if package_id fails validate_package_id, or if the package’s state directory can’t be created, inspected or locked.

pub fn open_room_record( package_id: &str, room_key: &str, record_key: &str, ) -> Result<DocStore, StoreError>

Open one record in one collaboration room. A record id is only unique within a room: a hostile or stale peer must not be able to make uuid:... in room B resolve to room A’s change graph.

§Errors

Returns an error when an identifier is invalid or the room-scoped store cannot be created, locked, or loaded.

pub fn open_room( package_id: &str, room_key: &str, ) -> Result<DocStore, StoreError>

Open the index of one room — the list of which records that room holds. A sibling of the room’s records, so a room id can never resolve to a record’s document and merge the two.

§Errors

Returns an error if package_id fails validate_package_id or room_key fails validate_record_key, or if the room’s state directory can’t be created, inspected or locked.

pub fn shared( store: Rc<dyn DurableStore>, key: StorageKey, ) -> Result<DocStore, StoreError>

Join key’s shared writers on store.

§Errors

An exclusive owner holds the key, or the store refuses it.

pub fn exclusive( store: Rc<dyn DurableStore>, key: StorageKey, ) -> Result<DocStore, StoreError>

Become key’s exclusive owner on store.

§Errors

Another owner holds the key, or the store refuses it.

pub fn open_canonical_at( package_id: &str, directory: &Path, ) -> Result<DocStore, StoreError>

The exclusive owner of the document kept directly in directory. Never adopts stale files. The ownership gate is cooperative: older binaries that do not acquire it can still write, so concurrent use of one profile with those binaries is unsupported.

§Errors

Rejects invalid paths, contested gates and every filesystem durability failure.

pub fn room_primary_dir_at( profile_root: &Path, package: &str, room: &str, ) -> Result<PathBuf, StoreError>

The existing room-scoped package-primary directory, with explicit custody.

§Errors

Rejects relative roots and invalid package or room identifiers.

pub fn room_record_dir_at( profile_root: &Path, package: &str, room: &str, record: &str, ) -> Result<PathBuf, StoreError>

Resolve one record under an explicit profile root without consulting the environment.

§Errors

Rejects relative roots and invalid package, room or record identifiers.

pub fn package_id(&self) -> &str

pub fn with_schema_version(self, version: u32) -> DocStore

Select the app-owned CRDT layout this store reads and writes. Call this before load, load_or_new, or creating a writer.

pub fn schema_version(&self) -> u32

pub fn dir(&self) -> &Path

The directory holding the document, its actor sidecar and its locks, where the store keeps one.

pub fn document_path(&self) -> &Path

See [DocOwner::label].

pub fn actor(&self) -> &ActorId

The Automerge actor this store writes as.

pub fn is_exclusive_writer(&self) -> bool

Whether this process continues the stored writer identity. false means another instance is live: writes still succeed (merged on next load) but the actor id is fresh rather than the stored one.

pub fn load(&mut self) -> Result<Option<AutoCommit>, StoreError>

Load the persisted document, or Ok(None) on a first launch. A trailing partially-written chunk (crash during append) is dropped rather than failing the load, losing only the last unflushed edit.

§Errors

Returns an error if the document exists but can’t be read, if its bytes aren’t a loadable Automerge document, or if it declares a schema layout newer than this build understands (StoreError::NewerSchema).

pub fn load_complete(&mut self) -> Result<Option<AutoCommit>, StoreError>

Load a complete existing change graph for checked record admission.

§Errors

Rejects incomplete, empty, unreadable, or unsupported stored documents.

pub fn load_migrating<F>( &mut self, migrate: F, ) -> Result<Option<AutoCommit>, StoreError>
where F: FnOnce(&mut AutoCommit, u32, u32) -> Result<(), String>,

Load and, when necessary, atomically migrate an older app-owned CRDT layout to Self::schema_version. The callback must be deterministic and idempotent because another replica may independently migrate the same logical document before their changes merge.

A successful migration is written before returning. This keeps the autosave frontier aligned with what is actually durable; merely mutating the returned document and then seeding autosave would otherwise make those migration heads look already persisted.

§Errors

Returns load/write errors unchanged, or StoreError::Migration when the app callback rejects the older layout.

pub fn load_or_new(&mut self) -> AutoCommit

Load the persisted document, falling back to an empty one. An unreadable file is logged and treated as empty rather than crashing on launch. A document from a newer layout is different: the refusal is recorded (DocStore::refusal) and every writer built on this store switches itself off, since starting empty and then saving over the file would be data loss rather than a survivable empty session.

pub fn refusal(&self) -> Option<&str>

Why this store handed back an empty document, when it did — Some means the on-disk document must not be written over.

pub fn new_document(&mut self) -> AutoCommit

An empty document already carrying this store’s actor id, stamped with the current layout version at creation (not first save) so the version is never missing from a document written outside this path.

pub fn save(&mut self, doc: &mut AutoCommit) -> Result<(), StoreError>

Replace the whole document and wait until the store has committed it — for [FsStore], a synced temporary file renamed into place, so a crash leaves either the previous or the new document complete. Refuses when DocStore::refusal is set, since the in-memory document is an empty stand-in and writing it out would delete the user’s actual data.

§Errors

Returns an error if DocStore::refusal is set (writing would discard a newer-schema document already stored), or if the store fails to commit it.

pub fn append(&mut self, doc: &mut AutoCommit) -> Result<usize, StoreError>

Append only the changes doc has that the store does not, and wait for the store to commit them. Returns bytes appended (0 when idle). Refuses for the same data-loss reason as DocStore::save.

§Errors

Returns an error if DocStore::refusal is set, or if the store fails to commit the changes.

pub fn has_stored(&self) -> Result<bool, StoreError>

Whether the store holds anything for this document, even bytes that would not load.

§Errors

A failure reading the store.

pub fn writer(self) -> DocWriter

A DocWriter continuing this document in the background: a burst of edits becomes one write. Seed it with the loaded document (see DocWriter::seed). A refused store hands back a disabled writer, so the stand-in document never reaches storage.

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
§

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

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

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

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
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

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

Initializes a with the given initializer. Read more
§

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

Dereferences the given pointer. Read more
§

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

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

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

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

§

fn simd_from(_simd: S, value: T) -> T

§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

§

fn simd_into(self, simd: S) -> T

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

impl<T> Upcast<T> for T

§

fn upcast(&self) -> Option<&T>

§

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

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self>

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

impl<T> ErasedDestructor for T
where T: 'static,