@yieldstar/runtime-conformance 0.0.0-stage → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -2
- package/dist/effect.d.ts +33 -0
- package/dist/effect.d.ts.map +1 -0
- package/dist/execution.d.ts +36 -0
- package/dist/execution.d.ts.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3852 -0
- package/package.json +35 -3
package/README.md
CHANGED
|
@@ -1,3 +1,104 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@yieldstar/runtime-conformance`
|
|
2
|
+
|
|
3
|
+
This package contains the runnable qualification suites for YieldStar runtimes: one for store connectors, one for the execution client and one for the effect client. The normative protocol is documented in the [store connector conformance specification](https://github.com/notationlabs/yieldstar/blob/main/docs/store-connector-spec.md).
|
|
4
|
+
|
|
5
|
+
Install it with the test runner and core package:
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pnpm add -D @yieldstar/core @yieldstar/runtime-conformance vitest
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Register the suite from a Vitest test file. The only required integration point is a factory that creates a clean backend and returns a `Runtime` built on it. Store wakes are observed through the runtime's `ExecutionClient`: the suite admits the executions that wait on stores, and a commit that satisfies a waiter must make that execution due, so `runtime.executions.claimDue()` returns it.
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { registerStoreClientConformance } from "@yieldstar/runtime-conformance";
|
|
15
|
+
import { MyRuntime } from "./my-runtime";
|
|
16
|
+
|
|
17
|
+
registerStoreClientConformance({
|
|
18
|
+
name: "my-store",
|
|
19
|
+
create() {
|
|
20
|
+
const backend = createCleanBackend();
|
|
21
|
+
return {
|
|
22
|
+
runtime: new MyRuntime(backend),
|
|
23
|
+
dispose: () => backend.close(),
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The base factory qualifies a process-local runtime. A backend that supports multiple clients should also return `createPeer`, a runtime over the same backend as another process would open; a durable backend should additionally return `restart`. These capabilities activate the shared-client race and crash-recovery suites:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
create() {
|
|
33
|
+
const backend = createCleanBackend();
|
|
34
|
+
const runtime = new MyRuntime(backend);
|
|
35
|
+
return {
|
|
36
|
+
runtime,
|
|
37
|
+
createPeer: () => new MyRuntime(backend),
|
|
38
|
+
restart: async () => {
|
|
39
|
+
await runtime.close();
|
|
40
|
+
return new MyRuntime(backend.reopen());
|
|
41
|
+
},
|
|
42
|
+
dispose: () => backend.close(),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Run the test with either supported runtime:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
vitest run runtime-conformance.test.ts
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Execution client suite
|
|
54
|
+
|
|
55
|
+
`registerExecutionClientConformance` checks a runtime's `ExecutionClient` and fenced heap writes: admission, wake merging, claims, acknowledgement and terminal outcomes; leases, renewal, release and the `running` status; the redelivery delay and `unacknowledgedDeliveryCount`; fencing of heap writes, renewals, releases and acknowledgements against a stale holder; and `start`, its idempotency by request ID, parameter validation, mismatches and the target's parent link. The suite passes a `clock` to `create`; build every runtime on it so the suite controls time, including lease expiry.
|
|
56
|
+
|
|
57
|
+
The harness has three optional capabilities:
|
|
58
|
+
|
|
59
|
+
- `createPeer` returns another runtime over the same backend, as a second runtime process would. The suite uses it to race two clients for one execution and to reclaim an expired lease from a different client than the one that holds it. Return it whenever several processes can share the backend; without it those cases run both sides on `runtime`, which proves less.
|
|
60
|
+
- `restart` reopens the same durable backend in a new runtime. It enables the restart cases; without it they are skipped.
|
|
61
|
+
- `failStartCommits` makes every new `start` on `runtime` fail after it begins writing but before it commits, and returns a function that stops the failures. It enables the case that a failed start leaves no trace; without it that case is skipped. The SQLite harness installs a temporary trigger that aborts the start-request insert.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { registerExecutionClientConformance } from "@yieldstar/runtime-conformance";
|
|
65
|
+
import { MyRuntime } from "./my-runtime";
|
|
66
|
+
|
|
67
|
+
registerExecutionClientConformance({
|
|
68
|
+
name: "my-runtime",
|
|
69
|
+
create({ clock }) {
|
|
70
|
+
const backend = createCleanBackend();
|
|
71
|
+
return {
|
|
72
|
+
runtime: new MyRuntime(backend, { clock }),
|
|
73
|
+
// A separate connection, as another process would open.
|
|
74
|
+
createPeer: () => new MyRuntime(backend.connect(), { clock }),
|
|
75
|
+
restart: () => new MyRuntime(backend.reopen(), { clock }),
|
|
76
|
+
dispose: () => backend.close(),
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Effect client suite
|
|
83
|
+
|
|
84
|
+
`registerEffectClientConformance` checks a runtime's `EffectClient`: `begin` creating or reading one effect, mismatched operations and inputs, concurrent equal and different settlements and their conflict reports, `watch` registration and immediate wakes, settlement racing `watch`, waiter deletion with the step's result and its rejection for a stale holder, value encoding, and durability across a restart. Its harness takes the same `clock`, `createPeer` and `restart` as the execution client suite, plus `failEffectWatches`, which makes every `watch` on `runtime` fail before it commits and returns a function that stops the failures. Without it the case for a failed watch is skipped; the SQLite harness installs a temporary trigger that aborts the waiter insert.
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { registerEffectClientConformance } from "@yieldstar/runtime-conformance";
|
|
88
|
+
|
|
89
|
+
registerEffectClientConformance({
|
|
90
|
+
name: "my-runtime",
|
|
91
|
+
create({ clock }) {
|
|
92
|
+
const backend = createCleanBackend();
|
|
93
|
+
return {
|
|
94
|
+
runtime: new MyRuntime(backend, { clock }),
|
|
95
|
+
createPeer: () => new MyRuntime(backend.connect(), { clock }),
|
|
96
|
+
restart: () => new MyRuntime(backend.reopen(), { clock }),
|
|
97
|
+
dispose: () => backend.close(),
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The suite covers the runtime adapter. The workflow-driver and delivery cases for `step.start` and `step.effect` are tested in the repository rather than here (`test/start.test.ts`, `test/effect.test.ts` and `test/effect-delivery.test.ts`). The dispatcher and worker cases, such as concurrency, releasing on a retry reply, a worker that exits without replying, and a worker whose runtime process dies, are properties of `ExecutionDispatcher` and the invoker rather than of an adapter; the repository tests them in `test/dispatcher.test.ts` and `test/worker-invoker.test.ts`.
|
|
2
104
|
|
|
3
|
-
This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
|
package/dist/effect.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type Runtime } from "@yieldstar/core";
|
|
2
|
+
export type EffectConformanceHarnessOptions = {
|
|
3
|
+
/** The suite's clock. Construct the runtime with it. */
|
|
4
|
+
clock: () => number;
|
|
5
|
+
};
|
|
6
|
+
/** A clean runtime under test, built on the suite's clock. */
|
|
7
|
+
export type EffectConformanceHarness = {
|
|
8
|
+
runtime: Runtime;
|
|
9
|
+
/**
|
|
10
|
+
* Creates another runtime sharing the same backend, as another process
|
|
11
|
+
* would. Race cases fall back to `runtime` when it is absent.
|
|
12
|
+
*/
|
|
13
|
+
createPeer?(): Runtime | Promise<Runtime>;
|
|
14
|
+
/** Opens the same durable backend in a new runtime, as after a restart. */
|
|
15
|
+
restart?(): Runtime | Promise<Runtime>;
|
|
16
|
+
/**
|
|
17
|
+
* Makes every `watch` on `runtime` fail after it begins writing but before
|
|
18
|
+
* it commits, until the returned function is called. Without it, the case
|
|
19
|
+
* for a failure before a watch commits is skipped.
|
|
20
|
+
*/
|
|
21
|
+
failEffectWatches?(): (() => void | Promise<void>) | Promise<() => void | Promise<void>>;
|
|
22
|
+
dispose?(): void | Promise<void>;
|
|
23
|
+
};
|
|
24
|
+
export type EffectConformanceOptions = {
|
|
25
|
+
name: string;
|
|
26
|
+
create(options: EffectConformanceHarnessOptions): EffectConformanceHarness | Promise<EffectConformanceHarness>;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Registers the runtime-adapter suite for `EffectClient` and the wakes it
|
|
30
|
+
* requests (RFC 005).
|
|
31
|
+
*/
|
|
32
|
+
export declare function registerEffectClientConformance({ name, create, }: EffectConformanceOptions): void;
|
|
33
|
+
//# sourceMappingURL=effect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effect.d.ts","sourceRoot":"","sources":["../src/effect.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,OAAO,EACb,MAAM,iBAAiB,CAAC;AAGzB,MAAM,MAAM,+BAA+B,GAAG;IAC5C,wDAAwD;IACxD,KAAK,EAAE,MAAM,MAAM,CAAC;CACrB,CAAC;AAEF,8DAA8D;AAC9D,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1C,2EAA2E;IAC3E,OAAO,CAAC,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC;;;;OAIG;IACH,iBAAiB,CAAC,IACd,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAC5B,OAAO,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACxC,OAAO,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CACJ,OAAO,EAAE,+BAA+B,GACvC,wBAAwB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;CACjE,CAAC;AA8BF;;;GAGG;AACH,wBAAgB,+BAA+B,CAAC,EAC9C,IAAI,EACJ,MAAM,GACP,EAAE,wBAAwB,GAAG,IAAI,CA6rBjC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type Runtime } from "@yieldstar/core";
|
|
2
|
+
export type ExecutionConformanceHarnessOptions = {
|
|
3
|
+
/**
|
|
4
|
+
* The suite's clock. Construct the runtime with it, so due times, lease
|
|
5
|
+
* expiry and redelivery delays are deterministic.
|
|
6
|
+
*/
|
|
7
|
+
clock: () => number;
|
|
8
|
+
};
|
|
9
|
+
/** A clean runtime under test, built on the suite's clock. */
|
|
10
|
+
export type ExecutionConformanceHarness = {
|
|
11
|
+
runtime: Runtime;
|
|
12
|
+
/**
|
|
13
|
+
* Creates another runtime sharing the same backend, as another process
|
|
14
|
+
* would. Cases that need one fall back to `runtime` when it is absent.
|
|
15
|
+
*/
|
|
16
|
+
createPeer?(): Runtime | Promise<Runtime>;
|
|
17
|
+
/** Opens the same durable backend in a new runtime, as after a restart. */
|
|
18
|
+
restart?(): Runtime | Promise<Runtime>;
|
|
19
|
+
/**
|
|
20
|
+
* Makes every new start on `runtime` fail after it begins writing but before
|
|
21
|
+
* it commits, until the returned function is called. Without it, the case
|
|
22
|
+
* for a failure before a start commits is skipped.
|
|
23
|
+
*/
|
|
24
|
+
failStartCommits?(): (() => void | Promise<void>) | Promise<() => void | Promise<void>>;
|
|
25
|
+
dispose?(): void | Promise<void>;
|
|
26
|
+
};
|
|
27
|
+
export type ExecutionConformanceOptions = {
|
|
28
|
+
name: string;
|
|
29
|
+
create(options: ExecutionConformanceHarnessOptions): ExecutionConformanceHarness | Promise<ExecutionConformanceHarness>;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Registers the runtime-adapter suite for `ExecutionClient` and fenced heap
|
|
33
|
+
* writes (RFC 001, RFC 002 and RFC 003).
|
|
34
|
+
*/
|
|
35
|
+
export declare function registerExecutionClientConformance({ name, create, }: ExecutionConformanceOptions): void;
|
|
36
|
+
//# sourceMappingURL=execution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../src/execution.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,OAAO,EAGb,MAAM,iBAAiB,CAAC;AAGzB,MAAM,MAAM,kCAAkC,GAAG;IAC/C;;;OAGG;IACH,KAAK,EAAE,MAAM,MAAM,CAAC;CACrB,CAAC;AAEF,8DAA8D;AAC9D,MAAM,MAAM,2BAA2B,GAAG;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1C,2EAA2E;IAC3E,OAAO,CAAC,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC;;;;OAIG;IACH,gBAAgB,CAAC,IAAI,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACxF,OAAO,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CACJ,OAAO,EAAE,kCAAkC,GAC1C,2BAA2B,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;CACvE,CAAC;AAwDF;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,EACjD,IAAI,EACJ,MAAM,GACP,EAAE,2BAA2B,GAAG,IAAI,CAg/DpC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type Runtime } from "@yieldstar/core";
|
|
2
|
+
export { registerEffectClientConformance, type EffectConformanceHarness, type EffectConformanceHarnessOptions, type EffectConformanceOptions, } from "./effect";
|
|
3
|
+
export { registerExecutionClientConformance, type ExecutionConformanceHarness, type ExecutionConformanceHarnessOptions, type ExecutionConformanceOptions, } from "./execution";
|
|
4
|
+
/**
|
|
5
|
+
* A clean runtime under test. Store wakes are observed through its
|
|
6
|
+
* `ExecutionClient`: a commit that satisfies a waiter makes the waiter's
|
|
7
|
+
* execution due, so `runtime.executions.claimDue()` returns it.
|
|
8
|
+
*/
|
|
9
|
+
export type StoreConformanceHarness = {
|
|
10
|
+
runtime: Runtime;
|
|
11
|
+
/** Creates another runtime connected to the same backend. */
|
|
12
|
+
createPeer?(): Runtime | Promise<Runtime>;
|
|
13
|
+
/** Simulates opening the same durable backend in a new process. */
|
|
14
|
+
restart?(): Runtime | Promise<Runtime>;
|
|
15
|
+
dispose?(): void | Promise<void>;
|
|
16
|
+
};
|
|
17
|
+
export type StoreConformanceFactory = () => StoreConformanceHarness | Promise<StoreConformanceHarness>;
|
|
18
|
+
export type StoreConformanceOptions = {
|
|
19
|
+
name: string;
|
|
20
|
+
create: StoreConformanceFactory;
|
|
21
|
+
};
|
|
22
|
+
/** Registers the normative YieldStar store connector qualification suite. */
|
|
23
|
+
export declare function registerStoreClientConformance({ name, create, }: StoreConformanceOptions): void;
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,OAAO,EAKb,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,+BAA+B,EAC/B,KAAK,wBAAwB,EAC7B,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,GAC9B,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,kCAAkC,EAClC,KAAK,2BAA2B,EAChC,KAAK,kCAAkC,EACvC,KAAK,2BAA2B,GACjC,MAAM,aAAa,CAAC;AAErB;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,6DAA6D;IAC7D,UAAU,CAAC,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1C,mEAAmE;IACnE,OAAO,CAAC,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,OAAO,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,MAClC,uBAAuB,GACvB,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAErC,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,uBAAuB,CAAC;CACjC,CAAC;AAkJF,6EAA6E;AAC7E,wBAAgB,8BAA8B,CAAC,EAC7C,IAAI,EACJ,MAAM,GACP,EAAE,uBAAuB,GAAG,IAAI,CA+9ChC"}
|