componentized/directory

wasmcloud:keyvalue

interface dependency

interface batch wasmcloud:keyvalue/batch@0.2.0

A keyvalue interface that provides batch operations.

A batch operation is an operation that operates on multiple keys at once.

Batch operations are useful for reducing network round-trip time. For example, if you want to get the values associated with 100 keys, you can either do 100 get operations or you can do 1 batch get operation. The batch operation is faster because it only needs to make 1 network call instead of 100.

A batch operation does not guarantee atomicity, meaning that if the batch operation fails, some of the keys may have been modified and some may not.

This interface has the same consistency guarantees as the store interface, meaning that you should be able to "read your writes."

Types

use resource bucket

from wasmcloud:keyvalue/types@0.2.0

A bucket is a collection of key-value pairs. Each key-value pair is stored as an 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 vary 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

  • async functionget: async func(key: string) -> result<option<list<u8>>, error>

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

  • async functionset: async func( key: string, value: list<u8>, options: option<set-options>, ) -> 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.

    options controls expiry (ttl-ms) and conditional writes (if-not-exists); pass none for the default overwrite-on-exists behavior with no expiry.

    If any other error occurs, it returns an err(error).

  • async functiondelete: async func(key: string) -> 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).

  • async functionexists: async func(key: string) -> result<bool, 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).

  • async functionlist-keys: async func( prefix: option<string>, cursor: option<string>, ) -> result<key-response, error>

    Get the keys in the store, optionally restricted to those starting with prefix, with an optional cursor (for use in pagination). It returns a list of keys. Please note that for most KeyValue implementations, this 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.

    prefix filters the result to keys that begin with the given string; pass none to list all keys. When paginating, the same prefix should be supplied alongside each cursor.

    Note that the keys are not guaranteed to be returned in any particular order.

    If the store is empty (or no keys match prefix), 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).

use variant error

from wasmcloud:keyvalue/types@0.2.0

The set of errors which may be raised by functions in this package.

Following the wasip3 convention, this enumerates specific named cases rather than leaning on stringly-typed errors. It is intentionally non-exhaustive: future versions may add cases, and generated bindings are marked non-exhaustive accordingly, so consumers must always include a catch-all arm. Backend-specific failures that do not map to a named case are reported via other.

  • no-such-store

    The host does not recognize the store identifier requested.

  • access-denied

    The requesting component does not have access to the specified store (which may or may not exist).

  • invalid-argument

    The request was malformed or self-contradictory, e.g. a cas.swap whose cas-options sets no precondition.

  • precondition-failed

    A conditional operation did not meet its precondition, e.g. a set with if-not-exists against a key that already exists.

  • timeout

    The operation did not complete within the host- or backend-imposed time limit.

  • store-unavailable

    The store is currently unreachable or otherwise unavailable. The operation may succeed if retried later.

  • quota-exceeded

    The operation was rejected because a quota or rate limit was exceeded.

  • other: string

    Some other implementation-specific error has occurred (e.g. I/O). Used for backend-specific failures that do not map to a named case above.

Functions

async functionget-many: async func( bucket: borrow<bucket>, keys: list<string>, ) -> result<list<option<tuple<string, list<u8>>>>, error>

Get the key-value pairs associated with the keys in the store. It returns a list of key-value pairs.

If any of the keys do not exist in the store, it returns a none value for that pair in the list.

MAY show an out-of-date value if there are concurrent writes to the store.

If any other error occurs, it returns an err(error).

async functionset-many: async func( bucket: borrow<bucket>, key-values: list<tuple<string, list<u8>>>, ) -> result<_, error>

Set the values associated with the keys in the store. If the key already exists in the store, it overwrites the value.

Note that the key-value pairs are not guaranteed to be set in the order they are provided.

If any of the keys do not exist in the store, it creates a new key-value pair.

If any other error occurs, it returns an err(error). When an error occurs, it does not rollback the key-value pairs that were already set. Thus, this batch operation does not guarantee atomicity, implying that some key-value pairs could be set while others might fail.

Other concurrent operations may also be able to see the partial results.

async functiondelete-many: async func( bucket: borrow<bucket>, keys: list<string>, ) -> result<_, error>

Delete the key-value pairs associated with the keys in the store.

Note that the key-value pairs are not guaranteed to be deleted in the order they are provided.

If any of the keys do not exist in the store, it skips the key.

If any other error occurs, it returns an err(error). When an error occurs, it does not rollback the key-value pairs that were already deleted. Thus, this batch operation does not guarantee atomicity, implying that some key-value pairs could be deleted while others might fail.

Other concurrent operations may also be able to see the partial results.

WIT

/// A keyvalue interface that provides batch operations.
///
/// A batch operation is an operation that operates on multiple keys at once.
///
/// Batch operations are useful for reducing network round-trip time. For example, if you want to
/// get the values associated with 100 keys, you can either do 100 get operations or you can do 1
/// batch get operation. The batch operation is faster because it only needs to make 1 network call
/// instead of 100.
///
/// A batch operation does not guarantee atomicity, meaning that if the batch operation fails, some
/// of the keys may have been modified and some may not.
///
/// This interface has the same consistency guarantees as the `store` interface, meaning that you
/// should be able to "read your writes."
interface batch {
  use types.{bucket, error};

  /// Get the key-value pairs associated with the keys in the store. It returns a list of
  /// key-value pairs.
  ///
  /// If any of the keys do not exist in the store, it returns a `none` value for that pair in the
  /// list.
  ///
  /// MAY show an out-of-date value if there are concurrent writes to the store.
  ///
  /// If any other error occurs, it returns an `err(error)`.
  get-many: async func(bucket: borrow<bucket>, keys: list<string>) -> result<list<option<tuple<string, list<u8>>>>, error>;

  /// Set the values associated with the keys in the store. If the key already exists in the
  /// store, it overwrites the value.
  ///
  /// Note that the key-value pairs are not guaranteed to be set in the order they are provided.
  ///
  /// If any of the keys do not exist in the store, it creates a new key-value pair.
  ///
  /// If any other error occurs, it returns an `err(error)`. When an error occurs, it does not
  /// rollback the key-value pairs that were already set. Thus, this batch operation does not
  /// guarantee atomicity, implying that some key-value pairs could be set while others might
  /// fail.
  ///
  /// Other concurrent operations may also be able to see the partial results.
  set-many: async func(bucket: borrow<bucket>, key-values: list<tuple<string, list<u8>>>) -> result<_, error>;

  /// Delete the key-value pairs associated with the keys in the store.
  ///
  /// Note that the key-value pairs are not guaranteed to be deleted in the order they are
  /// provided.
  ///
  /// If any of the keys do not exist in the store, it skips the key.
  ///
  /// If any other error occurs, it returns an `err(error)`. When an error occurs, it does not
  /// rollback the key-value pairs that were already deleted. Thus, this batch operation does not
  /// guarantee atomicity, implying that some key-value pairs could be deleted while others might
  /// fail.
  ///
  /// Other concurrent operations may also be able to see the partial results.
  delete-many: async func(bucket: borrow<bucket>, keys: list<string>) -> result<_, error>;
}