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
impl DocStore
pub fn open() -> Result<DocStore, StoreError>
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>
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>
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>
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>
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>
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.
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>
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>
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>
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>
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
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
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
pub fn document_path(&self) -> &Path
See [DocOwner::label].
pub fn is_exclusive_writer(&self) -> bool
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>
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>
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>
pub fn load_migrating<F>( &mut self, migrate: F, ) -> Result<Option<AutoCommit>, StoreError>
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
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>
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
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>
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>
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>
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
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§
impl Freeze for DocStore
impl !RefUnwindSafe for DocStore
impl !Send for DocStore
impl !Sync for DocStore
impl Unpin for DocStore
impl UnsafeUnpin for DocStore
impl !UnwindSafe for DocStore
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
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§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