Eric Bower
·
2025-06-06
supervisor.test.ts
1import { take } from "../action.js";
2import { API_ACTION_PREFIX } from "../action.js";
3import {
4 type Operation,
5 call,
6 run,
7 spawn,
8 supervise,
9 superviseBackoff,
10} from "../index.js";
11import { describe, expect, test } from "../test.js";
12import type { ActionWithPayload } from "../types.js";
13
14describe("superviseBackoff", () => {
15 test("should increase number exponentially", () => {
16 const actual: number[] = [];
17 for (let i = 1; i < 15; i += 1) {
18 actual.push(superviseBackoff(i));
19 }
20 expect(actual).toEqual([
21 20, 40, 80, 160, 320, 640, 1280, 2560, 5120, 10240, -1, -1, -1, -1,
22 ]);
23 });
24});
25
26type LogAction = ActionWithPayload<{ message: string }>;
27
28test("should recover with backoff pressure", async () => {
29 const err = console.error;
30 console.error = () => {};
31
32 const actions: LogAction[] = [];
33 const backoff = (attempt: number) => {
34 if (attempt === 4) return -1;
35 return attempt;
36 };
37
38 await run(function* () {
39 function* op(): Operation<void> {
40 throw new Error("boom!");
41 }
42 yield* spawn(function* () {
43 while (true) {
44 const action = yield* take<LogAction["payload"]>("*");
45 actions.push(action);
46 }
47 });
48 yield* call(supervise(op, backoff));
49 });
50
51 expect(actions.length).toEqual(3);
52 expect(actions[0].type).toEqual(`${API_ACTION_PREFIX}supervise`);
53 expect(actions[0].meta).toEqual(
54 "Exception caught, waiting 1ms before restarting operation",
55 );
56 expect(actions[1].type).toEqual(`${API_ACTION_PREFIX}supervise`);
57 expect(actions[1].meta).toEqual(
58 "Exception caught, waiting 2ms before restarting operation",
59 );
60 expect(actions[2].type).toEqual(`${API_ACTION_PREFIX}supervise`);
61 expect(actions[2].meta).toEqual(
62 "Exception caught, waiting 3ms before restarting operation",
63 );
64
65 console.error = err;
66});