forked from WebAssembly/wasi-keyvalue
-
Notifications
You must be signed in to change notification settings - Fork 0
/
store.wit
114 lines (105 loc) · 6.05 KB
/
store.wit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/// 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<string>,
/// 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<u64>
}
/// 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<option<list<u8>>, 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<u8>) -> 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<bool, error>;
/// 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<u64>) -> result<key-response, error>;
}