From 99514bd130bfbc46846f21a100fcd0c982075079 Mon Sep 17 00:00:00 2001 From: David Justice Date: Sat, 6 Jan 2024 16:41:32 -0500 Subject: [PATCH] initial interface definition for distributed locks Signed-off-by: David Justice --- README.md | 66 +++++++++++++++++++++++++++++++++++----- proposal-template.abi.md | 31 ------------------- proposal-template.wit.md | 32 ------------------- wit/lock.wit | 8 +++++ wit/types.wit | 23 ++++++++++++++ wit/world.wit | 5 +++ 6 files changed, 95 insertions(+), 70 deletions(-) delete mode 100644 proposal-template.abi.md delete mode 100644 proposal-template.wit.md create mode 100644 wit/lock.wit create mode 100644 wit/types.wit create mode 100644 wit/world.wit diff --git a/README.md b/README.md index 48ae47b..8d1d01e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# `wasi-distributed-lock-service` +# `wasi-distributed-lock` A proposed [WebAssembly System Interface](https://github.com/WebAssembly/WASI) API. ### Current Phase -`wasi-distributed-lock-service` is currently in [Phase 1](https://github.com/WebAssembly/WASI/blob/main/Proposals.md#phase-1---feature-proposal-cg). +`wasi-distributed-lock` is currently in [Phase 1](https://github.com/WebAssembly/WASI/blob/main/Proposals.md#phase-1---feature-proposal-cg). ### Champions @@ -14,18 +14,70 @@ A proposed [WebAssembly System Interface](https://github.com/WebAssembly/WASI) A ### Phase 4 Advancement Criteria -`wasi-distributed-lock-service` should have at least two implementations (i.e., from service providers, and or cloud providers), and, at the very minimum, pass the testsuite for Windows, Linux, and MacOS. +`wasi-distributed-lock` should have at least two implementations (i.e., from service providers, and or cloud providers), and, at the very minimum, pass the test suite for Windows, Linux, and MacOS. ## Table of Contents - [Introduction](#introduction) +- [Goals](#goals) +- [Non-Goals](#non-goals) +- [API Walk-through](#api-walk-through) + - [Use Case - Leader Election](#use-case---leader-election) +- [Detailed Design Discussion](#detailed-design-discussion) +- [Considered Alternatives](#considered-alternatives) +- [Stakeholder Interest and Feedback](#stakeholder-interest-and-feedback) +- [References and Acknowledgements](#references-and-acknowledgements) ### Introduction -The `wasi-distributed-lock-service` world aim to provide a set of generic interfaces for distributed lock services which provide mechanisms to ensure that only one process can mutate a particular state at a time. They are often used to prevent race conditions in scenarios where two or more processes attempting to update the same state at the same time that could result in data inconsistencies. +The `wasi-distributed-lock` world aim to provide a set of generic interfaces for distributed locking which provides mechanisms to ensure that only one process can mutate a particular state at a time. They are often used to prevent race conditions in scenarios where two or more processes attempting to update the same state at the same time that could result in data inconsistencies. -For example, in a e-commerce application, when a popular item is back in stock, a distributed lock service can be used to ensure that stock is not oversold by multiple processes attempting to update the stock count at the same time. +For example, in a e-commerce application, when a popular item is back in stock, a distributed lock can be used to ensure that stock is not oversold by multiple processes attempting to update the stock count at the same time. -### TODO +### Goals + +The primary goal of this API is to allow users to write distributed applications which require coarse grained, synchronized access +to shared state. + +### Non Goals +- Provide a fine grained, generic, high frequency locking mechanism + +### API Walk-through + +#### Use Case - Leader Election +**TODO** + +### Detailed Design Discussion +The `wasi-distributed-lock` world consists of the `locker` interface, which enables consumers to +acquire a lock (lease) on a key for a specified time to live (ttl) returning the `lock` resource. + +``` +/// acquire will attempt to obtain a lease for a given string key for a time to live (ttl) +/// in milliseconds. +acquire: func(key: string, ttl: milliseconds) -> result; +``` + +The `lock` resource is a handle to the lease and enable consumers to release the lock (lease) on the key. +``` +/// lock resource is a handle to a named lease which can be released when work is completed. +resource lock { + /// release the lease for this lock. This can only be called once. + release: func() -> result<_, error>; +} +``` + +### Considered Alternatives +#### Use of WASI KeyValue +With most key value stores, it is relatively trivial to implement a distributed lock. Given that +WASI-Cloud-Core contains a key value interface, it would be reasonable to expect that implementors could use it to create distributed locks for themselves. + +It is the opinion of this proposal that distributed locking is a fundamental building block of distributed applications and is prone to errors in implementation. It is with that in mind that the distributed lock interface should be provided as a WASI-Cloud-Core rather than expecting developer to implement distributed locks themselves. + +Kubernetes is a great example of an application platform that provides distributed locks as part of the platform with great success for the developer population building applications in the Kubernetes ecosystem. + +### Stakeholder Interest and Feedback +**TODO** + +### References and Acknowledgements +**TODO** -This readme needs to be expanded to cover a number of additional fields suggested in the [WASI Proposal template](https://github.com/WebAssembly/wasi-proposal-template). diff --git a/proposal-template.abi.md b/proposal-template.abi.md deleted file mode 100644 index 7a1c372..0000000 --- a/proposal-template.abi.md +++ /dev/null @@ -1,31 +0,0 @@ -# Types - -## `api-type-one`: record - - Short description - - Explanation for developers using the API. - -Size: 16, Alignment: 8 - -### Record Fields - -- [`property1`](#api_type_one.property1): `u64` - - -- [`property2`](#api_type_one.property2): `string` - - -# Functions - ----- - -#### `api-function-one` - - Short description - - Explanation for developers using the API. -##### Results - -- [`api-type-one`](#api_type_one) - diff --git a/proposal-template.wit.md b/proposal-template.wit.md deleted file mode 100644 index 3c7e8ef..0000000 --- a/proposal-template.wit.md +++ /dev/null @@ -1,32 +0,0 @@ -# [Proposal Template] API - -[This document contains the actual specification. It should be written in the WIT interface definition format. You can find more documentation on the WIT syntax (coming soon!).] - -[Note that all comments inside of WIT code blocks will be included in the developer facing documentation for language bindings generated using this WIT file. If there is additional information that needs to be communicated to implementers of the API, then these should be captured in text directly below the code block.] - -[If you want to include examples of the API in use, these should be in the README and linked to from this file.] - -## api_type_one - -```wit -/// Short description -/// -/// Explanation for developers using the API. -record api-type-one { - property1: u64, - property2: string, -} -``` - -More rigorous specification details for the implementer go here, if needed. - -## api_function_one - -```wit -/// Short description -/// -/// Explanation for developers using the API. -api-function-one: func() -> api-type-one -``` - -If needed, this would explain what a compliant implementation MUST do, such as never returning an earlier result from a later call. diff --git a/wit/lock.wit b/wit/lock.wit new file mode 100644 index 0000000..014b8bb --- /dev/null +++ b/wit/lock.wit @@ -0,0 +1,8 @@ +/// locker interface provides the ability to acquire locks +interface locker { + use types.{milliseconds, error, lock}; + + /// acquire will attempt to obtain a lease for a given string key for a time to live (ttl) + /// in milliseconds. + acquire: func(key: string, ttl: milliseconds) -> result; +} \ No newline at end of file diff --git a/wit/types.wit b/wit/types.wit new file mode 100644 index 0000000..d37f412 --- /dev/null +++ b/wit/types.wit @@ -0,0 +1,23 @@ +interface types { + // milliseconds is the u32 number of milliseconds + type milliseconds = u32; + + /// Errors that can be returned from the locker + variant error { + /// not-acquired error indicates the lock was not acquired because it has already been + /// acquired by another entity. + not-acquired(string), + /// already-released error indicates the lease for the lock has already expired. + lease-expired(string), + /// already-released error indicates the lease for the loack has already been released. + already-released(string), + /// unknown indicates an unexpected error occurred when acquiring or releasing a lock + unknown(string), + }; + + /// lock resource is a handle to a named lease which can be released when work is completed. + resource lock { + /// release the lease for this lock. This can only be called once. + release: func() -> result<_, error>; + } +} \ No newline at end of file diff --git a/wit/world.wit b/wit/world.wit new file mode 100644 index 0000000..434a236 --- /dev/null +++ b/wit/world.wit @@ -0,0 +1,5 @@ +package wasi:distributed-lock@0.1.0 + +world imports { + import locker; +} \ No newline at end of file