@akterjs/conformance 0.1.1 → 0.1.3

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 CHANGED
@@ -29,7 +29,7 @@ The computer guarantees are a second suite, `computerConformanceOf({ engine, ski
29
29
  - a computer step runs once by its key: sent again, even after the engine restarts, it reads back the outcome it recorded
30
30
  - a computer keeps its files across pause, resume, stop and an engine restart
31
31
  - a held computer stays paused, or stopped if it was stopped: an ensure, a step, and a resume or pause without its hold are refused until its hold resumes it
32
- - a computer past the store's limit is refused with ComputerLimitError and makes nothing, and one fits again once another is removed
32
+ - an actor keeps as many computers as it ensures: five all start and are listed, and all five remove
33
33
  - a removed computer is gone with its disk: calls to it fail with ComputerNotFoundError, and ensuring it again starts it empty
34
34
 
35
35
  The fork guarantees are a third suite, `forkConformanceOf({ engine, skip })` from `@akterjs/conformance/fork`, which forks the suite's `acct-1` Ledger into `acct-5`, and its `bench-1` Workbench, with a running and a stopped computer, into `bench-250`, through `ActorHost.fork`. An engine under test serves all four keys, with the Workbench's computers bound both to its jobs and to its fork, and an engine that places an actor by its key puts each fork's key on its parent's shard, because Akter Cloud forks only within a shard (`acct-5` and `bench-250` hash to their parents' shards there). The local engine runs it with `AKTER_LOCAL_COMPUTERS=true` in `tests/engine-conformance.suite.test.ts`.
@@ -17,7 +17,7 @@ declare const guaranteeTitles: {
17
17
  declare const computerGuaranteeTitles: {
18
18
  readonly computerHeldStaysPaused: "a held computer stays paused, or stopped if it was stopped: an ensure, a step, and a resume or pause without its hold are refused until its hold resumes it";
19
19
  readonly computerKeepsFiles: "a computer keeps its files across pause, resume, stop and an engine restart";
20
- readonly computerLimitHolds: "a computer past the store's limit is refused with ComputerLimitError and makes nothing, and one fits again once another is removed";
20
+ readonly computerManyKept: "an actor keeps as many computers as it ensures: five all start and are listed, and all five remove";
21
21
  readonly computerRemovedIsGone: "a removed computer is gone with its disk: calls to it fail with ComputerNotFoundError, and ensuring it again starts it empty";
22
22
  readonly computerStepJournaled: "a durable computer step journals its start and outcome in the actor, and its steps read back newest first, one with its output";
23
23
  readonly computerStepRunsOnce: "a computer step runs once by its key: sent again, even after the engine restarts, it reads back the outcome it recorded";
@@ -18,7 +18,7 @@ const guaranteeTitles = {
18
18
  const computerGuaranteeTitles = {
19
19
  computerHeldStaysPaused: "a held computer stays paused, or stopped if it was stopped: an ensure, a step, and a resume or pause without its hold are refused until its hold resumes it",
20
20
  computerKeepsFiles: "a computer keeps its files across pause, resume, stop and an engine restart",
21
- computerLimitHolds: "a computer past the store's limit is refused with ComputerLimitError and makes nothing, and one fits again once another is removed",
21
+ computerManyKept: "an actor keeps as many computers as it ensures: five all start and are listed, and all five remove",
22
22
  computerRemovedIsGone: "a removed computer is gone with its disk: calls to it fail with ComputerNotFoundError, and ensuring it again starts it empty",
23
23
  computerStepJournaled: "a durable computer step journals its start and outcome in the actor, and its steps read back newest first, one with its output",
24
24
  computerStepRunsOnce: "a computer step runs once by its key: sent again, even after the engine restarts, it reads back the outcome it recorded",
@@ -132,41 +132,18 @@ const heldStaysPaused = (storage) => onBench(storage, (host) => Effect.gen(funct
132
132
  ]);
133
133
  yield* stoppedStaysStopped(host);
134
134
  }));
135
- const tried = 8;
136
- const none = 0;
137
- const first = 1;
138
- /** `value` `count` times, for a count from none to `tried`. */
139
- const times = (value, count) => Array.take(Array.replicate(value, tried), count);
135
+ const many = 5;
140
136
  const listed = (names) => `[${Array.join(Array.sort(names, String$1.Order), ",")}]`;
141
- const limitHolds = (storage) => onBench(storage, (host) => Effect.gen(function* fillThenFree() {
142
- const names = Array.makeBy(tried, (index) => `c${String(index)}`);
143
- const filled = yield* ran(host, "l-1", [...Array.map(names, ensure), list]);
144
- const made = Array.takeWhile(filled, (outcome) => outcome === "up").length;
145
- const refused = `ComputerLimitError store ${String(made)}`;
146
- const kept = Array.take(names, made);
147
- const freed = yield* ran(host, "l-2", [
148
- remove("c0"),
149
- ensure("again"),
150
- ensure("more"),
151
- list
152
- ]);
137
+ const manyKept = (storage) => onBench(storage, (host) => Effect.gen(function* ensureMany() {
138
+ const names = Array.makeBy(many, (index) => `c${String(index)}`);
139
+ const kept = yield* ran(host, "m-1", [...Array.map(names, ensure), list]);
140
+ const removed = yield* ran(host, "m-2", [...Array.map(names, remove), list]);
153
141
  expect({
154
- filled,
155
- freed,
156
- made: made > none && made < tried
142
+ kept,
143
+ removed
157
144
  }).toStrictEqual({
158
- filled: [
159
- ...times("up", made),
160
- ...times(refused, tried - made),
161
- listed(kept)
162
- ],
163
- freed: [
164
- "removed",
165
- "up",
166
- refused,
167
- listed([...Array.drop(kept, first), "again"])
168
- ],
169
- made: true
145
+ kept: [...Array.replicate("up", many), listed(names)],
146
+ removed: [...Array.replicate("removed", many), listed([])]
170
147
  });
171
148
  }));
172
149
  const removedIsGone = (storage) => onBench(storage, (host) => Effect.gen(function* removeThenEnsure() {
@@ -301,7 +278,7 @@ const stepSurvivesRestart = (storage) => Effect.gen(function* cutThenReplay() {
301
278
  const computerGuarantees = {
302
279
  computerHeldStaysPaused: heldStaysPaused,
303
280
  computerKeepsFiles: keepsFiles,
304
- computerLimitHolds: limitHolds,
281
+ computerManyKept: manyKept,
305
282
  computerRemovedIsGone: removedIsGone,
306
283
  computerStepJournaled: stepJournaled,
307
284
  computerStepRunsOnce: stepRunsOnce,
@@ -1,5 +1,4 @@
1
1
  import { ComputerOp, Workbench } from "./workbench.contract.mjs";
2
- import { ComputerLimitError } from "@akterjs/effect/contract/errors";
3
2
  import { Array, Cause, Effect, Exit, Layer, Option, Predicate, Record, Schema, String as String$1 } from "effect";
4
3
  import { Akter } from "@akterjs/effect/contract";
5
4
  import { Akter as Akter$1 } from "@akterjs/effect";
@@ -12,6 +11,7 @@ const failures = [
12
11
  "ActorUnavailableError",
13
12
  "CallerNotAllowedError",
14
13
  "ComputerHeldError",
14
+ "ComputerLimitError",
15
15
  "ComputerLostError",
16
16
  "ComputerNotFoundError",
17
17
  "ComputersUnavailableError",
@@ -19,7 +19,6 @@ const failures = [
19
19
  "SecretUnavailableError",
20
20
  "UnauthenticatedError"
21
21
  ];
22
- const isLimit = Schema.is(ComputerLimitError);
23
22
  const isRan = Schema.is(ExecRan);
24
23
  const specOf = (computer) => ({
25
24
  egress: [],
@@ -57,11 +56,8 @@ const called = (client, op) => ComputerOp.match(op, {
57
56
  Step: () => Effect.die("a durable step runs in the job, not in an activity"),
58
57
  Stop: ({ computer }) => Effect.map(client.stop(computer), stateOf)
59
58
  });
60
- /** A failure by its tag; a limit with the limit and its maximum, which the suite checks against what was made. */
61
- const failureOf = (failure) => {
62
- if (isLimit(failure)) return `ComputerLimitError ${failure.limit} ${String(failure.maximum)}`;
63
- return Option.getOrElse(Array.findFirst(failures, (tag) => Predicate.isTagged(failure, tag)), () => "unexpected failure");
64
- };
59
+ /** A failure by its tag. */
60
+ const failureOf = (failure) => Option.getOrElse(Array.findFirst(failures, (tag) => Predicate.isTagged(failure, tag)), () => "unexpected failure");
65
61
  const attempted = (key, op) => Effect.flatMap(Workbench.computer(key), (client) => called(client, op));
66
62
  const answered = (key, op) => Effect.match(attempted(key, op), {
67
63
  onFailure: failureOf,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akterjs/conformance",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "The test suite every Akter engine must pass: the local engine here and the production engine on Akter Cloud.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -48,9 +48,9 @@
48
48
  "provenance": true
49
49
  },
50
50
  "devDependencies": {
51
- "@akterjs/client": "0.1.1",
52
- "@akterjs/effect": "0.1.1",
53
- "@akterjs/sdk": "0.1.1",
51
+ "@akterjs/client": "0.1.3",
52
+ "@akterjs/effect": "0.1.3",
53
+ "@akterjs/sdk": "0.1.3",
54
54
  "@effect/platform-node": "4.1.2",
55
55
  "@effect/vitest": "4.1.2",
56
56
  "effect": "4.1.2",
@@ -60,9 +60,9 @@
60
60
  "zod": "4.6.7"
61
61
  },
62
62
  "peerDependencies": {
63
- "@akterjs/client": "0.1.1",
64
- "@akterjs/effect": "0.1.1",
65
- "@akterjs/sdk": "0.1.1",
63
+ "@akterjs/client": "0.1.3",
64
+ "@akterjs/effect": "0.1.3",
65
+ "@akterjs/sdk": "0.1.3",
66
66
  "@effect/vitest": "4.1.2",
67
67
  "effect": "4.1.2",
68
68
  "vitest": "5.1.0",
@@ -27,8 +27,8 @@ const computerGuaranteeTitles = {
27
27
  computerHeldStaysPaused:
28
28
  "a held computer stays paused, or stopped if it was stopped: an ensure, a step, and a resume or pause without its hold are refused until its hold resumes it",
29
29
  computerKeepsFiles: "a computer keeps its files across pause, resume, stop and an engine restart",
30
- computerLimitHolds:
31
- "a computer past the store's limit is refused with ComputerLimitError and makes nothing, and one fits again once another is removed",
30
+ computerManyKept:
31
+ "an actor keeps as many computers as it ensures: five all start and are listed, and all five remove",
32
32
  computerRemovedIsGone:
33
33
  "a removed computer is gone with its disk: calls to it fail with ComputerNotFoundError, and ensuring it again starts it empty",
34
34
  computerStepJournaled:
@@ -161,31 +161,20 @@ const heldStaysPaused = <Failure>(storage: Storage<Failure>): Checked<Failure> =
161
161
  }),
162
162
  );
163
163
 
164
- const tried = 8;
165
-
166
- const none = 0;
167
-
168
- const first = 1;
169
-
170
- /** `value` `count` times, for a count from none to `tried`. */
171
- const times = (value: string, count: number): readonly string[] => Arr.take(Arr.replicate(value, tried), count);
164
+ const many = 5;
172
165
 
173
166
  const listed = (names: readonly string[]): string => `[${Arr.join(Arr.sort(names, Str.Order), ",")}]`;
174
167
 
175
- const limitHolds = <Failure>(storage: Storage<Failure>): Checked<Failure> =>
168
+ const manyKept = <Failure>(storage: Storage<Failure>): Checked<Failure> =>
176
169
  onBench(storage, (host) =>
177
- Effect.gen(function* fillThenFree() {
178
- const names = Arr.makeBy(tried, (index) => `c${String(index)}`);
179
- const filled = yield* ran(host, "l-1", [...Arr.map(names, ensure), list]);
180
- const made = Arr.takeWhile(filled, (outcome) => outcome === "up").length;
181
- const refused = `ComputerLimitError store ${String(made)}`;
182
- const kept = Arr.take(names, made);
183
- const freed = yield* ran(host, "l-2", [remove("c0"), ensure("again"), ensure("more"), list]);
184
-
185
- expect({ filled, freed, made: made > none && made < tried }).toStrictEqual({
186
- filled: [...times("up", made), ...times(refused, tried - made), listed(kept)],
187
- freed: ["removed", "up", refused, listed([...Arr.drop(kept, first), "again"])],
188
- made: true,
170
+ Effect.gen(function* ensureMany() {
171
+ const names = Arr.makeBy(many, (index) => `c${String(index)}`);
172
+ const kept = yield* ran(host, "m-1", [...Arr.map(names, ensure), list]);
173
+ const removed = yield* ran(host, "m-2", [...Arr.map(names, remove), list]);
174
+
175
+ expect({ kept, removed }).toStrictEqual({
176
+ kept: [...Arr.replicate("up", many), listed(names)],
177
+ removed: [...Arr.replicate("removed", many), listed([])],
189
178
  });
190
179
  }),
191
180
  );
@@ -332,7 +321,7 @@ type Guarantee = <Failure>(storage: Storage<Failure>) => Checked<Failure>;
332
321
  const computerGuarantees = {
333
322
  computerHeldStaysPaused: heldStaysPaused,
334
323
  computerKeepsFiles: keepsFiles,
335
- computerLimitHolds: limitHolds,
324
+ computerManyKept: manyKept,
336
325
  computerRemovedIsGone: removedIsGone,
337
326
  computerStepJournaled: stepJournaled,
338
327
  computerStepRunsOnce: stepRunsOnce,
@@ -3,7 +3,6 @@ import { Akter } from "@akterjs/effect/contract";
3
3
  import { ComputerName, ExecRan } from "@akterjs/effect/contract/computer";
4
4
  import type { Computer, ComputerSpec, ExecResult } from "@akterjs/effect/contract/computer";
5
5
  import type { ActorComputerClients } from "@akterjs/effect/contract/computer-clients";
6
- import { ComputerLimitError } from "@akterjs/effect/contract/errors";
7
6
  import {
8
7
  Array as Arr,
9
8
  Cause,
@@ -36,6 +35,7 @@ const failures = [
36
35
  "ActorUnavailableError",
37
36
  "CallerNotAllowedError",
38
37
  "ComputerHeldError",
38
+ "ComputerLimitError",
39
39
  "ComputerLostError",
40
40
  "ComputerNotFoundError",
41
41
  "ComputersUnavailableError",
@@ -44,8 +44,6 @@ const failures = [
44
44
  "UnauthenticatedError",
45
45
  ] as const;
46
46
 
47
- const isLimit = Schema.is(ComputerLimitError);
48
-
49
47
  const isRan = Schema.is(ExecRan);
50
48
 
51
49
  const specOf = (computer: string): ComputerSpec => ({
@@ -102,17 +100,12 @@ const called = (client: ComputerClient, op: ComputerOp): Effect.Effect<string, C
102
100
  Stop: ({ computer }) => Effect.map(client.stop(computer), stateOf),
103
101
  });
104
102
 
105
- /** A failure by its tag; a limit with the limit and its maximum, which the suite checks against what was made. */
106
- const failureOf = (failure: Failed): string => {
107
- if (isLimit(failure)) {
108
- return `ComputerLimitError ${failure.limit} ${String(failure.maximum)}`;
109
- }
110
-
111
- return Option.getOrElse(
103
+ /** A failure by its tag. */
104
+ const failureOf = (failure: Failed): string =>
105
+ Option.getOrElse(
112
106
  Arr.findFirst(failures, (tag) => Predicate.isTagged(failure, tag)),
113
107
  () => "unexpected failure",
114
108
  );
115
- };
116
109
 
117
110
  const attempted = (key: string, op: ComputerOp): Effect.Effect<string, Failed> =>
118
111
  Effect.flatMap(Workbench.computer(key), (client) => called(client, op));