pub struct Store<K, V> { /* private fields */ }Expand description
A typed key-value store over an optional persistence Storage: an
embedded database on native targets, browser storage on wasm (feature
browser-cache), or nothing at all.
Reads follow HashMap’s shape and mutation rules, with no interior
mutability: get serves shared references from memory,
while everything that may change the store — insert,
get_mut, remove,
sync — requires &mut self. Share a store by wrapping it
in a lock, not by cloning it.
remove and clear act on memory alone;
their durable mirrors purge_key and
purge also delete from the storage.
CacheOption decides how the map is populated: Eager
ingests the whole namespace at open and serves every
read from memory, Lazy reads one key at a time on
demand.
§No Edits
A stored value never changes: there is no update, and reinserting a key
with a different value is an error. The one exception is imported entries:
a locally computed value replaces a value that came from a bundle, because
a shipped bundle must never be able to wedge the application that imported
it. See Store::insert. Mutating a value through
get_mut changes only the in-memory copy, never the
storage.
On an asynchronous storage (browser) a read can miss until the background
load finishes, which costs a recompute and nothing else; any &mut
operation ingests newly delivered content first.
§Environment switches
A store opened on the active environment stays bound to the environment,
not to the storage it opened: when crate::environment switches
(activate,
load, …), the store detects it and resets —
reads miss instead of serving the old environment’s entries, and the next
&mut operation drops the in-memory state and reopens the storage.
Detection is one relaxed atomic load, so it costs nothing while the
environment stays put. Stores on an explicit or absent storage are not
bound and never reset.
Implementations§
Source§impl<K: StoreKey, V: StoreValue> Store<K, V>
impl<K: StoreKey, V: StoreValue> Store<K, V>
Sourcepub fn new(options: StoreOptions) -> Self
pub fn new(options: StoreOptions) -> Self
Sourcepub fn namespace(&self) -> Option<&Namespace>
pub fn namespace(&self) -> Option<&Namespace>
The namespace this store addresses, if it persists anywhere.
Sourcepub fn get(&self, key: &K) -> Option<&V>
pub fn get(&self, key: &K) -> Option<&V>
Fetch an item from memory.
Never touches the storage: on an eager store the map is complete, so a
miss is a miss. On a lazy store this only serves entries a previous
get_mut faulted in; use get_mut to read through.
After an environment switch everything in memory belongs to the old environment, so this misses rather than serve it — a miss costs a recompute, a stale hit would be wrong.
Sourcepub fn get_mut(&mut self, key: &K) -> Option<&mut V>
pub fn get_mut(&mut self, key: &K) -> Option<&mut V>
Fetch an item, reading it from the storage on the first lookup of a lazy store and memoizing it afterwards.
Mutating the value changes only the in-memory copy, never the storage.
Sourcepub fn remove(&mut self, key: &K) -> Option<V>
pub fn remove(&mut self, key: &K) -> Option<V>
Take an item out of memory, reading through to the storage on a lazy store, and hand it out owned.
The storage is untouched — deleting durably is
purge_key. The key stays
known to the store. This is the read
for a value consumed once per process — a compiled kernel about to be
loaded — because nothing is cloned and nothing stays memoized.
Sourcepub fn insert(&mut self, key: K, value: V) -> Result<(), StoreError<K, V>>
pub fn insert(&mut self, key: K, value: V) -> Result<(), StoreError<K, V>>
Insert a new item into the store.
- Key absent: the entry is written to the storage.
- Present with the same value:
Ok, nothing written. - Present with a different value: an error, and the stored value is
left untouched —
StoreError::DuplicatedKeywhen this process wrote or read it,StoreError::KeyOutOfSyncwhen another process sharing the environment got there first. Both are routine, not bugs.
The exception is an entry that came from a bundle: the storage lets a locally computed value replace it, so a stale bundle can never wedge the application that imported it.
Sourcepub fn purge_key(&mut self, key: &K) -> Option<V>
pub fn purge_key(&mut self, key: &K) -> Option<V>
Deletes one entry, in memory and durably, and hands it out owned.
remove’s durable mirror, with the same signature:
where remove only evicts the in-memory copy, this also deletes the
storage entry, so the key is gone for every process sharing the
environment and free to reinsert.
Sourcepub fn purge(&mut self)
pub fn purge(&mut self)
Deletes everything this store addresses, in memory and durably.
clear’s durable mirror: after a purge the namespace
is empty for every process sharing the environment, and every key is
free to reinsert. Only this namespace is touched, never the rest of
the environment. Other stores on the same namespace keep what they
already ingested until they sync.
Sourcepub fn sync(&mut self)
pub fn sync(&mut self)
Ingest everything the storage holds into memory.
This is what makes an eager store complete, and new
performs it; call it again to ingest content an asynchronous storage
delivered since, or content another store wrote to a shared storage.
Sourcepub fn pending_load(&self) -> bool
pub fn pending_load(&self) -> bool
Whether asynchronously delivered content may still be waiting to be
ingested. false for synchronous storages (database, memory), whose
content is fully ingested at open. Also true right after an
environment switch, whose content is pending until the reset.
Sourcepub fn scan<F: FnMut(K, V)>(&mut self, func: F) -> bool
pub fn scan<F: FnMut(K, V)>(&mut self, func: F) -> bool
Visits every entry the storage holds, decoded and handed out owned, retaining none of them in memory.
The read-through counterpart of for_each: where
for_each walks the in-memory map, this walks the storage. It is the
hydration read for a caller keeping its own index over a
Lazy store — everything is visited once, and
nothing stays resident afterwards.
Returns whether the visit was complete. false means an asynchronous
storage was still loading, so entries may be missing: call again later
to see the rest.