/// A keyvalue interface that provides eventually consistent key-value operations. /// /// Each of these operations acts on a single key-value pair. /// /// The value in the key-value pair is defined as a `u8` byte array and the intention is that it is /// the common denominator for all data types defined by different key-value stores to handle data, /// ensuring compatibility between different key-value stores. Note: the clients will be expecting /// serialization/deserialization overhead to be handled by the key-value store. The value could be /// a serialized object from JSON, HTML or vendor-specific data types like AWS S3 objects. /// /// Data consistency in a key value store refers to the guarantee that once a write operation /// completes, all subsequent read operations will return the value that was written. /// /// Any implementation of this interface must have enough consistency to guarantee "reading your /// writes." In particular, this means that the client should never get a value that is older than /// the one it wrote, but it MAY get a newer value if one was written around the same time. These /// guarantees only apply to the same client (which will likely be provided by the host or an /// external capability of some kind). In this context a "client" is referring to the caller or /// guest that is consuming this interface. Once a write request is committed by a specific client, /// all subsequent read requests by the same client will reflect that write or any subsequent /// writes. Another client running in a different context may or may not immediately see the result /// due to the replication lag. As an example of all of this, if a value at a given key is A, and /// the client writes B, then immediately reads, it should get B. If something else writes C in /// quick succession, then the client may get C. However, a client running in a separate context may /// still see A or B interface store { /// The set of errors which may be raised by functions in this package variant error { /// The host does not recognize the store identifier requested. no-such-store, /// The requesting component does not have access to the specified store /// (which may or may not exist). access-denied, /// Some implementation-specific error has occurred (e.g. I/O) other(string) } /// A response to a `list-keys` operation. record key-response { /// The list of keys returned by the query. keys: list, /// The continuation token to use to fetch the next page of keys. If this is `null`, then /// there are no more keys to fetch. cursor: option } /// A bucket is a collection of key-value pairs. Each key-value pair is stored as a entry in the /// bucket, and the bucket itself acts as a collection of all these entries. /// /// It is worth noting that the exact terminology for bucket in key-value stores can very /// depending on the specific implementation. For example: /// /// 1. Amazon DynamoDB calls a collection of key-value pairs a table /// 2. Redis has hashes, sets, and sorted sets as different types of collections /// 3. Cassandra calls a collection of key-value pairs a column family /// 4. MongoDB calls a collection of key-value pairs a collection /// 5. Riak calls a collection of key-value pairs a bucket /// 6. Memcached calls a collection of key-value pairs a slab /// 7. Azure Cosmos DB calls a collection of key-value pairs a container /// /// In this interface, we use the term `bucket` to refer to a collection of key-value pairs /// Get the value associated with the specified `key` /// /// The value is returned as an option. If the key-value pair exists in the /// store, it returns `Ok(value)`. If the key does not exist in the /// store, it returns `Ok(none)`. /// /// If any other error occurs, it returns an `Err(error)`. get: func(bucket: string, key: string) -> result>, error>; /// Set the value associated with the key in the store. If the key already /// exists in the store, it overwrites the value. /// /// If the key does not exist in the store, it creates a new key-value pair. /// /// If any other error occurs, it returns an `Err(error)`. set: func(bucket: string, key: string, value: list) -> result<_, error>; /// Delete the key-value pair associated with the key in the store. /// /// If the key does not exist in the store, it does nothing. /// /// If any other error occurs, it returns an `Err(error)`. delete: func(bucket: string, key: string) -> result<_, error>; /// Check if the key exists in the store. /// /// If the key exists in the store, it returns `Ok(true)`. If the key does /// not exist in the store, it returns `Ok(false)`. /// /// If any other error occurs, it returns an `Err(error)`. exists: func(bucket: string, key: string) -> result; /// Get all the keys in the store with an optional cursor (for use in pagination). It /// returns a list of keys. Please note that for most KeyValue implementations, this is a /// can be a very expensive operation and so it should be used judiciously. Implementations /// can return any number of keys in a single response, but they should never attempt to /// send more data than is reasonable (i.e. on a small edge device, this may only be a few /// KB, while on a large machine this could be several MB). Any response should also return /// a cursor that can be used to fetch the next page of keys. See the `key-response` record /// for more information. /// /// Note that the keys are not guaranteed to be returned in any particular order. /// /// If the store is empty, it returns an empty list. /// /// MAY show an out-of-date list of keys if there are concurrent writes to the store. /// /// If any error occurs, it returns an `Err(error)`. list-keys: func(bucket: string, cursor: option) -> result; }