Reference / KV API for Rust
KV API for Rust
Every public type, trait and function of the KV engine in tinystore::kv, generated from its source. The KV guide explains how to use them, and the Bun and Node, Python and Go pages list the same API.
Store
impl StoreStore.bucket
pub fn bucket<V: Value>(&self, name: &str) -> BucketBuilder<V>A bucket of values of type V by key, in the store's kv.db; the engine
opens with the first handle.
Store.counters
pub fn counters(&self, name: &str) -> CountersBuilderNumbers by key that add up, in the store's kv.db: attempts, hits, uses.
Store.once
pub fn once<V: Value>(&self, name: &str) -> OnceBuilder<V>Functions run once a key, their answers kept in the store's kv.db: a request sent twice gets the first one's answer instead of doing its work again, as an idempotency key promises.
Store.quota
pub fn quota(&self, name: &str) -> QuotaBuilderUses a key may make in windows that each reset on their own, in the
store's kv.db: store.quota("ai").window("daily", 100, DAY).
Store.rate_limit
pub fn rate_limit(&self, name: &str) -> RateLimitBuilderRequests let through at a steady rate a key, with room for a burst, in
the store's kv.db: store.rate_limit("api").rate(100, Duration::from_secs(1)).
Allowance
pub struct Allowance {
pub ok: bool,
pub left: u64,
pub retry_at: Option<SystemTime>,
pub windows: Vec<Window>,
}What a rate limit or a quota answers a request: whether it passed, and what is left.
Allowance.window
pub fn window(&self, name: &str) -> Option<&Window>The window named name, of a quota's answer.
Window
pub struct Window {
pub name: String,
pub used: u64,
pub limit: u64,
pub left: u64,
pub resets_at: Option<SystemTime>,
}One window of a quota, as a key stands in it.
All
pub struct All<V> { /* private fields */ }Every key of a branch, a page at a time.
Bucket
pub struct Bucket<V> { /* private fields */ }Values of one type by key. A handle is cheap to clone and to keep; under
gives the same bucket seen from a branch.
Bucket.set
pub fn set(&self, key: impl Key, value: &V) -> Result<()>Writes value under key. A key that is there keeps its ttl; a new one
takes the bucket's, and an idle key lives its span from the write.
Bucket.create
pub fn create(&self, key: impl Key, value: &V) -> Result<bool>Writes value only when key is not there, and says whether it did; an
expired key is not there. A key that is there is false, never an error.
Bucket.key
pub fn key(&self, key: impl Key) -> KeyCall<'_, V>A call on key with what it asks beside its value, a new expiry or a
version the key must still be at, run by its last step:
sessions.key(&token).if_version(seen).set(&next).
Bucket.get
pub fn get(&self, key: impl Key) -> Result<Option<V>>Bucket.entry
pub fn entry(&self, key: impl Key) -> Result<Option<Entry<V>>>The value with its version and expiry.
Bucket.take
pub fn take(&self, key: impl Key) -> Result<Option<V>>Reads key and removes it in one commit: of two callers taking the same
key, one gets the value. A value that no longer reads as the bucket's
type is Corrupt, and stays.
Bucket.list
pub fn list(&self, limit: usize, after: Option<&str>) -> Result<Page<V>>One page of this branch's own keys, after after when it continues
another; limit keys at most, one at least, and never more than
PAGE_KEYS.
Bucket.all
pub fn all(&self) -> All<V>Every key of this branch, a page at a time. No snapshot is held between pages, so a slow loop keeps no reader, and a key written meanwhile may or may not be met.
Bucket.under
pub fn under(&self, owner: impl Key) -> Bucket<V>The same bucket seen from the branch owner names under this one:
sessions.under(user_id).clear() signs a user out everywhere.
Bucket.has
pub fn has(&self, key: impl Key) -> Result<bool>Bucket.delete
pub fn delete(&self, key: impl Key) -> Result<bool>Removes key and says whether a live key was there.
Bucket.expire
pub fn expire(&self, key: impl Key, ttl: Duration) -> Result<bool>Gives a live key a new expiry, ttl from now, as Redis's EXPIRE does,
keeping its value and version; says whether the key was there.
Bucket.clear
pub fn clear(&self) -> Result<()>Removes every key of this branch and of the branches under it, at once for every reader, however many there are.
Bucket.add
pub fn add(&self, key: impl Key) -> Result<bool>Adds key to a bucket of keys alone, a set, and says whether it was new:
seen.add(event_id) is false for an event already handled.
BucketBuilder
pub struct BucketBuilder<V> { /* private fields */ }A bucket being opened: its name, its type, how its keys expire, whether its values are encrypted.
BucketBuilder.ttl
pub fn ttl(self, ttl: Duration) -> SelfKeys expire this long after they are written, unless a write says otherwise.
BucketBuilder.idle
pub fn idle(self, idle: Duration) -> SelfKeys expire this long after they were last read or written.
BucketBuilder.encrypted
pub fn encrypted(self) -> SelfKeeps every value sealed with the store's encryption key, as a password or a token is kept: the file holds what nobody reads without the key, and a value copied under another key does not open. A key is not sealed, so a secret is a value and never a key. A name keeps whether it is encrypted: it opens the same way every time.
let passwords = store.bucket::<String>("source-passwords").encrypted().open()?;
passwords.set("source-42", &"hunter2".to_owned())?;BucketBuilder.open
pub fn open(self) -> Result<Bucket<V>>Entry
pub struct Entry<V> {
pub key: String,
pub value: V,
pub version: Version,
pub expires_at: Option<SystemTime>,
}A key's value with what a conditional write needs.
PAGE_KEYS
pub const PAGE_KEYS: usizeKeys a page holds at most.
Page
pub struct Page<V> {
pub entries: Vec<Entry<V>>,
pub next: Option<String>,
}One page of a branch's keys, in the byte order of their text.
Version
pub struct Version(_)The revision of kv.db that wrote a value. It never repeats, across deletes, expiry and restarts, and it compares only for equality.
Counters
pub struct Counters { /* private fields */ }Numbers by key that only add up; a counter that is not there holds 0. Every handle on a name counts the same way, in the file or in memory.
Counters.under
pub fn under(&self, owner: impl Key) -> CountersThe same counters seen from the branch owner names under these.
Counters.add
pub fn add(&self, key: impl Key, n: i64) -> Result<i64>Adds n to the counter under key and returns what it holds now. A
counter that is not there starts from 0, its ttl from now; a sum past
the range of an i64 is Limit and changes nothing.
Counters.get
pub fn get(&self, key: impl Key) -> Result<i64>What the counter under key holds; 0 when it is not there.
Counters.delete
pub fn delete(&self, key: impl Key) -> Result<bool>Removes the counter under key and says whether it was there.
Counters.clear
pub fn clear(&self) -> Result<()>Removes every counter of this branch and of the branches under it, at once for every reader, however many there are.
CountersBuilder
pub struct CountersBuilder { /* private fields */ }Counters being opened: their name, how long a counter lasts, and whether they are kept in memory between flushes.
CountersBuilder.ttl
pub fn ttl(self, ttl: Duration) -> SelfA counter lasts this long from its first add, then starts again from 0: the adds after the first do not move it.
CountersBuilder.flush_every
pub fn flush_every(self, span: Duration) -> SelfKeeps the counters in memory and writes what changed once a span, so that an add costs no commit and a crash loses at most the last span. Without it each add is written before it returns.
CountersBuilder.open
pub fn open(self) -> Result<Counters>Maintenance
pub struct Maintenance {
pub expired: usize,
pub cleared: usize,
pub renewed: usize,
pub flushed: usize,
}What one maintenance pass did.
KeyCall
pub struct KeyCall<'a, V> { /* private fields */ }A call on one key with what it asks beside its value, run by its last step:
sessions.key(&token).if_version(seen).set(&next).
KeyCall.ttl
pub fn ttl(self, ttl: Duration) -> SelfThe key expires ttl from now, for set, create and expire.
KeyCall.expires_at
pub fn expires_at(self, time: SystemTime) -> SelfThe key expires at time, for set, create and expire.
KeyCall.if_version
pub fn if_version(self, version: Version) -> SelfThe call applies only to a live key still at version: a key written,
expired or deleted since is a Conflict.
KeyCall.set
pub fn set(self, value: &V) -> Result<()>KeyCall.create
pub fn create(self, value: &V) -> Result<bool>Writes only when the key is not there, and says whether it did.
KeyCall.take
pub fn take(self) -> Result<Option<V>>KeyCall.delete
pub fn delete(self) -> Result<bool>Removes the key and says whether a live key was there.
KeyCall.expire
pub fn expire(self) -> Result<bool>Gives a live key the expiry ttl or expires_at named, keeping its
value and version, and says whether it was there.
Once
pub struct Once<V> { /* private fields */ }Functions run at most once a key, their answers kept: a charge, an import, a webhook's effect, done once however often the request arrives.
Once.under
pub fn under(&self, owner: impl Key) -> Once<V>The same answers seen from the branch owner names under these.
Once.run
pub fn run<E: From<Error>>(
&self,
key: impl Key,
work: impl FnOnce() -> Result<V, E>,
) -> Result<V, E>The answer kept under key, or work's, which is then kept.
While another run of the key is under way, in this process or through its server, this one waits for it and returns its answer. An error keeps nothing, so the next run runs again; an answer meant to be kept, a card declined, is a value rather than an error. An answer that could not be kept is still returned, and the failure logged.
Once.get
pub fn get(&self, key: impl Key) -> Result<Option<V>>The answer kept under key.
Once.delete
pub fn delete(&self, key: impl Key) -> Result<bool>Forgets the answer kept under key, so that the next run runs again;
says whether there was one.
OnceBuilder
pub struct OnceBuilder<V> { /* private fields */ }Answers being opened: their name and type, and how long one is kept.
OnceBuilder.keep
pub fn keep(self, keep: Duration) -> SelfHow long an answer is kept from when it was made; a day unless said. After that, a run of its key runs again.
OnceBuilder.open
pub fn open(self) -> Result<Once<V>>Key
pub trait KeyWhat names a key, an owner or a folder: text, or an integer spelled in
decimal, so that 42 and "42" are one key.
Key.text
fn text(&self) -> Cow<'_, str>Quota
pub struct Quota { /* private fields */ }Uses a key may make in each of its windows, such as 100 messages every five
hours and 300 a week, counted by one allow.
A window starts at a key's first use after the last one ended and lasts its span, so each key resets on its own:
window("session", 100, 5 h): first use 13:42 → resets at 18:42;
a use at 19:07 starts the next, which resets at 00:07An allow counts in every window or in none, in one durable write: two
quotas asked one after the other would leave the first counted when the
second refused.
Quota.under
pub fn under(&self, owner: impl Key) -> QuotaThe same quota seen from the branch owner names under this one, whose
keys are counted apart.
Quota.allow
pub fn allow(&self, key: impl Key) -> Result<Allowance>Uses one of each of key's windows, or none when one has no room left.
retry_at is when the windows that refused reset.
Quota.allow_n
pub fn allow_n(&self, key: impl Key, n: u64) -> Result<Allowance>Uses n of each of key's windows at once, or none when one has no
room for n. More than a window's limit never passes, and is Invalid.
Quota.peek
pub fn peek(&self, key: impl Key) -> Result<Allowance>key's windows, using nothing: ok says whether one more use would
pass now.
Quota.refund
pub fn refund(&self, key: impl Key) -> Result<()>Gives one use back to each of key's windows that has not reset since.
Quota.refund_n
pub fn refund_n(&self, key: impl Key, n: u64) -> Result<()>Gives n uses back, never below nothing.
Quota.reset
pub fn reset(&self, key: impl Key) -> Result<()>Forgets key's windows, so that its next use starts each anew.
QuotaBuilder
pub struct QuotaBuilder { /* private fields */ }A quota being opened: its name and its windows.
QuotaBuilder.window
pub fn window(self, name: &str, limit: u64, span: Duration) -> SelfLets a key use up to limit every span from its first use. A name is
a lowercase letter, then up to 31 of them, digits and '_'; a quota has
one to eight windows.
QuotaBuilder.open
pub fn open(self) -> Result<Quota>RateLimit
pub struct RateLimit { /* private fields */ }Requests let through at a steady rate a key, with room for a burst.
It is the generic cell rate algorithm: a key holds one time, when its next request is due, so no window has an edge that lets twice the rate through, and a key costs one number.
rate(3, 3 s), burst 3: three pass at once, and the fourth may pass 1 s laterThe times live in memory and reach kv.db every second and at close: a crash forgets at most the last second, which lets at most one burst more through. A key whose time has come is as one never seen.
RateLimit.under
pub fn under(&self, owner: impl Key) -> RateLimitThe same rate limit seen from the branch owner names under this one,
whose keys are counted apart.
RateLimit.allow
pub fn allow(&self, key: impl Key) -> Result<Allowance>Asks for one request of key.
RateLimit.allow_n
pub fn allow_n(&self, key: impl Key, n: u64) -> Result<Allowance>Asks for n requests of key at once: all of them pass or none does.
More than the burst never passes, and is Invalid.
RateLimit.peek
pub fn peek(&self, key: impl Key) -> Result<Allowance>Whether one request of key would pass now, using nothing.
RateLimit.reset
pub fn reset(&self, key: impl Key) -> Result<()>Forgets key's requests, so that its next one has the whole burst.
RateLimitBuilder
pub struct RateLimitBuilder { /* private fields */ }A rate limit being opened: its name, its rate and its burst.
RateLimitBuilder.rate
pub fn rate(self, count: u64, per: Duration) -> SelfLets count requests a key through every per.
RateLimitBuilder.burst
pub fn burst(self, burst: u64) -> SelfHow many requests may pass at once before the rate holds the next; the rate's count unless said.
RateLimitBuilder.open
pub fn open(self) -> Result<RateLimit>TxBucket
pub struct TxBucket<'a, V> { /* private fields */ }A bucket's calls inside a transaction.
TxBucket.get
pub fn get(&self, key: impl Key) -> Result<Option<V>>TxBucket.entry
pub fn entry(&self, key: impl Key) -> Result<Option<Entry<V>>>TxBucket.has
pub fn has(&self, key: impl Key) -> Result<bool>TxBucket.set
pub fn set(&self, key: impl Key, value: &V) -> Result<()>TxBucket.create
pub fn create(&self, key: impl Key, value: &V) -> Result<bool>TxBucket.take
pub fn take(&self, key: impl Key) -> Result<Option<V>>Takes key; a value that no longer reads as the bucket's type is
Corrupt, and stays, and the transaction goes on.
TxBucket.delete
pub fn delete(&self, key: impl Key) -> Result<bool>TxBucket.expire
pub fn expire(&self, key: impl Key, ttl: Duration) -> Result<bool>TxBucket.key
pub fn key(&self, key: impl Key) -> KeyCall<'a, V>A call on key with what it asks beside its value, inside the
transaction: tx.with(&sessions).key(&token).if_version(seen).set(&next).
TxBucket.clear
pub fn clear(&self) -> Result<()>Removes every key of the bucket's branch and of the branches under it.
TxBucket.list
pub fn list(&self, limit: usize, after: Option<&str>) -> Result<Page<V>>One page of the branch's own keys, as Bucket::list reads it.
TxCounters
pub struct TxCounters<'a> { /* private fields */ }Counters' calls inside a transaction. Counters kept in memory join no
transaction: their calls through it are Invalid.
TxCounters.add
pub fn add(&self, key: impl Key, n: i64) -> Result<i64>TxCounters.get
pub fn get(&self, key: impl Key) -> Result<i64>TxCounters.delete
pub fn delete(&self, key: impl Key) -> Result<bool>Bytes
pub struct Bytes(pub Vec<u8>)Bytes kept as they are rather than as a JSON list of numbers.
Value
pub trait ValueA type a bucket can keep: anything serde reads and writes.
maintain
pub fn maintain(store: &Store) -> Result<Maintenance>Writes what kv keeps in memory, then deletes what expired and what large clears hid. The store runs it every minute, and writes memory every second; a store opened without background work leaves both to the caller.