repos / starfx

supercharged async flow control library.
git clone https://github.com/neurosnap/starfx.git

starfx / fx
Eric Bower · 23 Feb 24

race.ts

 1import type { Callable, Operation, Task } from "../deps.ts";
 2import { action, call, resource, spawn } from "../deps.ts";
 3
 4interface OpMap<T = unknown> {
 5  [key: string]: Callable<T>;
 6}
 7
 8export function raceMap<T>(
 9  opMap: OpMap,
10): Operation<
11  {
12    [K in keyof OpMap<T>]: OpMap[K] extends (...args: any[]) => any
13      ? ReturnType<OpMap[K]>
14      : OpMap[K];
15  }
16> {
17  return resource(function* Race(provide) {
18    const keys = Object.keys(opMap);
19    const taskMap: { [key: string]: Task<unknown> } = {};
20    const resultMap: { [key: keyof OpMap]: OpMap[keyof OpMap] } = {};
21
22    const winner = yield* action<Task<unknown>>(function* (resolve) {
23      for (let i = 0; i < keys.length; i += 1) {
24        const key = keys[i];
25        yield* spawn(function* () {
26          const task = yield* spawn(function* () {
27            yield* call(opMap[key] as any);
28          });
29          taskMap[key] = task;
30          (resultMap as any)[key] = yield* task;
31          resolve(task);
32        });
33      }
34    });
35
36    for (let i = 0; i < keys.length; i += 1) {
37      const key = keys[i];
38      const task = taskMap[key];
39      if (task === winner) {
40        continue;
41      }
42
43      yield* spawn(() => task.halt());
44    }
45
46    yield* provide(resultMap);
47  });
48}