diff --git a/imports.md b/imports.md index ca31a78..103db60 100644 --- a/imports.md +++ b/imports.md @@ -23,20 +23,50 @@ the common denominator for all data types defined by different key-value stores 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
+An implementation of this interface MUST be eventually consistent, but is not required to +provide any consistency guaranteeds beyond that. Practically speaking, eventual consistency is +among the weakest of consistency models, guaranteeing only that values will not be produced +"from nowhere", i.e. any value read is guaranteed to have been written to that key at some +earlier time. Beyond that, there are no guarantees, and thus a portable component must neither +expect nor rely on anything else.
+In the future, additional interfaces may be added to wasi:keyvalue
with stronger guarantees,
+which will allow components to express their requirements by importing whichever interface(s)
+provides matching (or stronger) guarantees. For example, a component requiring strict
+serializability might import a (currently hypothetical) strict-serializable-store
interface
+with a similar signature to store
but with much stronger semantic guarantees. On the other
+end, a host might either support implementations of both the store
and
+strict-serializable-store
or just the former, in which case the host would immediately reject
+a component which imports the unsupported interface.
Here are a few examples of behavior which a component developer might wish to rely on but which +are NOT guaranteed by an eventually consistent system (e.g. a distributed system composed of +multiple replicas, each of which may receive writes in a different order, making no attempt to +converge on a global consensus):
+Read-your-own-writes: eventual consistency does NOT guarantee that a write to a given key +followed by a read from the same key will retrieve the same or newer value.
+Convergence: eventual consistency does NOT guarantee that any two replicas will agree on the +value for a given key -- even after all writes have had time to propagate to all replicas.
+Last-write-wins: eventual consistency does NOT guarantee that the most recent write will +take precendence over an earlier one; old writes may overwrite newer ones temporarily or +permanently.
+This interface does not currently make any hard guarantees about the durability of values
+stored. A valid implementation might rely on an in-memory hash table, the contents of which are
+lost when the process exits. Alternatively, another implementation might synchronously persist
+all writes to disk -- or even to a quorum of disk-backed nodes at multiple locations -- before
+returning a result for a set
call. Finally, a third implementation might persist values
+asynchronously on a best-effort basis without blocking set
calls, in which case an I/O error
+could occur after the component instance which originally made the call has exited.
Future versions of wasi:keyvalue
may provide ways to query and control the durability and
+consistency provided by the backing implementation.
variant error
resource bucket
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 +
It is worth noting that the exact terminology for bucket in key-value stores can vary depending on the specific implementation. For example:
bucket
to refer to a collection of key-value pairsIn this interface, we use the term bucket
to refer to a connection to a collection of
+key-value pairs.
bucket
resources using the same identifier MAY result in connections
+to two separate replicas in a distributed database, and that writes to one of those
+resources are not guaranteed to be readable from the other resource promptly (or ever, in
+the case of a replica failure or message reordering). See the Consistency
section of the
+store
interface documentation for details.open: func
Get the bucket with the specified identifier.
diff --git a/watch-service.md b/watch-service.md index a65115a..05d90bf 100644 --- a/watch-service.md +++ b/watch-service.md @@ -21,20 +21,50 @@ the common denominator for all data types defined by different key-value stores 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
+An implementation of this interface MUST be eventually consistent, but is not required to +provide any consistency guaranteeds beyond that. Practically speaking, eventual consistency is +among the weakest of consistency models, guaranteeing only that values will not be produced +"from nowhere", i.e. any value read is guaranteed to have been written to that key at some +earlier time. Beyond that, there are no guarantees, and thus a portable component must neither +expect nor rely on anything else.
+In the future, additional interfaces may be added to wasi:keyvalue
with stronger guarantees,
+which will allow components to express their requirements by importing whichever interface(s)
+provides matching (or stronger) guarantees. For example, a component requiring strict
+serializability might import a (currently hypothetical) strict-serializable-store
interface
+with a similar signature to store
but with much stronger semantic guarantees. On the other
+end, a host might either support implementations of both the store
and
+strict-serializable-store
or just the former, in which case the host would immediately reject
+a component which imports the unsupported interface.
Here are a few examples of behavior which a component developer might wish to rely on but which +are NOT guaranteed by an eventually consistent system (e.g. a distributed system composed of +multiple replicas, each of which may receive writes in a different order, making no attempt to +converge on a global consensus):
+Read-your-own-writes: eventual consistency does NOT guarantee that a write to a given key +followed by a read from the same key will retrieve the same or newer value.
+Convergence: eventual consistency does NOT guarantee that any two replicas will agree on the +value for a given key -- even after all writes have had time to propagate to all replicas.
+Last-write-wins: eventual consistency does NOT guarantee that the most recent write will +take precendence over an earlier one; old writes may overwrite newer ones temporarily or +permanently.
+This interface does not currently make any hard guarantees about the durability of values
+stored. A valid implementation might rely on an in-memory hash table, the contents of which are
+lost when the process exits. Alternatively, another implementation might synchronously persist
+all writes to disk -- or even to a quorum of disk-backed nodes at multiple locations -- before
+returning a result for a set
call. Finally, a third implementation might persist values
+asynchronously on a best-effort basis without blocking set
calls, in which case an I/O error
+could occur after the component instance which originally made the call has exited.
Future versions of wasi:keyvalue
may provide ways to query and control the durability and
+consistency provided by the backing implementation.
variant error
resource bucket
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 +
It is worth noting that the exact terminology for bucket in key-value stores can vary depending on the specific implementation. For example:
bucket
to refer to a collection of key-value pairsIn this interface, we use the term bucket
to refer to a connection to a collection of
+key-value pairs.
bucket
resources using the same identifier MAY result in connections
+to two separate replicas in a distributed database, and that writes to one of those
+resources are not guaranteed to be readable from the other resource promptly (or ever, in
+the case of a replica failure or message reordering). See the Consistency
section of the
+store
interface documentation for details.open: func
Get the bucket with the specified identifier.
diff --git a/wit/store.wit b/wit/store.wit index a35c2d4..5d999b8 100644 --- a/wit/store.wit +++ b/wit/store.wit @@ -7,22 +7,52 @@ /// 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. +/// +/// ## Consistency /// -/// 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 +/// An implementation of this interface MUST be eventually consistent, but is not required to +/// provide any consistency guaranteeds beyond that. Practically speaking, eventual consistency is +/// among the weakest of consistency models, guaranteeing only that values will not be produced +/// "from nowhere", i.e. any value read is guaranteed to have been written to that key at some +/// earlier time. Beyond that, there are no guarantees, and thus a portable component must neither +/// expect nor rely on anything else. +/// +/// In the future, additional interfaces may be added to `wasi:keyvalue` with stronger guarantees, +/// which will allow components to express their requirements by importing whichever interface(s) +/// provides matching (or stronger) guarantees. For example, a component requiring strict +/// serializability might import a (currently hypothetical) `strict-serializable-store` interface +/// with a similar signature to `store` but with much stronger semantic guarantees. On the other +/// end, a host might either support implementations of both the `store` and +/// `strict-serializable-store` or just the former, in which case the host would immediately reject +/// a component which imports the unsupported interface. +/// +/// Here are a few examples of behavior which a component developer might wish to rely on but which +/// are _NOT_ guaranteed by an eventually consistent system (e.g. a distributed system composed of +/// multiple replicas, each of which may receive writes in a different order, making no attempt to +/// converge on a global consensus): +/// +/// - Read-your-own-writes: eventual consistency does _NOT_ guarantee that a write to a given key +/// followed by a read from the same key will retrieve the same or newer value. +/// +/// - Convergence: eventual consistency does _NOT_ guarantee that any two replicas will agree on the +/// value for a given key -- even after all writes have had time to propagate to all replicas. +/// +/// - Last-write-wins: eventual consistency does _NOT_ guarantee that the most recent write will +/// take precendence over an earlier one; old writes may overwrite newer ones temporarily or +/// permanently. +/// +/// ## Durability +/// +/// This interface does not currently make any hard guarantees about the durability of values +/// stored. A valid implementation might rely on an in-memory hash table, the contents of which are +/// lost when the process exits. Alternatively, another implementation might synchronously persist +/// all writes to disk -- or even to a quorum of disk-backed nodes at multiple locations -- before +/// returning a result for a `set` call. Finally, a third implementation might persist values +/// asynchronously on a best-effort basis without blocking `set` calls, in which case an I/O error +/// could occur after the component instance which originally made the call has exited. +/// +/// Future versions of `wasi:keyvalue` may provide ways to query and control the durability and +/// consistency provided by the backing implementation. interface store { /// The set of errors which may be raised by functions in this package variant error { @@ -56,7 +86,7 @@ interface store { /// 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 + /// 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 @@ -67,7 +97,14 @@ interface store { /// 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 + /// In this interface, we use the term `bucket` to refer to a connection to a collection of + /// key-value pairs. + /// + /// Note that opening two `bucket` resources using the same identifier MAY result in connections + /// to two separate replicas in a distributed database, and that writes to one of those + /// resources are not guaranteed to be readable from the other resource promptly (or ever, in + /// the case of a replica failure or message reordering). See the `Consistency` section of the + /// `store` interface documentation for details. resource bucket { /// Get the value associated with the specified `key` ///