From 5b9b548c8ae3ecea0cfc72975b75682fcc53de70 Mon Sep 17 00:00:00 2001
From: Darwin Boersma
Date: Sat, 29 Mar 2025 12:21:55 -0600
Subject: [PATCH] Update CAS interface to remove current and add new-with-read
Signed-off-by: Darwin Boersma
---
README.md | 3 ++-
imports.md | 23 ++++++++++++-----------
watch-service.md | 27 ++++++++++++++-------------
wit/atomic.wit | 25 ++++++++++++++++++-------
wit/world.wit | 2 +-
5 files changed, 47 insertions(+), 33 deletions(-)
diff --git a/README.md b/README.md
index 7a3b673..2d1feed 100644
--- a/README.md
+++ b/README.md
@@ -120,7 +120,8 @@ This proposal was inspired by Dapr's [State API]
[State API](https://docs.dapr.io/developing-applications/building-blocks/state-management/)
### Change log
-
+- 2025-03-29:
+ - Modified `atomics` interface signature
- 2024-03-29:
- Simplified interfaces to 3 key pieces of functionality: store, atomics, and batch. Also removed
the use of streams to simplify the starting point of the API
diff --git a/imports.md b/imports.md
index ca31a78..28536b7 100644
--- a/imports.md
+++ b/imports.md
@@ -9,13 +9,13 @@ Components targeting this world will be able to do:
A keyvalue interface that provides atomic operations.
Atomic operations are single, indivisible operations. When a fault causes an atomic operation to
fail, it will appear to the invoker of the atomic operation that the action either completed
@@ -226,16 +226,17 @@ latest version or transaction.
Get the current value of the key (if it exists). This allows for avoiding reads if all
-that is needed to ensure the atomicity of the operation
+
[static]cas.new_with_read: func
+
Construct a new CAS operation returning the current value. Implementors can map the underlying functionality
+(transactions, versions, etc) as desired.
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
diff --git a/watch-service.md b/watch-service.md
index a65115a..c144319 100644
--- a/watch-service.md
+++ b/watch-service.md
@@ -2,18 +2,18 @@
A keyvalue interface that provides atomic operations.
Atomic operations are single, indivisible operations. When a fault causes an atomic operation to
fail, it will appear to the invoker of the atomic operation that the action either completed
@@ -224,16 +224,17 @@ latest version or transaction.
Get the current value of the key (if it exists). This allows for avoiding reads if all
-that is needed to ensure the atomicity of the operation
+
[static]cas.new_with_read: func
+
Construct a new CAS operation returning the current value. Implementors can map the underlying functionality
+(transactions, versions, etc) as desired.
diff --git a/wit/atomic.wit b/wit/atomic.wit
index 87d562a..10289b4 100644
--- a/wit/atomic.wit
+++ b/wit/atomic.wit
@@ -16,19 +16,30 @@ interface atomics {
/// A store error occurred when performing the operation
store-error(error),
/// The CAS operation failed because the value was too old. This returns a new CAS handle
- /// for easy retries. Implementors MUST return a CAS handle that has been updated to the
+ /// for easy retries, as well as the current value for comparison. Implementors MUST return a CAS handle that has been updated to the
/// latest version or transaction.
- cas-failed(cas),
+ cas-failed(tuple>>),
}
/// A handle to a CAS (compare-and-swap) operation.
resource cas {
- /// Construct a new CAS operation. Implementors can map the underlying functionality
- /// (transactions, versions, etc) as desired.
+ /// Construct a new CAS handle for `key`.
+ ///
+ /// This handle should guarantee that a subsequent `swap` operation will operate on data that has
+ /// not been modified since this call. If that condition is not met, `swap` should return `error`.
+ ///
+ /// Note that this handle does not necessarily guarantee that no other operations occur on the key
+ /// after the handle is created, only that `error` is returned when calling `swap` if other operations did occur.
new: static func(bucket: borrow, key: string) -> result;
- /// Get the current value of the key (if it exists). This allows for avoiding reads if all
- /// that is needed to ensure the atomicity of the operation
- current: func() -> result