@@ -24,53 +24,39 @@ ensuring compatibility between different key-value stores. Note: the clients wil
24
24
serialization/deserialization overhead to be handled by the key-value store. The value could be
25
25
a serialized object from JSON, HTML or vendor-specific data types like AWS S3 objects.</p >
26
26
<h2 >Consistency</h2 >
27
- <p >An implementation of this interface MUST be eventually consistent, meaning that, after some time
28
- with no further updates, all replicas in the (potentially distributed) system will eventually
29
- converge on a consistent state for all values. This allows replicas to temporarily diverge to
30
- ensure low latency and high availability. Implementations based on a centralized or local
31
- backing store may provide a stronger consistency model, but guest components which are intended
32
- to be portable to any <code >wasi-keyvalue</code > implementation should not rely on anything stronger than
33
- eventual consistency.</p >
34
- <p >Given that each <a href =" #bucket " ><code >bucket</code ></a > resource may represent a connection to a different replica in a
35
- distributed system, values read for a given key from two different <a href =" #bucket " ><code >bucket</code ></a >s may differ, even if
36
- those <a href =" #bucket " ><code >bucket</code ></a > resources were opened using the same string identifier. In addition, consecutive
37
- operations on a single <a href =" #bucket " ><code >bucket</code ></a > resource may produce temporarily inconsistent results if
38
- e.g. the implementation is forced to reconnect to a different replica due to a connection
39
- failure. For example, a write followed by a read may not return the value just written, even if
40
- no other recent or subsequent writes have occurred.</p >
41
- <p >Consider the following pseudocode example (and assume we start with an empty store and no other
42
- concurrent activity):</p >
43
- <pre ><code >bucketA = open(" ; foo" ; )
44
- bucketB = open(" ; foo" ; )
45
- bucketA.set(" ; bar" ; , " ; a" ; )
46
-
47
- // These are guaranteed to succeed:
48
- assert bucketA.get(" ; bar" ; ).equals(" ; a" ; ) or bucketA.get(" ; bar" ; ) is None
49
- assert bucketB.get(" ; bar" ; ).equals(" ; a" ; ) or bucketB.get(" ; bar" ; ) is None
50
-
51
- // This is likely to succeed, but not guaranteed; e.g. `bucketA` might need to reconnect to a
52
- // different replica which hasn't received the above write yet. It will _eventually_
53
- // succeed, provided there are no irrecoverable errors which prevent the propagation of the
54
- // write.
55
- assert bucketA.get(" ; bar" ; ).equals(" ; a" ; )
56
-
57
- // Likewise, this will _eventually_ succeed in the absence of irrecoverable errors:
58
- assert bucketB.get(" ; bar" ; ).equals(" ; a" ; )
59
-
60
- bucketB.set(" ; bar" ; , " ; b" ; )
61
- bucketC = open(" ; foo" ; )
62
- value = bucketC.get(" ; bar" ; )
63
-
64
- // This is guaranteed to succeed:
65
- assert value.equals(" ; a" ; ) or value.equals(" ; b" ; ) or value is None
66
- </code ></pre >
67
- <p >In other words, the <code >bucketC</code > resource MAY reflect either the most recent write to the <code >bucketA</code >
68
- resource, or the one to the <code >bucketB</code > resource, or neither, depending on how quickly either of
69
- those writes reached the replica from which the <code >bucketC</code > resource is reading. However,
70
- assuming there are no irrecoverable errors -- such that the state of a replica is irretrievably
71
- lost before it can be propagated -- one of the values (" ; a" ; or " ; b" ; ) MUST eventually be considered
72
- the " ; latest" ; and replicated across the system, at which point all three resources will return
73
- that same value.</p >
27
+ <p >An implementation of this interface MUST be eventually consistent, but is not required to
28
+ provide any consistency guaranteeds beyond that. Practically speaking, eventual consistency is
29
+ among the weakest of consistency models, guaranteeing only that values will not be produced
30
+ " ; from nowhere" ; , i.e. any value read is guaranteed to have been written to that key at some
31
+ earlier time. Beyond that, there are no guarantees, and thus a portable component must neither
32
+ expect nor rely on anything else.</p >
33
+ <p >In the future, additional interfaces may be added to <code >wasi:key-value</code > with stronger guarantees,
34
+ which will allow components to express their requirements by importing whichever interface(s)
35
+ provides matching (or stronger) guarantees. For example, a component requiring strict
36
+ serializability might import a (currently hypothetical) <code >strict-serializable-store</code > interface
37
+ with a similar signature to <code >store</code > but with much stronger semantic guarantees. On the other
38
+ end, a host might either support implementations of both the <code >store</code > and
39
+ <code >strict-serializable-store</code > or just the former, in which case the host would immediately reject
40
+ a component which imports the unsupported interface.</p >
41
+ <p >Here are a few examples of behavior which an component developer might wish to rely on but which
42
+ are <em >NOT</em > guaranteed by an eventually consistent system (e.g. a distributed system composed of
43
+ multiple replicas, each of which may receive writes in a different order, making no attempt to
44
+ converge on a global consensus):</p >
45
+ <ul >
46
+ <li >
47
+ <p >Read-your-own-writes: eventual consistency does <em >NOT</em > guarantee that a write to a given key
48
+ followed by a read from the same key will retrieve the same or newer value.</p >
49
+ </li >
50
+ <li >
51
+ <p >Convergence: eventual consistency does <em >NOT</em > guarantee that any two replicas will agree on the
52
+ value for a given key -- even after all writes have had time to propagate to all replicas.</p >
53
+ </li >
54
+ <li >
55
+ <p >Last-write-wins: eventual consistency does <em >NOT</em > guarantee that the most recent write will
56
+ take precendence over an earlier one; old writes may overwrite newer ones temporarily or
57
+ permanently.</p >
58
+ </li >
59
+ </ul >
74
60
<h2 >Durability</h2 >
75
61
<p >This interface does not currently make any hard guarantees about the durability of values
76
62
stored. A valid implementation might rely on an in-memory hash table, the contents of which are
@@ -79,7 +65,7 @@ all writes to disk -- or even to a quorum of disk-backed nodes at multiple locat
79
65
returning a result for a <code >set</code > call. Finally, a third implementation might persist values
80
66
asynchronously on a best-effort basis without blocking <code >set</code > calls, in which case an I/O error
81
67
could occur after the component instance which originally made the call has exited.</p >
82
- <p >Future versions of the <code >wasi- keyvalue</code > package may provide ways to query and control the
68
+ <p >Future versions of the <code >wasi: keyvalue</code > package may provide ways to query and control the
83
69
durability and consistency provided by the backing implementation.</p >
84
70
<hr />
85
71
<h3 >Types</h3 >
@@ -118,7 +104,7 @@ there are no more keys to fetch.
118
104
<h4 ><a id =" bucket " ></a ><code >resource bucket</code ></h4 >
119
105
<p >A bucket is a collection of key-value pairs. Each key-value pair is stored as a entry in the
120
106
bucket, and the bucket itself acts as a collection of all these entries.</p >
121
- <p >It is worth noting that the exact terminology for bucket in key-value stores can very
107
+ <p >It is worth noting that the exact terminology for bucket in key-value stores can vary
122
108
depending on the specific implementation. For example:</p >
123
109
<ol >
124
110
<li >Amazon DynamoDB calls a collection of key-value pairs a table</li >
@@ -134,8 +120,8 @@ key-value pairs.</p>
134
120
<h2 >Note that opening two <a href =" #bucket " ><code >bucket</code ></a > resources using the same identifier MAY result in connections
135
121
to two separate replicas in a distributed database, and that writes to one of those
136
122
resources are not guaranteed to be readable from the other resource promptly (or ever, in
137
- the case of a replica failure). See the <code >Consistency</code > section of the < code >store</ code > interface
138
- documentation for details.</h2 >
123
+ the case of a replica failure or message reordering ). See the <code >Consistency</code > section of the
124
+ < code >store</ code > interface documentation for details.</h2 >
139
125
<h3 >Functions</h3 >
140
126
<h4 ><a id =" open " ></a ><code >open: func</code ></h4 >
141
127
<p >Get the bucket with the specified identifier.</p >
0 commit comments