nfkit 1.0.4 → 1.0.6

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/build.js ADDED
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env node
2
+ /* build.js - node build.js [all|cjs|esm|types|clean] */
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { builtinModules } = require('module');
6
+
7
+ const DIST_DIR = 'dist';
8
+
9
+ /* ------------------------- utils ------------------------- */
10
+ function readJSONSafe(file, fallback = {}) {
11
+ try {
12
+ const p = path.resolve(process.cwd(), file);
13
+ const txt = fs.readFileSync(p, 'utf8');
14
+ return JSON.parse(txt);
15
+ } catch {
16
+ return fallback;
17
+ }
18
+ }
19
+ function uniq(arr) { return Array.from(new Set(arr)); }
20
+ function ensureDir(p) { fs.mkdirSync(p, { recursive: true }); }
21
+ function rimraf(p) { if (fs.existsSync(p)) fs.rmSync(p, { recursive: true, force: true }); }
22
+
23
+ function depsAsExternal(pkg) {
24
+ const dep = Object.keys(pkg.dependencies || {});
25
+ const peer = Object.keys(pkg.peerDependencies || {});
26
+ const names = uniq([...dep, ...peer]);
27
+ // 覆盖子路径导入(lodash/fp、react/jsx-runtime)
28
+ return uniq(names.flatMap((n) => [n, `${n}/*`]));
29
+ }
30
+ function nodeBuiltinsExternal() {
31
+ // 既包含 'fs' 也包含 'node:fs' 形式
32
+ return uniq([...builtinModules, ...builtinModules.map((m) => `node:${m}`)]);
33
+ }
34
+ async function loadEsbuild() {
35
+ try { return require('esbuild'); }
36
+ catch { const mod = await import('esbuild'); return mod.build ? mod : mod.default; }
37
+ }
38
+ function tsconfigPath() { return fs.existsSync('tsconfig.json') ? 'tsconfig.json' : undefined; }
39
+ function entryPointsFromPkg(/*pkg*/) { return ['index.ts']; }
40
+
41
+ /* ------------------------- esbuild builds ------------------------- */
42
+ async function buildOne(format, options) {
43
+ const esbuild = await loadEsbuild();
44
+ const { external, tsconfig, entryPoints } = options;
45
+ const isCjs = format === 'cjs';
46
+ const outfile = path.join(DIST_DIR, isCjs ? 'index.cjs' : 'index.mjs');
47
+
48
+ ensureDir(path.dirname(outfile));
49
+ console.log(`[build] ${format} -> ${outfile}`);
50
+
51
+ await esbuild.build({
52
+ entryPoints,
53
+ outfile,
54
+ bundle: true,
55
+ sourcemap: true,
56
+ format, // 'cjs' | 'esm'
57
+ platform: isCjs ? 'node' : 'neutral',
58
+ target: isCjs ? 'es2021' : 'esnext',
59
+ external, // deps + peerDeps + node builtins (含 node:*)
60
+ logLevel: 'info',
61
+ ...(tsconfig ? { tsconfig } : {}),
62
+ });
63
+ }
64
+
65
+ /* ------------------------- types via TypeScript API ------------------------- */
66
+ function buildTypesAPI(outDir = DIST_DIR) {
67
+ let ts;
68
+ try { ts = require('typescript'); }
69
+ catch {
70
+ console.error('[types] Missing dependency: typescript');
71
+ process.exit(1);
72
+ }
73
+
74
+ const cfgPath = ts.findConfigFile('./', ts.sys.fileExists, 'tsconfig.json');
75
+
76
+ let fileNames, options;
77
+ if (cfgPath) {
78
+ // 读取 tsconfig.json
79
+ const { config } = ts.readConfigFile(cfgPath, ts.sys.readFile);
80
+ const parsed = ts.parseJsonConfigFileContent(config, ts.sys, path.dirname(cfgPath));
81
+ fileNames = parsed.fileNames;
82
+ options = parsed.options;
83
+ } else {
84
+ // 没有 tsconfig 的降级:仅用 index.ts
85
+ console.warn('[types] tsconfig.json not found; fallback to index.ts with basic options.');
86
+ fileNames = ['index.ts'].filter((f) => fs.existsSync(f));
87
+ options = {
88
+ moduleResolution: 99, // NodeNext(避免引入 enum 名字,用常量值)
89
+ target: 99, // ESNext
90
+ skipLibCheck: true,
91
+ strict: true,
92
+ };
93
+ }
94
+
95
+ // 强制仅输出声明
96
+ options.declaration = true;
97
+ options.emitDeclarationOnly = true;
98
+ options.outDir = outDir;
99
+ // 为了不受 sourceMap/emit 等其它设置影响
100
+ options.noEmitOnError = false;
101
+
102
+ console.log('[types] Generating .d.ts ...');
103
+ const program = ts.createProgram(fileNames, options);
104
+ const pre = ts.getPreEmitDiagnostics(program);
105
+ const emitResult = program.emit();
106
+ const diagnostics = pre.concat(emitResult.diagnostics);
107
+
108
+ if (diagnostics.length) {
109
+ const formatHost = {
110
+ getCanonicalFileName: (p) => p,
111
+ getCurrentDirectory: ts.sys.getCurrentDirectory,
112
+ getNewLine: () => ts.sys.newLine,
113
+ };
114
+ const message = ts.formatDiagnosticsWithColorAndContext(diagnostics, formatHost);
115
+ console.error(message);
116
+ if (emitResult.emitSkipped) {
117
+ throw new Error('[types] Type generation failed.');
118
+ }
119
+ }
120
+ console.log('[types] Declarations generated.');
121
+ }
122
+
123
+ /* ------------------------- main dispatcher ------------------------- */
124
+ (async function main() {
125
+ const sub = (process.argv[2] || 'all').toLowerCase(); // all | cjs | esm | types | clean
126
+
127
+ const pkg = readJSONSafe('package.json');
128
+ const externalFromPkg = depsAsExternal(pkg);
129
+ // 统一 external:依赖 + peer + Node 内置(含 node:*)
130
+ const external = uniq([...externalFromPkg, ...nodeBuiltinsExternal()]);
131
+ const tscPath = tsconfigPath();
132
+ const entryPoints = entryPointsFromPkg(pkg);
133
+
134
+ switch (sub) {
135
+ case 'clean': {
136
+ console.log('[clean] remove dist/');
137
+ rimraf(DIST_DIR);
138
+ break;
139
+ }
140
+ case 'cjs': {
141
+ await buildOne('cjs', { external, tsconfig: tscPath, entryPoints });
142
+ break;
143
+ }
144
+ case 'esm': {
145
+ await buildOne('esm', { external, tsconfig: tscPath, entryPoints });
146
+ break;
147
+ }
148
+ case 'types': {
149
+ ensureDir(DIST_DIR);
150
+ buildTypesAPI(DIST_DIR);
151
+ break;
152
+ }
153
+ case 'all':
154
+ default: {
155
+ console.log('[clean] remove dist/');
156
+ rimraf(DIST_DIR);
157
+ await buildOne('cjs', { external, tsconfig: tscPath, entryPoints });
158
+ await buildOne('esm', { external, tsconfig: tscPath, entryPoints });
159
+ buildTypesAPI(DIST_DIR);
160
+ console.log('[build] Done.');
161
+ break;
162
+ }
163
+ }
164
+ })().catch((err) => {
165
+ console.error('[build] Failed:', err);
166
+ process.exit(1);
167
+ });
package/dist/index.cjs CHANGED
@@ -19,6 +19,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  // index.ts
20
20
  var index_exports = {};
21
21
  __export(index_exports, {
22
+ RoundRobin: () => RoundRobin,
22
23
  WF_NODE: () => WF_NODE,
23
24
  WorkflowDispatcher: () => WorkflowDispatcher,
24
25
  dualizeAny: () => dualizeAny,
@@ -119,13 +120,12 @@ function makeProxy(node) {
119
120
  // src/dual-object.ts
120
121
  var isThenKey = (k) => k === "then" || k === "catch" || k === "finally";
121
122
  function dualizeAny(sync, asyncFn, options) {
122
- var _a;
123
123
  let state = "undecided";
124
124
  let value;
125
125
  let reason;
126
126
  let p;
127
127
  const asyncMethodSet = new Set(
128
- (_a = options == null ? void 0 : options.asyncMethods) != null ? _a : []
128
+ options?.asyncMethods ?? []
129
129
  );
130
130
  const startAsync = () => {
131
131
  if (!p || state === "undecided") {
@@ -183,9 +183,9 @@ function dualizeAny(sync, asyncFn, options) {
183
183
  if (state === "undecided") {
184
184
  startAsync();
185
185
  } else if (state === "fulfilled") {
186
- p || (p = Promise.resolve(value));
186
+ p ||= Promise.resolve(value);
187
187
  } else if (state === "rejected") {
188
- p || (p = Promise.reject(reason));
188
+ p ||= Promise.reject(reason);
189
189
  } else {
190
190
  startAsync();
191
191
  }
@@ -253,9 +253,8 @@ var WorkflowDispatcher = class {
253
253
  this.pendingInits = 0;
254
254
  this.everActivated = false;
255
255
  this.drainScheduled = false;
256
- var _a, _b;
257
- this.maxAttempts = (_a = options.maxAttempts) != null ? _a : 3;
258
- this.backoffBaseMs = (_b = options.backoffBaseMs) != null ? _b : 1e3;
256
+ this.maxAttempts = options.maxAttempts ?? 3;
257
+ this.backoffBaseMs = options.backoffBaseMs ?? 1e3;
259
258
  for (let i = 0; i < workersOrPromises.length; i++) {
260
259
  const w = workersOrPromises[i];
261
260
  if (typeof w === "function") {
@@ -346,14 +345,13 @@ var WorkflowDispatcher = class {
346
345
  }
347
346
  /** Replace a worker at index with a new active worker function. */
348
347
  replaceWorker(index, fn) {
349
- var _a, _b, _c;
350
348
  if (index < 0 || index >= this.slots.length) {
351
349
  throw new Error(`worker index out of range: ${index}`);
352
350
  }
353
351
  const prevHadActive = this.hasAnyActive();
354
352
  const slot = this.slots[index];
355
353
  const preservedQueue = slot.queue;
356
- const preservedWaiters = (_a = slot.removalWaiters) != null ? _a : [];
354
+ const preservedWaiters = slot.removalWaiters ?? [];
357
355
  const next = {
358
356
  kind: "active",
359
357
  fn,
@@ -361,7 +359,7 @@ var WorkflowDispatcher = class {
361
359
  running: false,
362
360
  failCount: 0,
363
361
  nextAvailableAt: 0,
364
- totalRuns: (_c = (_b = slot.state) == null ? void 0 : _b.totalRuns) != null ? _c : 0
362
+ totalRuns: slot.state?.totalRuns ?? 0
365
363
  },
366
364
  queue: preservedQueue,
367
365
  removalWaiters: preservedWaiters
@@ -444,7 +442,6 @@ var WorkflowDispatcher = class {
444
442
  snapshot() {
445
443
  const now = Date.now();
446
444
  return this.slots.map((slot, i) => {
447
- var _a;
448
445
  switch (slot.kind) {
449
446
  case "active": {
450
447
  const s = slot.state;
@@ -470,7 +467,7 @@ var WorkflowDispatcher = class {
470
467
  return {
471
468
  index: i,
472
469
  status: "rejected",
473
- error: String((_a = slot.error) != null ? _a : "unknown error"),
470
+ error: String(slot.error ?? "unknown error"),
474
471
  specificQueue: slot.queue.length
475
472
  };
476
473
  }
@@ -489,7 +486,6 @@ var WorkflowDispatcher = class {
489
486
  });
490
487
  }
491
488
  _drainLoop() {
492
- var _a;
493
489
  if (!this.hasAnyActive()) {
494
490
  if (this.pendingInits > 0) return;
495
491
  return;
@@ -499,7 +495,7 @@ var WorkflowDispatcher = class {
499
495
  if (slot.kind === "rejected" && slot.queue.length > 0) {
500
496
  const q = slot.queue.splice(0);
501
497
  const err = new Error(
502
- `Worker[${i}] failed to initialize: ${String((_a = slot.error) != null ? _a : "unknown error")}`
498
+ `Worker[${i}] failed to initialize: ${String(slot.error ?? "unknown error")}`
503
499
  );
504
500
  setTimeout(() => {
505
501
  for (const t of q) t.reject(err);
@@ -563,7 +559,7 @@ var WorkflowDispatcher = class {
563
559
  let best = -1, bestRuns = Infinity;
564
560
  for (let i = 0; i < this.slots.length; i++) {
565
561
  if (!this.isEligibleActive(i, now)) continue;
566
- if (task == null ? void 0 : task.triedWorkers.has(i)) continue;
562
+ if (task?.triedWorkers.has(i)) continue;
567
563
  const slot = this.slots[i];
568
564
  if (slot.state.totalRuns < bestRuns) {
569
565
  bestRuns = slot.state.totalRuns;
@@ -631,8 +627,25 @@ var WorkflowDispatcher = class {
631
627
  })();
632
628
  }
633
629
  };
630
+
631
+ // src/round-robin.ts
632
+ var RoundRobin = class {
633
+ constructor(items) {
634
+ this.items = items;
635
+ this.index = 0;
636
+ if (items.length === 0) {
637
+ throw new Error("RoundRobin requires at least one item");
638
+ }
639
+ }
640
+ next() {
641
+ const nextIndex = this.index % this.items.length;
642
+ this.index = (this.index + 1) % this.items.length;
643
+ return this.items[nextIndex];
644
+ }
645
+ };
634
646
  // Annotate the CommonJS export names for ESM import in node:
635
647
  0 && (module.exports = {
648
+ RoundRobin,
636
649
  WF_NODE,
637
650
  WorkflowDispatcher,
638
651
  dualizeAny,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../index.ts", "../src/workflow.ts", "../src/dual-object.ts", "../src/workflow-dispatcher.ts"],
4
- "sourcesContent": ["export * from './src/workflow';\nexport * from './src/dual-object';\nexport * from './src/workflow-dispatcher';\n", "// ========== \u7C7B\u578B\u5DE5\u5177 ==========\ntype AwaitedLike<T> = T extends Promise<infer R> ? R : T;\ntype AnyFn = (...args: any[]) => any;\n\ntype Chain<T> = Promise<AwaitedLike<T>> &\n (T extends AnyFn\n ? (...a: Parameters<T>) => Chain<AwaitedLike<ReturnType<T>>>\n : {}) & {\n [K in keyof T]: T[K] extends (...a: infer A) => infer R\n ? (...a: A) => Chain<AwaitedLike<R>>\n : Chain<AwaitedLike<T[K]>>;\n };\n\n// ========== \u6838\u5FC3\uFF1A\u4E0D\u53EF\u53D8\u8282\u70B9 ==========\nclass Node {\n private memo?: Promise<any>;\n constructor(\n private readonly source: any, // \u53EA\u6709\u6839\u8282\u70B9\u6709\u610F\u4E49\uFF1B\u5B50\u8282\u70B9\u53EF\u590D\u7528\u6839\u7684 source\n private readonly parent: Node | null, // \u524D\u7F00\n private readonly op: ((x: any) => any) | null, // \u4ECE parent \u7ED3\u679C\u5230\u672C\u8282\u70B9\u7ED3\u679C\u7684\u53D8\u6362\n ) {}\n\n run(): Promise<any> {\n if (!this.memo) {\n this.memo = (async () => {\n if (!this.parent) {\n // \u6839\uFF1A\u628A source \u89E3\u4E00\u6B21\u5373\u53EF\n return await this.source;\n }\n // \u5148\u62FF\u5230\u7236\u8282\u70B9\u7ED3\u679C\uFF08\u4F1A\u8BB0\u5FC6\u5316\uFF09\n const base = await this.parent.run();\n // \u5E94\u7528\u672C\u8282\u70B9\u7684\u53D8\u6362\uFF08\u5141\u8BB8\u8FD4\u56DE\u540C\u6B65\u6216\u5F02\u6B65\uFF09\n return this.op ? this.op(base) : base;\n })();\n }\n return this.memo;\n }\n\n // \u5DE5\u5382\uFF1A\u884D\u751F\u5B50\u8282\u70B9\uFF08\u5206\u53C9 = \u590D\u7528\u540C\u4E00\u4E2A parent\uFF09\n child(op: (x: any) => any): Node {\n return new Node(this.source, this, op);\n }\n\n // \u62FF\u5230\u201C\u76F8\u540C\u8282\u70B9\u201D\u7684\u53E5\u67C4\uFF08\u663E\u5F0F fork\uFF09\n fork(): Node {\n return new Node(this.source, this.parent, this.op);\n }\n}\n\nexport const WF_NODE = Symbol('@@workflow/node');\n\nfunction isWorkflowChain(x: any): x is Chain<any> {\n return !!x && typeof x === 'function' && x[WF_NODE] instanceof Node;\n}\n\n// ========== \u5BF9\u5916 API\uFF1Aworkflow ==========\nexport function workflow<T>(source: T | Promise<T>): Chain<T> {\n if (isWorkflowChain(source)) {\n return source as unknown as Chain<T>;\n }\n const root = new Node(source, null, null);\n return makeProxy<T>(root) as any;\n}\n\n// ========== \u4EE3\u7406\u5C42\uFF1A\u628A Node \u66B4\u9732\u6210\u94FE\u5F0F API ==========\nfunction makeProxy<T>(node: Node): Chain<T> {\n const runOnce = () => node.run(); // \u8BB0\u5FC6\u5316\u5728 Node \u5185\u90E8\n\n const rootHandler: ProxyHandler<any> = {\n get(_t, prop) {\n if (prop === WF_NODE) return node;\n // \u7ED3\u675F\u4FE1\u53F7\uFF1A\u6240\u6709 then/catch/finally \u590D\u7528\u540C\u4E00\u4E2A Promise\n if (prop === 'then')\n return (res: any, rej?: any) => runOnce().then(res, rej);\n if (prop === 'catch') return (rej: any) => runOnce().catch(rej);\n if (prop === 'finally') return (fin: any) => runOnce().finally(fin);\n\n // \u8BBF\u95EE\u4E00\u4E2A\u5C5E\u6027\uFF1A\u751F\u6210\u4E00\u4E2A\u201CGet\u201D\u5B50\u8282\u70B9\uFF0C\u4F46\u4E0D\u6267\u884C\n return linkProxy(prop);\n },\n // \u652F\u6301\u5BF9\u201C\u5F53\u524D\u503C\u201D\u76F4\u63A5\u4E8C\u6B21\u8C03\u7528\uFF1A foo()()\n apply(_t, _this, argArray) {\n const child = node.child((cur: any) => {\n if (typeof cur !== 'function')\n throw new TypeError('Current value is not callable');\n return cur(...argArray);\n });\n return makeProxy<any>(child);\n },\n };\n\n const linkProxy = (prop: PropertyKey) =>\n new Proxy(function () {}, {\n // \u628A \u201C.foo(\u2026args)\u201D \u8BB0\u5F55\u4E3A Call\n apply(_t, _this, argArray) {\n const child = node.child((cur: any) => {\n const fn = (cur as any)[prop];\n if (typeof fn !== 'function') {\n throw new TypeError(`${String(prop)} is not a function`);\n }\n return fn.apply(cur, argArray);\n });\n return makeProxy<any>(child);\n },\n // \u628A \u201C.bar\u201D \u8BB0\u5F55\u4E3A Get\uFF1B\u7EE7\u7EED\u6DF1\u5165\u65F6\u5728\u8FD9\u4E2A Get \u7684\u7ED3\u679C\u4E0A\u518D\u5904\u7406\n get(_t, next) {\n if (next === WF_NODE) return node;\n if (next === 'then')\n return (r: any, j?: any) =>\n node\n .child((cur: any) => (cur as any)[prop])\n .run()\n .then(r, j);\n if (next === 'catch')\n return (rej: any) =>\n node\n .child((cur: any) => (cur as any)[prop])\n .run()\n .catch(rej);\n if (next === 'finally')\n return (fin: any) =>\n node\n .child((cur: any) => (cur as any)[prop])\n .run()\n .finally(fin);\n\n const child = node.child((cur: any) => (cur as any)[prop]);\n return (makeProxy as any)(child)[next];\n },\n });\n\n return new Proxy(function () {}, rootHandler) as any;\n}\n", "// dual-unified.ts\nexport type Dual<T> = T & PromiseLike<T>;\n\ntype ThenKey = 'then' | 'catch' | 'finally';\nconst isThenKey = (k: PropertyKey): k is ThenKey =>\n k === 'then' || k === 'catch' || k === 'finally';\n\ntype State = 'undecided' | 'pending' | 'fulfilled' | 'rejected';\n\n/** \u4EC5\u5141\u8BB8\u586B\u5165 \u201C\u8FD4\u56DE Promise \u7684\u65B9\u6CD5\u540D\u201D */\nexport type AsyncMethodKeys<T> = {\n [K in keyof T]-?: T[K] extends (...args: any[]) => Promise<any> ? K : never;\n}[keyof T];\n\nexport interface DualizeOptions<T> {\n /** \u8FD9\u4E9B\u65B9\u6CD5\u5728 undecided/pending \u65F6\u4F1A\u8FD4\u56DE\u4E00\u4E2A\u5EF6\u8FDF\u6267\u884C\u51FD\u6570\uFF0C\u7B49\u5F85\u5BF9\u8C61 Promise \u5B8C\u6210\u540E\u518D\u8C03\u7528 */\n asyncMethods?: readonly AsyncMethodKeys<T>[];\n}\n\nexport function dualizeAny<T>(\n sync: () => T, // \u540C\u6B65\u6784\u9020\uFF1B\u82E5\u629B\u9519\u5219\u89C6\u4E3A rejected\n asyncFn: () => Promise<T>, // \u5F02\u6B65\u6784\u9020\n options?: DualizeOptions<T>,\n): Dual<T> {\n let state: State = 'undecided';\n\n let value!: T; // fulfilled \u65F6\u7684\u503C\uFF08\u542B\u6765\u81EA sync \u6216 async\uFF09\n let reason: any; // rejected \u7684\u9519\u8BEF\n let p!: Promise<T>; // \u7F13\u5B58 Promise\uFF08resolved/rejected/\u8FDB\u884C\u4E2D\uFF09\n\n const asyncMethodSet = new Set<PropertyKey>(\n (options?.asyncMethods ?? []) as readonly PropertyKey[],\n );\n\n const startAsync = () => {\n if (!p || state === 'undecided') {\n state = 'pending';\n p = Promise.resolve()\n .then(asyncFn)\n .then(\n (v) => {\n value = v;\n state = 'fulfilled';\n return v;\n },\n (e) => {\n reason = e;\n state = 'rejected';\n throw e;\n },\n );\n }\n return p;\n };\n\n const ensureSync = () => {\n if (state === 'undecided') {\n try {\n value = sync();\n state = 'fulfilled';\n } catch (e) {\n reason = e;\n state = 'rejected';\n }\n }\n };\n\n /** \u5728\u201C\u5BF9\u8C61\u53EF\u7528\u201D\u540E\u8C03\u7528\u67D0\u4E2A\u5F02\u6B65\u65B9\u6CD5\uFF08\u7531 asyncMethods \u58F0\u660E\uFF09 */\n const makeDeferredAsyncMethod =\n (prop: PropertyKey) =>\n (...args: any[]) =>\n startAsync().then((obj) => {\n const fn = (obj as any)[prop];\n return fn.apply(obj, args);\n });\n\n // \u4ECE\u67D0\u4E2A\u503C\u4E0A\u53D6\u5C5E\u6027\uFF08\u539F\u59CB\u503C\u4F1A\u88C5\u7BB1\uFF09\uFF0C\u5E76\u7ED1\u5B9A this\n const getFrom = (v: unknown, prop: PropertyKey) => {\n if (prop === Symbol.toPrimitive) {\n return (hint: 'default' | 'number' | 'string') => {\n const x: any = v;\n if (hint === 'number') return Number(x);\n if (hint === 'string') return String(x);\n if (typeof x === 'string') return x;\n const n = Number(x);\n return Number.isNaN(n) ? String(x) : n;\n };\n }\n if (prop === 'valueOf') return () => v as any;\n if (prop === 'toString') return () => String(v);\n\n const boxed: any =\n v !== null && (typeof v === 'object' || typeof v === 'function')\n ? v\n : Object(v as any);\n const out = boxed[prop];\n return typeof out === 'function' ? out.bind(boxed) : out;\n };\n\n const proxy = new Proxy(Object.create(null) as any, {\n get(_t, prop) {\n // then/catch/finally\uFF1A\u8D70 Promise \u901A\u9053\n if (isThenKey(prop)) {\n if (state === 'undecided') {\n startAsync();\n } else if (state === 'fulfilled') {\n // \u82E5\u5DF2 fulfilled\uFF08\u6765\u81EA sync \u6216 async\uFF09\uFF0C\u8865\u4E00\u4E2A\u5DF2\u5B8C\u6210\u7684 Promise\n p ||= Promise.resolve(value);\n } else if (state === 'rejected') {\n p ||= Promise.reject(reason);\n } else {\n // pending\uFF1A\u5DF2\u6709 p\n startAsync();\n }\n const anyP: any = p;\n const m = anyP[prop];\n return typeof m === 'function' ? m.bind(anyP) : m;\n }\n\n // \u58F0\u660E\u4E3A\u5F02\u6B65\u65B9\u6CD5\u7684\u952E\uFF1A\u5728 undecided/pending \u65F6\u8FD4\u56DE\u201C\u5EF6\u8FDF\u51FD\u6570\u201D\n if (asyncMethodSet.has(prop)) {\n if (state === 'undecided' || state === 'pending') {\n startAsync();\n return makeDeferredAsyncMethod(prop);\n }\n if (state === 'fulfilled') {\n return getFrom(value, prop); // \u540C\u6B65\u53EF\u76F4\u63A5\u53D6\u5230\u65B9\u6CD5\uFF08\u5176\u672C\u8EAB\u8FD4\u56DE Promise\uFF09\n }\n if (state === 'rejected') {\n // \u8BBF\u95EE\u5373\u629B\uFF1B\u4E5F\u53EF\u4EE5\u9009\u62E9\u8FD4\u56DE () => Promise.reject(reason)\n throw reason;\n }\n }\n\n // \u5176\u5B83\u5C5E\u6027\u8BBF\u95EE\uFF1A\u9075\u5FAA\u72B6\u6001\u673A\n switch (state) {\n case 'undecided': {\n ensureSync();\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (state === 'fulfilled') return getFrom(value, prop);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (state === 'rejected') throw reason;\n // \u7406\u8BBA\u4E0A\u4E0D\u4F1A\u5230\u8FD9\u91CC\n throw new TypeError('Invalid state transition');\n }\n case 'pending': {\n // \u975E asyncMethods \u7684\u5C5E\u6027\u5728 pending \u65F6\u4E0D\u53EF\u540C\u6B65\u8BFB\u53D6\n throw new TypeError('Value is not ready yet. Please await it first.');\n }\n case 'fulfilled': {\n return getFrom(value, prop);\n }\n case 'rejected': {\n throw reason;\n }\n }\n },\n\n has(_t, key) {\n if (state === 'undecided') {\n ensureSync();\n }\n if (state === 'fulfilled') return key in Object(value as any);\n return false; // pending/rejected\uFF1A\u4FDD\u5B88\u5904\u7406\n },\n\n ownKeys() {\n if (state === 'undecided') ensureSync();\n if (state === 'fulfilled') return Reflect.ownKeys(Object(value as any));\n return [];\n },\n\n getOwnPropertyDescriptor(_t, key) {\n if (state === 'undecided') ensureSync();\n if (state === 'fulfilled')\n return Object.getOwnPropertyDescriptor(Object(value as any), key);\n return undefined;\n },\n });\n\n return proxy as Dual<T>;\n}\n", "export interface DispatcherOptions {\n /** Max attempts per task. Default 3. */\n maxAttempts?: number;\n /** Backoff base in ms. backoff = base * 2^failCount. Default 1000. */\n backoffBaseMs?: number;\n}\n\n// Internal task record\ntype Task<F extends (...args: any[]) => Promise<any>> = {\n args: Parameters<F>;\n resolve: (v: Awaited<ReturnType<F>>) => void;\n reject: (e: any) => void;\n attempts: number;\n lastError?: any;\n triedWorkers: Set<number>; // for global dispatch\n specificWorkerIndex?: number; // for dispatchSpecific only\n};\n\ntype WorkerState = {\n running: boolean;\n failCount: number;\n nextAvailableAt: number;\n totalRuns: number;\n};\n\ntype RemovalWaiter = () => void;\n\ntype ActiveSlot<F extends (...args: any[]) => Promise<any>> = {\n kind: 'active';\n fn: F;\n state: WorkerState;\n queue: Task<F>[];\n removalWaiters: RemovalWaiter[];\n removed?: boolean; // marker when removed while running; retained for completion callback\n};\n\ntype PendingSlot<F extends (...args: any[]) => Promise<any>> = {\n kind: 'pending';\n promise: Promise<F>;\n queue: Task<F>[];\n removalWaiters: RemovalWaiter[];\n error?: any;\n removed?: boolean; // if removed before resolved\n};\n\ntype RejectedSlot<F extends (...args: any[]) => Promise<any>> = {\n kind: 'rejected';\n error: any;\n queue: Task<F>[];\n removalWaiters: RemovalWaiter[];\n removed?: boolean;\n};\n\ntype Slot<F extends (...args: any[]) => Promise<any>> =\n | ActiveSlot<F>\n | PendingSlot<F>\n | RejectedSlot<F>;\n\nexport type WorkerSnapshot<F extends (...args: any[]) => Promise<any>> =\n | {\n index: number;\n status: 'active';\n fn: F;\n running: boolean;\n failCount: number;\n totalRuns: number;\n blockedMs: number;\n specificQueue: number;\n }\n | {\n index: number;\n status: 'pending';\n promise: Promise<F>;\n specificQueue: number;\n }\n | {\n index: number;\n status: 'rejected';\n error: string;\n specificQueue: number;\n };\n\nexport class WorkflowDispatcher<F extends (...args: any[]) => Promise<any>> {\n private readonly maxAttempts: number;\n private readonly backoffBaseMs: number;\n\n private readonly slots: Slot<F>[] = [];\n private readonly globalQueue: Task<F>[] = [];\n\n private pendingInits = 0;\n private everActivated = false;\n private drainScheduled = false;\n\n constructor(\n workersOrPromises: Array<F | Promise<F>>,\n options: DispatcherOptions = {},\n ) {\n // if (!workersOrPromises?.length) throw new Error('workers cannot be empty');\n\n this.maxAttempts = options.maxAttempts ?? 3;\n this.backoffBaseMs = options.backoffBaseMs ?? 1000;\n\n for (let i = 0; i < workersOrPromises.length; i++) {\n const w = workersOrPromises[i];\n if (typeof w === 'function') {\n const slot: ActiveSlot<F> = {\n kind: 'active',\n fn: w,\n state: {\n running: false,\n failCount: 0,\n nextAvailableAt: 0,\n totalRuns: 0,\n },\n queue: [],\n removalWaiters: [],\n };\n this.slots.push(slot);\n this.everActivated = true;\n } else {\n // Create a stable slot object and mutate it in-place on resolve/reject.\n this.pendingInits++;\n const slot: PendingSlot<F> = {\n kind: 'pending',\n promise: Promise.resolve(w),\n queue: [],\n removalWaiters: [],\n };\n this.slots.push(slot);\n\n slot.promise\n .then((fn) => {\n if (slot.removed) return; // was removed; ignore resolution\n // mutate in-place to active\n (slot as any).kind = 'active';\n (slot as any).fn = fn;\n (slot as any).state = {\n running: false,\n failCount: 0,\n nextAvailableAt: 0,\n totalRuns: 0,\n };\n this.everActivated = true;\n // keep queue & removalWaiters arrays as-is\n })\n .catch((err) => {\n if (slot.removed) return; // was removed; ignore\n // mutate in-place to rejected (keep queue/waiters)\n (slot as any).kind = 'rejected';\n (slot as any).error = err;\n })\n .finally(() => {\n this.pendingInits--;\n this.drain();\n if (this.pendingInits === 0 && !this.hasAnyActive()) {\n const err = new Error(\n 'No workers available (all failed to initialize).',\n );\n setTimeout(() => this.rejectAllQueued(err), 0);\n }\n });\n }\n }\n\n if (this.everActivated) this.drain();\n }\n\n /** Dispatch: choose eligible active with least totalRuns; retry across workers on failure. */\n dispatch(...args: Parameters<F>): Promise<Awaited<ReturnType<F>>> {\n return new Promise((resolve, reject) => {\n const task: Task<F> = {\n args,\n resolve,\n reject,\n attempts: 0,\n triedWorkers: new Set(),\n };\n this.globalQueue.push(task);\n this.drain();\n });\n }\n\n /** Dispatch to a specific worker (ignore backoff), wait until it is free; retry on the same worker. */\n dispatchSpecific(\n index: number,\n ...args: Parameters<F>\n ): Promise<Awaited<ReturnType<F>>> {\n if (index < 0 || index >= this.slots.length) {\n return Promise.reject(new Error(`worker index out of range: ${index}`));\n }\n return new Promise((resolve, reject) => {\n const task: Task<F> = {\n args,\n resolve,\n reject,\n attempts: 0,\n triedWorkers: new Set(),\n specificWorkerIndex: index,\n };\n const slot = this.slots[index];\n slot.queue.push(task);\n this.drain();\n });\n }\n\n /** Replace a worker at index with a new active worker function. */\n public replaceWorker(index: number, fn: F): void {\n if (index < 0 || index >= this.slots.length) {\n throw new Error(`worker index out of range: ${index}`);\n }\n const prevHadActive = this.hasAnyActive();\n const slot = this.slots[index];\n\n // Preserve queue & removal waiters; reset failure/backoff; keep totalRuns to avoid skew.\n const preservedQueue = slot.queue;\n const preservedWaiters = slot.removalWaiters ?? [];\n\n const next: ActiveSlot<F> = {\n kind: 'active',\n fn,\n state: {\n running: false,\n failCount: 0,\n nextAvailableAt: 0,\n totalRuns: (slot as any).state?.totalRuns ?? 0,\n },\n queue: preservedQueue,\n removalWaiters: preservedWaiters,\n };\n\n // Mutate in-place if possible (keeps references stable), else replace array entry.\n Object.assign(slot as any, next);\n (slot as any).kind = 'active';\n (slot as any).fn = fn;\n (slot as any).state.failCount = 0;\n (slot as any).state.nextAvailableAt = 0;\n\n this.everActivated = true;\n if (!prevHadActive && this.hasAnyActive()) {\n this.drain();\n } else {\n this.drain();\n }\n }\n\n /** Add a new active worker at the tail; return its index. */\n public addWorker(fn: F): number {\n const slot: ActiveSlot<F> = {\n kind: 'active',\n fn,\n state: { running: false, failCount: 0, nextAvailableAt: 0, totalRuns: 0 },\n queue: [],\n removalWaiters: [],\n };\n const index = this.slots.length;\n this.slots.push(slot);\n this.everActivated = true;\n this.drain();\n return index;\n }\n\n /**\n * Remove a worker completely (splice). It becomes unavailable immediately.\n * Returns a Promise that resolves when its last running task (if any) finishes.\n */\n public removeWorker(index: number): Promise<void> {\n if (index < 0 || index >= this.slots.length) {\n return Promise.reject(new Error(`worker index out of range: ${index}`));\n }\n\n const slot = this.slots[index];\n\n // Reject all queued specific tasks on this worker (macro-task to avoid unhandled)\n const queued = slot.queue.splice(0);\n const removalErr = new Error(`Worker[${index}] removed`);\n setTimeout(() => {\n for (const t of queued) t.reject(removalErr);\n }, 0);\n\n // Decide completion promise:\n let completion: Promise<void>;\n const isRunning = slot.kind === 'active' && slot.state.running;\n if (!isRunning) {\n completion = Promise.resolve();\n } else {\n completion = new Promise<void>((resolve) => {\n slot.removalWaiters.push(resolve);\n });\n }\n\n // Mark as removed (so any pending init resolution is ignored)\n (slot as any).removed = true;\n\n // Physically remove the slot\n this.slots.splice(index, 1);\n\n // Re-map indices in all remaining tasks:\n // 1) Fix specificWorkerIndex in every remaining slot.queue\n for (let i = 0; i < this.slots.length; i++) {\n const s = this.slots[i];\n for (const t of s.queue) {\n if (typeof t.specificWorkerIndex === 'number') {\n if (t.specificWorkerIndex === index) {\n // This should not happen because we just removed and flushed its queue,\n // but guard anyway.\n t.reject(new Error(`Worker[${index}] no longer exists`));\n } else if (t.specificWorkerIndex > index) {\n t.specificWorkerIndex -= 1;\n }\n }\n }\n }\n // 2) Fix triedWorkers sets in globalQueue\n for (const t of this.globalQueue) {\n if (t.triedWorkers.has(index)) t.triedWorkers.delete(index);\n const next = new Set<number>();\n for (const w of t.triedWorkers) {\n next.add(w > index ? w - 1 : w);\n }\n t.triedWorkers = next;\n }\n\n // Trigger scheduling for the remaining system\n this.drain();\n\n return completion;\n }\n\n snapshot(): WorkerSnapshot<F>[] {\n const now = Date.now();\n\n return this.slots.map((slot, i) => {\n switch (slot.kind) {\n case 'active': {\n const s = slot.state;\n return {\n index: i,\n status: 'active' as const,\n fn: slot.fn,\n running: s.running,\n failCount: s.failCount,\n totalRuns: s.totalRuns,\n blockedMs: Math.max(0, s.nextAvailableAt - now),\n specificQueue: slot.queue.length,\n };\n }\n\n case 'pending':\n return {\n index: i,\n status: 'pending' as const,\n promise: slot.promise,\n specificQueue: slot.queue.length,\n };\n\n case 'rejected':\n return {\n index: i,\n status: 'rejected' as const,\n error: String(slot.error ?? 'unknown error'),\n specificQueue: slot.queue.length,\n };\n }\n });\n }\n\n get pending(): number {\n return this.globalQueue.length;\n }\n\n // ---------------- scheduling ----------------\n\n private drain() {\n if (this.drainScheduled) return;\n this.drainScheduled = true;\n queueMicrotask(() => {\n this.drainScheduled = false;\n this._drainLoop();\n });\n }\n\n private _drainLoop() {\n // If no active workers and still initializing, wait; if all inited and none active, constructor already rejects all.\n if (!this.hasAnyActive()) {\n if (this.pendingInits > 0) return;\n return;\n }\n\n // First: flush rejected workers' specific queues (macro-task rejection)\n for (let i = 0; i < this.slots.length; i++) {\n const slot = this.slots[i];\n if (slot.kind === 'rejected' && slot.queue.length > 0) {\n const q = slot.queue.splice(0);\n const err = new Error(\n `Worker[${i}] failed to initialize: ${String(slot.error ?? 'unknown error')}`,\n );\n setTimeout(() => {\n for (const t of q) t.reject(err);\n }, 0);\n }\n }\n\n let progressed = true;\n while (progressed) {\n progressed = false;\n\n // 1) Run specific queues for active workers (ignore backoff)\n for (let i = 0; i < this.slots.length; i++) {\n const slot = this.slots[i];\n if (slot.kind !== 'active') continue;\n const st = slot.state;\n if (!st.running && slot.queue.length > 0) {\n const task = slot.queue.shift()!;\n this.startTaskOnActiveSlot(i, slot, task, /*fromSpecific*/ true);\n progressed = true;\n }\n }\n\n // 2) Run global queue (choose eligible active with least totalRuns)\n if (this.globalQueue.length > 0) {\n const idx = this.pickBestActiveForGlobal();\n if (idx !== -1) {\n const slot = this.slots[idx] as ActiveSlot<F>;\n const task = this.globalQueue.shift()!;\n this.startTaskOnActiveSlot(idx, slot, task, /*fromSpecific*/ false);\n progressed = true;\n }\n }\n }\n }\n\n private hasAnyActive() {\n return this.slots.some((s) => s.kind === 'active');\n }\n\n private rejectAllQueued(err: any) {\n while (this.globalQueue.length) this.globalQueue.shift()!.reject(err);\n for (const slot of this.slots) {\n while (slot.queue.length) slot.queue.shift()!.reject(err);\n }\n }\n\n private isEligibleActive(i: number, now: number) {\n const slot = this.slots[i];\n if (!slot || slot.kind !== 'active') return false;\n const s = slot.state;\n return !s.running && now >= s.nextAvailableAt;\n // note: specific queues ignore backoff; this is only for global picks.\n }\n\n private pickBestActiveForGlobal(): number {\n const now = Date.now();\n const task = this.globalQueue[0];\n\n // Prefer actives not tried yet\n let best = -1,\n bestRuns = Infinity;\n for (let i = 0; i < this.slots.length; i++) {\n if (!this.isEligibleActive(i, now)) continue;\n if (task?.triedWorkers.has(i)) continue;\n const slot = this.slots[i] as ActiveSlot<F>;\n if (slot.state.totalRuns < bestRuns) {\n bestRuns = slot.state.totalRuns;\n best = i;\n }\n }\n if (best !== -1) return best;\n\n // Allow already-tried actives\n best = -1;\n bestRuns = Infinity;\n for (let i = 0; i < this.slots.length; i++) {\n if (!this.isEligibleActive(i, now)) continue;\n const slot = this.slots[i] as ActiveSlot<F>;\n if (slot.state.totalRuns < bestRuns) {\n bestRuns = slot.state.totalRuns;\n best = i;\n }\n }\n return best;\n }\n\n private startTaskOnActiveSlot(\n index: number,\n slot: ActiveSlot<F>,\n task: Task<F>,\n fromSpecific: boolean,\n ) {\n const st = slot.state;\n st.running = true;\n st.totalRuns += 1;\n\n const finalize = () => {\n st.running = false;\n // If someone is waiting for this worker to finish (removeWorker), resolve them when idle.\n if (\n slot.removalWaiters.length > 0 &&\n !st.running &&\n slot.queue.length === 0\n ) {\n const list = slot.removalWaiters.splice(0);\n for (const w of list) w();\n }\n this.drain();\n };\n\n (async () => {\n try {\n const result = await slot.fn(...task.args);\n st.failCount = Math.max(0, st.failCount - 1);\n task.resolve(result as Awaited<ReturnType<F>>);\n } catch (err) {\n task.lastError = err;\n st.failCount += 1;\n st.nextAvailableAt =\n Date.now() + this.backoffBaseMs * Math.pow(2, st.failCount);\n\n if (fromSpecific) {\n task.attempts += 1;\n if (task.attempts >= this.maxAttempts) {\n task.reject(task.lastError);\n } else {\n // retry on the same worker (ignore backoff)\n slot.queue.push(task);\n }\n } else {\n task.attempts += 1;\n task.triedWorkers.add(index);\n const activeCount = this.slots.filter(\n (s) => s.kind === 'active',\n ).length;\n const allActiveTriedOnce = task.triedWorkers.size >= activeCount;\n const attemptsLimitReached = task.attempts >= this.maxAttempts;\n\n if (allActiveTriedOnce || attemptsLimitReached) {\n task.reject(task.lastError);\n } else {\n this.globalQueue.push(task);\n }\n }\n } finally {\n finalize();\n }\n })();\n }\n}\n"],
5
- "mappings": "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",
3
+ "sources": ["../index.ts", "../src/workflow.ts", "../src/dual-object.ts", "../src/workflow-dispatcher.ts", "../src/round-robin.ts"],
4
+ "sourcesContent": ["export * from './src/workflow';\nexport * from './src/dual-object';\nexport * from './src/workflow-dispatcher';\nexport * from './src/round-robin';\n", "// ========== \u7C7B\u578B\u5DE5\u5177 ==========\ntype AwaitedLike<T> = T extends Promise<infer R> ? R : T;\ntype AnyFn = (...args: any[]) => any;\n\ntype Chain<T> = Promise<AwaitedLike<T>> &\n (T extends AnyFn\n ? (...a: Parameters<T>) => Chain<AwaitedLike<ReturnType<T>>>\n : {}) & {\n [K in keyof T]: T[K] extends (...a: infer A) => infer R\n ? (...a: A) => Chain<AwaitedLike<R>>\n : Chain<AwaitedLike<T[K]>>;\n };\n\n// ========== \u6838\u5FC3\uFF1A\u4E0D\u53EF\u53D8\u8282\u70B9 ==========\nclass Node {\n private memo?: Promise<any>;\n constructor(\n private readonly source: any, // \u53EA\u6709\u6839\u8282\u70B9\u6709\u610F\u4E49\uFF1B\u5B50\u8282\u70B9\u53EF\u590D\u7528\u6839\u7684 source\n private readonly parent: Node | null, // \u524D\u7F00\n private readonly op: ((x: any) => any) | null, // \u4ECE parent \u7ED3\u679C\u5230\u672C\u8282\u70B9\u7ED3\u679C\u7684\u53D8\u6362\n ) {}\n\n run(): Promise<any> {\n if (!this.memo) {\n this.memo = (async () => {\n if (!this.parent) {\n // \u6839\uFF1A\u628A source \u89E3\u4E00\u6B21\u5373\u53EF\n return await this.source;\n }\n // \u5148\u62FF\u5230\u7236\u8282\u70B9\u7ED3\u679C\uFF08\u4F1A\u8BB0\u5FC6\u5316\uFF09\n const base = await this.parent.run();\n // \u5E94\u7528\u672C\u8282\u70B9\u7684\u53D8\u6362\uFF08\u5141\u8BB8\u8FD4\u56DE\u540C\u6B65\u6216\u5F02\u6B65\uFF09\n return this.op ? this.op(base) : base;\n })();\n }\n return this.memo;\n }\n\n // \u5DE5\u5382\uFF1A\u884D\u751F\u5B50\u8282\u70B9\uFF08\u5206\u53C9 = \u590D\u7528\u540C\u4E00\u4E2A parent\uFF09\n child(op: (x: any) => any): Node {\n return new Node(this.source, this, op);\n }\n\n // \u62FF\u5230\u201C\u76F8\u540C\u8282\u70B9\u201D\u7684\u53E5\u67C4\uFF08\u663E\u5F0F fork\uFF09\n fork(): Node {\n return new Node(this.source, this.parent, this.op);\n }\n}\n\nexport const WF_NODE = Symbol('@@workflow/node');\n\nfunction isWorkflowChain(x: any): x is Chain<any> {\n return !!x && typeof x === 'function' && x[WF_NODE] instanceof Node;\n}\n\n// ========== \u5BF9\u5916 API\uFF1Aworkflow ==========\nexport function workflow<T>(source: T | Promise<T>): Chain<T> {\n if (isWorkflowChain(source)) {\n return source as unknown as Chain<T>;\n }\n const root = new Node(source, null, null);\n return makeProxy<T>(root) as any;\n}\n\n// ========== \u4EE3\u7406\u5C42\uFF1A\u628A Node \u66B4\u9732\u6210\u94FE\u5F0F API ==========\nfunction makeProxy<T>(node: Node): Chain<T> {\n const runOnce = () => node.run(); // \u8BB0\u5FC6\u5316\u5728 Node \u5185\u90E8\n\n const rootHandler: ProxyHandler<any> = {\n get(_t, prop) {\n if (prop === WF_NODE) return node;\n // \u7ED3\u675F\u4FE1\u53F7\uFF1A\u6240\u6709 then/catch/finally \u590D\u7528\u540C\u4E00\u4E2A Promise\n if (prop === 'then')\n return (res: any, rej?: any) => runOnce().then(res, rej);\n if (prop === 'catch') return (rej: any) => runOnce().catch(rej);\n if (prop === 'finally') return (fin: any) => runOnce().finally(fin);\n\n // \u8BBF\u95EE\u4E00\u4E2A\u5C5E\u6027\uFF1A\u751F\u6210\u4E00\u4E2A\u201CGet\u201D\u5B50\u8282\u70B9\uFF0C\u4F46\u4E0D\u6267\u884C\n return linkProxy(prop);\n },\n // \u652F\u6301\u5BF9\u201C\u5F53\u524D\u503C\u201D\u76F4\u63A5\u4E8C\u6B21\u8C03\u7528\uFF1A foo()()\n apply(_t, _this, argArray) {\n const child = node.child((cur: any) => {\n if (typeof cur !== 'function')\n throw new TypeError('Current value is not callable');\n return cur(...argArray);\n });\n return makeProxy<any>(child);\n },\n };\n\n const linkProxy = (prop: PropertyKey) =>\n new Proxy(function () {}, {\n // \u628A \u201C.foo(\u2026args)\u201D \u8BB0\u5F55\u4E3A Call\n apply(_t, _this, argArray) {\n const child = node.child((cur: any) => {\n const fn = (cur as any)[prop];\n if (typeof fn !== 'function') {\n throw new TypeError(`${String(prop)} is not a function`);\n }\n return fn.apply(cur, argArray);\n });\n return makeProxy<any>(child);\n },\n // \u628A \u201C.bar\u201D \u8BB0\u5F55\u4E3A Get\uFF1B\u7EE7\u7EED\u6DF1\u5165\u65F6\u5728\u8FD9\u4E2A Get \u7684\u7ED3\u679C\u4E0A\u518D\u5904\u7406\n get(_t, next) {\n if (next === WF_NODE) return node;\n if (next === 'then')\n return (r: any, j?: any) =>\n node\n .child((cur: any) => (cur as any)[prop])\n .run()\n .then(r, j);\n if (next === 'catch')\n return (rej: any) =>\n node\n .child((cur: any) => (cur as any)[prop])\n .run()\n .catch(rej);\n if (next === 'finally')\n return (fin: any) =>\n node\n .child((cur: any) => (cur as any)[prop])\n .run()\n .finally(fin);\n\n const child = node.child((cur: any) => (cur as any)[prop]);\n return (makeProxy as any)(child)[next];\n },\n });\n\n return new Proxy(function () {}, rootHandler) as any;\n}\n", "// dual-unified.ts\nexport type Dual<T> = T & PromiseLike<T>;\n\ntype ThenKey = 'then' | 'catch' | 'finally';\nconst isThenKey = (k: PropertyKey): k is ThenKey =>\n k === 'then' || k === 'catch' || k === 'finally';\n\ntype State = 'undecided' | 'pending' | 'fulfilled' | 'rejected';\n\n/** \u4EC5\u5141\u8BB8\u586B\u5165 \u201C\u8FD4\u56DE Promise \u7684\u65B9\u6CD5\u540D\u201D */\nexport type AsyncMethodKeys<T> = {\n [K in keyof T]-?: T[K] extends (...args: any[]) => Promise<any> ? K : never;\n}[keyof T];\n\nexport interface DualizeOptions<T> {\n /** \u8FD9\u4E9B\u65B9\u6CD5\u5728 undecided/pending \u65F6\u4F1A\u8FD4\u56DE\u4E00\u4E2A\u5EF6\u8FDF\u6267\u884C\u51FD\u6570\uFF0C\u7B49\u5F85\u5BF9\u8C61 Promise \u5B8C\u6210\u540E\u518D\u8C03\u7528 */\n asyncMethods?: readonly AsyncMethodKeys<T>[];\n}\n\nexport function dualizeAny<T>(\n sync: () => T, // \u540C\u6B65\u6784\u9020\uFF1B\u82E5\u629B\u9519\u5219\u89C6\u4E3A rejected\n asyncFn: () => Promise<T>, // \u5F02\u6B65\u6784\u9020\n options?: DualizeOptions<T>,\n): Dual<T> {\n let state: State = 'undecided';\n\n let value!: T; // fulfilled \u65F6\u7684\u503C\uFF08\u542B\u6765\u81EA sync \u6216 async\uFF09\n let reason: any; // rejected \u7684\u9519\u8BEF\n let p!: Promise<T>; // \u7F13\u5B58 Promise\uFF08resolved/rejected/\u8FDB\u884C\u4E2D\uFF09\n\n const asyncMethodSet = new Set<PropertyKey>(\n (options?.asyncMethods ?? []) as readonly PropertyKey[],\n );\n\n const startAsync = () => {\n if (!p || state === 'undecided') {\n state = 'pending';\n p = Promise.resolve()\n .then(asyncFn)\n .then(\n (v) => {\n value = v;\n state = 'fulfilled';\n return v;\n },\n (e) => {\n reason = e;\n state = 'rejected';\n throw e;\n },\n );\n }\n return p;\n };\n\n const ensureSync = () => {\n if (state === 'undecided') {\n try {\n value = sync();\n state = 'fulfilled';\n } catch (e) {\n reason = e;\n state = 'rejected';\n }\n }\n };\n\n /** \u5728\u201C\u5BF9\u8C61\u53EF\u7528\u201D\u540E\u8C03\u7528\u67D0\u4E2A\u5F02\u6B65\u65B9\u6CD5\uFF08\u7531 asyncMethods \u58F0\u660E\uFF09 */\n const makeDeferredAsyncMethod =\n (prop: PropertyKey) =>\n (...args: any[]) =>\n startAsync().then((obj) => {\n const fn = (obj as any)[prop];\n return fn.apply(obj, args);\n });\n\n // \u4ECE\u67D0\u4E2A\u503C\u4E0A\u53D6\u5C5E\u6027\uFF08\u539F\u59CB\u503C\u4F1A\u88C5\u7BB1\uFF09\uFF0C\u5E76\u7ED1\u5B9A this\n const getFrom = (v: unknown, prop: PropertyKey) => {\n if (prop === Symbol.toPrimitive) {\n return (hint: 'default' | 'number' | 'string') => {\n const x: any = v;\n if (hint === 'number') return Number(x);\n if (hint === 'string') return String(x);\n if (typeof x === 'string') return x;\n const n = Number(x);\n return Number.isNaN(n) ? String(x) : n;\n };\n }\n if (prop === 'valueOf') return () => v as any;\n if (prop === 'toString') return () => String(v);\n\n const boxed: any =\n v !== null && (typeof v === 'object' || typeof v === 'function')\n ? v\n : Object(v as any);\n const out = boxed[prop];\n return typeof out === 'function' ? out.bind(boxed) : out;\n };\n\n const proxy = new Proxy(Object.create(null) as any, {\n get(_t, prop) {\n // then/catch/finally\uFF1A\u8D70 Promise \u901A\u9053\n if (isThenKey(prop)) {\n if (state === 'undecided') {\n startAsync();\n } else if (state === 'fulfilled') {\n // \u82E5\u5DF2 fulfilled\uFF08\u6765\u81EA sync \u6216 async\uFF09\uFF0C\u8865\u4E00\u4E2A\u5DF2\u5B8C\u6210\u7684 Promise\n p ||= Promise.resolve(value);\n } else if (state === 'rejected') {\n p ||= Promise.reject(reason);\n } else {\n // pending\uFF1A\u5DF2\u6709 p\n startAsync();\n }\n const anyP: any = p;\n const m = anyP[prop];\n return typeof m === 'function' ? m.bind(anyP) : m;\n }\n\n // \u58F0\u660E\u4E3A\u5F02\u6B65\u65B9\u6CD5\u7684\u952E\uFF1A\u5728 undecided/pending \u65F6\u8FD4\u56DE\u201C\u5EF6\u8FDF\u51FD\u6570\u201D\n if (asyncMethodSet.has(prop)) {\n if (state === 'undecided' || state === 'pending') {\n startAsync();\n return makeDeferredAsyncMethod(prop);\n }\n if (state === 'fulfilled') {\n return getFrom(value, prop); // \u540C\u6B65\u53EF\u76F4\u63A5\u53D6\u5230\u65B9\u6CD5\uFF08\u5176\u672C\u8EAB\u8FD4\u56DE Promise\uFF09\n }\n if (state === 'rejected') {\n // \u8BBF\u95EE\u5373\u629B\uFF1B\u4E5F\u53EF\u4EE5\u9009\u62E9\u8FD4\u56DE () => Promise.reject(reason)\n throw reason;\n }\n }\n\n // \u5176\u5B83\u5C5E\u6027\u8BBF\u95EE\uFF1A\u9075\u5FAA\u72B6\u6001\u673A\n switch (state) {\n case 'undecided': {\n ensureSync();\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (state === 'fulfilled') return getFrom(value, prop);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (state === 'rejected') throw reason;\n // \u7406\u8BBA\u4E0A\u4E0D\u4F1A\u5230\u8FD9\u91CC\n throw new TypeError('Invalid state transition');\n }\n case 'pending': {\n // \u975E asyncMethods \u7684\u5C5E\u6027\u5728 pending \u65F6\u4E0D\u53EF\u540C\u6B65\u8BFB\u53D6\n throw new TypeError('Value is not ready yet. Please await it first.');\n }\n case 'fulfilled': {\n return getFrom(value, prop);\n }\n case 'rejected': {\n throw reason;\n }\n }\n },\n\n has(_t, key) {\n if (state === 'undecided') {\n ensureSync();\n }\n if (state === 'fulfilled') return key in Object(value as any);\n return false; // pending/rejected\uFF1A\u4FDD\u5B88\u5904\u7406\n },\n\n ownKeys() {\n if (state === 'undecided') ensureSync();\n if (state === 'fulfilled') return Reflect.ownKeys(Object(value as any));\n return [];\n },\n\n getOwnPropertyDescriptor(_t, key) {\n if (state === 'undecided') ensureSync();\n if (state === 'fulfilled')\n return Object.getOwnPropertyDescriptor(Object(value as any), key);\n return undefined;\n },\n });\n\n return proxy as Dual<T>;\n}\n", "export interface DispatcherOptions {\n /** Max attempts per task. Default 3. */\n maxAttempts?: number;\n /** Backoff base in ms. backoff = base * 2^failCount. Default 1000. */\n backoffBaseMs?: number;\n}\n\n// Internal task record\ntype Task<F extends (...args: any[]) => Promise<any>> = {\n args: Parameters<F>;\n resolve: (v: Awaited<ReturnType<F>>) => void;\n reject: (e: any) => void;\n attempts: number;\n lastError?: any;\n triedWorkers: Set<number>; // for global dispatch\n specificWorkerIndex?: number; // for dispatchSpecific only\n};\n\ntype WorkerState = {\n running: boolean;\n failCount: number;\n nextAvailableAt: number;\n totalRuns: number;\n};\n\ntype RemovalWaiter = () => void;\n\ntype ActiveSlot<F extends (...args: any[]) => Promise<any>> = {\n kind: 'active';\n fn: F;\n state: WorkerState;\n queue: Task<F>[];\n removalWaiters: RemovalWaiter[];\n removed?: boolean; // marker when removed while running; retained for completion callback\n};\n\ntype PendingSlot<F extends (...args: any[]) => Promise<any>> = {\n kind: 'pending';\n promise: Promise<F>;\n queue: Task<F>[];\n removalWaiters: RemovalWaiter[];\n error?: any;\n removed?: boolean; // if removed before resolved\n};\n\ntype RejectedSlot<F extends (...args: any[]) => Promise<any>> = {\n kind: 'rejected';\n error: any;\n queue: Task<F>[];\n removalWaiters: RemovalWaiter[];\n removed?: boolean;\n};\n\ntype Slot<F extends (...args: any[]) => Promise<any>> =\n | ActiveSlot<F>\n | PendingSlot<F>\n | RejectedSlot<F>;\n\nexport type WorkerSnapshot<F extends (...args: any[]) => Promise<any>> =\n | {\n index: number;\n status: 'active';\n fn: F;\n running: boolean;\n failCount: number;\n totalRuns: number;\n blockedMs: number;\n specificQueue: number;\n }\n | {\n index: number;\n status: 'pending';\n promise: Promise<F>;\n specificQueue: number;\n }\n | {\n index: number;\n status: 'rejected';\n error: string;\n specificQueue: number;\n };\n\nexport class WorkflowDispatcher<F extends (...args: any[]) => Promise<any>> {\n private readonly maxAttempts: number;\n private readonly backoffBaseMs: number;\n\n private readonly slots: Slot<F>[] = [];\n private readonly globalQueue: Task<F>[] = [];\n\n private pendingInits = 0;\n private everActivated = false;\n private drainScheduled = false;\n\n constructor(\n workersOrPromises: Array<F | Promise<F>>,\n options: DispatcherOptions = {},\n ) {\n // if (!workersOrPromises?.length) throw new Error('workers cannot be empty');\n\n this.maxAttempts = options.maxAttempts ?? 3;\n this.backoffBaseMs = options.backoffBaseMs ?? 1000;\n\n for (let i = 0; i < workersOrPromises.length; i++) {\n const w = workersOrPromises[i];\n if (typeof w === 'function') {\n const slot: ActiveSlot<F> = {\n kind: 'active',\n fn: w,\n state: {\n running: false,\n failCount: 0,\n nextAvailableAt: 0,\n totalRuns: 0,\n },\n queue: [],\n removalWaiters: [],\n };\n this.slots.push(slot);\n this.everActivated = true;\n } else {\n // Create a stable slot object and mutate it in-place on resolve/reject.\n this.pendingInits++;\n const slot: PendingSlot<F> = {\n kind: 'pending',\n promise: Promise.resolve(w),\n queue: [],\n removalWaiters: [],\n };\n this.slots.push(slot);\n\n slot.promise\n .then((fn) => {\n if (slot.removed) return; // was removed; ignore resolution\n // mutate in-place to active\n (slot as any).kind = 'active';\n (slot as any).fn = fn;\n (slot as any).state = {\n running: false,\n failCount: 0,\n nextAvailableAt: 0,\n totalRuns: 0,\n };\n this.everActivated = true;\n // keep queue & removalWaiters arrays as-is\n })\n .catch((err) => {\n if (slot.removed) return; // was removed; ignore\n // mutate in-place to rejected (keep queue/waiters)\n (slot as any).kind = 'rejected';\n (slot as any).error = err;\n })\n .finally(() => {\n this.pendingInits--;\n this.drain();\n if (this.pendingInits === 0 && !this.hasAnyActive()) {\n const err = new Error(\n 'No workers available (all failed to initialize).',\n );\n setTimeout(() => this.rejectAllQueued(err), 0);\n }\n });\n }\n }\n\n if (this.everActivated) this.drain();\n }\n\n /** Dispatch: choose eligible active with least totalRuns; retry across workers on failure. */\n dispatch(...args: Parameters<F>): Promise<Awaited<ReturnType<F>>> {\n return new Promise((resolve, reject) => {\n const task: Task<F> = {\n args,\n resolve,\n reject,\n attempts: 0,\n triedWorkers: new Set(),\n };\n this.globalQueue.push(task);\n this.drain();\n });\n }\n\n /** Dispatch to a specific worker (ignore backoff), wait until it is free; retry on the same worker. */\n dispatchSpecific(\n index: number,\n ...args: Parameters<F>\n ): Promise<Awaited<ReturnType<F>>> {\n if (index < 0 || index >= this.slots.length) {\n return Promise.reject(new Error(`worker index out of range: ${index}`));\n }\n return new Promise((resolve, reject) => {\n const task: Task<F> = {\n args,\n resolve,\n reject,\n attempts: 0,\n triedWorkers: new Set(),\n specificWorkerIndex: index,\n };\n const slot = this.slots[index];\n slot.queue.push(task);\n this.drain();\n });\n }\n\n /** Replace a worker at index with a new active worker function. */\n public replaceWorker(index: number, fn: F): void {\n if (index < 0 || index >= this.slots.length) {\n throw new Error(`worker index out of range: ${index}`);\n }\n const prevHadActive = this.hasAnyActive();\n const slot = this.slots[index];\n\n // Preserve queue & removal waiters; reset failure/backoff; keep totalRuns to avoid skew.\n const preservedQueue = slot.queue;\n const preservedWaiters = slot.removalWaiters ?? [];\n\n const next: ActiveSlot<F> = {\n kind: 'active',\n fn,\n state: {\n running: false,\n failCount: 0,\n nextAvailableAt: 0,\n totalRuns: (slot as any).state?.totalRuns ?? 0,\n },\n queue: preservedQueue,\n removalWaiters: preservedWaiters,\n };\n\n // Mutate in-place if possible (keeps references stable), else replace array entry.\n Object.assign(slot as any, next);\n (slot as any).kind = 'active';\n (slot as any).fn = fn;\n (slot as any).state.failCount = 0;\n (slot as any).state.nextAvailableAt = 0;\n\n this.everActivated = true;\n if (!prevHadActive && this.hasAnyActive()) {\n this.drain();\n } else {\n this.drain();\n }\n }\n\n /** Add a new active worker at the tail; return its index. */\n public addWorker(fn: F): number {\n const slot: ActiveSlot<F> = {\n kind: 'active',\n fn,\n state: { running: false, failCount: 0, nextAvailableAt: 0, totalRuns: 0 },\n queue: [],\n removalWaiters: [],\n };\n const index = this.slots.length;\n this.slots.push(slot);\n this.everActivated = true;\n this.drain();\n return index;\n }\n\n /**\n * Remove a worker completely (splice). It becomes unavailable immediately.\n * Returns a Promise that resolves when its last running task (if any) finishes.\n */\n public removeWorker(index: number): Promise<void> {\n if (index < 0 || index >= this.slots.length) {\n return Promise.reject(new Error(`worker index out of range: ${index}`));\n }\n\n const slot = this.slots[index];\n\n // Reject all queued specific tasks on this worker (macro-task to avoid unhandled)\n const queued = slot.queue.splice(0);\n const removalErr = new Error(`Worker[${index}] removed`);\n setTimeout(() => {\n for (const t of queued) t.reject(removalErr);\n }, 0);\n\n // Decide completion promise:\n let completion: Promise<void>;\n const isRunning = slot.kind === 'active' && slot.state.running;\n if (!isRunning) {\n completion = Promise.resolve();\n } else {\n completion = new Promise<void>((resolve) => {\n slot.removalWaiters.push(resolve);\n });\n }\n\n // Mark as removed (so any pending init resolution is ignored)\n (slot as any).removed = true;\n\n // Physically remove the slot\n this.slots.splice(index, 1);\n\n // Re-map indices in all remaining tasks:\n // 1) Fix specificWorkerIndex in every remaining slot.queue\n for (let i = 0; i < this.slots.length; i++) {\n const s = this.slots[i];\n for (const t of s.queue) {\n if (typeof t.specificWorkerIndex === 'number') {\n if (t.specificWorkerIndex === index) {\n // This should not happen because we just removed and flushed its queue,\n // but guard anyway.\n t.reject(new Error(`Worker[${index}] no longer exists`));\n } else if (t.specificWorkerIndex > index) {\n t.specificWorkerIndex -= 1;\n }\n }\n }\n }\n // 2) Fix triedWorkers sets in globalQueue\n for (const t of this.globalQueue) {\n if (t.triedWorkers.has(index)) t.triedWorkers.delete(index);\n const next = new Set<number>();\n for (const w of t.triedWorkers) {\n next.add(w > index ? w - 1 : w);\n }\n t.triedWorkers = next;\n }\n\n // Trigger scheduling for the remaining system\n this.drain();\n\n return completion;\n }\n\n snapshot(): WorkerSnapshot<F>[] {\n const now = Date.now();\n\n return this.slots.map((slot, i) => {\n switch (slot.kind) {\n case 'active': {\n const s = slot.state;\n return {\n index: i,\n status: 'active' as const,\n fn: slot.fn,\n running: s.running,\n failCount: s.failCount,\n totalRuns: s.totalRuns,\n blockedMs: Math.max(0, s.nextAvailableAt - now),\n specificQueue: slot.queue.length,\n };\n }\n\n case 'pending':\n return {\n index: i,\n status: 'pending' as const,\n promise: slot.promise,\n specificQueue: slot.queue.length,\n };\n\n case 'rejected':\n return {\n index: i,\n status: 'rejected' as const,\n error: String(slot.error ?? 'unknown error'),\n specificQueue: slot.queue.length,\n };\n }\n });\n }\n\n get pending(): number {\n return this.globalQueue.length;\n }\n\n // ---------------- scheduling ----------------\n\n private drain() {\n if (this.drainScheduled) return;\n this.drainScheduled = true;\n queueMicrotask(() => {\n this.drainScheduled = false;\n this._drainLoop();\n });\n }\n\n private _drainLoop() {\n // If no active workers and still initializing, wait; if all inited and none active, constructor already rejects all.\n if (!this.hasAnyActive()) {\n if (this.pendingInits > 0) return;\n return;\n }\n\n // First: flush rejected workers' specific queues (macro-task rejection)\n for (let i = 0; i < this.slots.length; i++) {\n const slot = this.slots[i];\n if (slot.kind === 'rejected' && slot.queue.length > 0) {\n const q = slot.queue.splice(0);\n const err = new Error(\n `Worker[${i}] failed to initialize: ${String(slot.error ?? 'unknown error')}`,\n );\n setTimeout(() => {\n for (const t of q) t.reject(err);\n }, 0);\n }\n }\n\n let progressed = true;\n while (progressed) {\n progressed = false;\n\n // 1) Run specific queues for active workers (ignore backoff)\n for (let i = 0; i < this.slots.length; i++) {\n const slot = this.slots[i];\n if (slot.kind !== 'active') continue;\n const st = slot.state;\n if (!st.running && slot.queue.length > 0) {\n const task = slot.queue.shift()!;\n this.startTaskOnActiveSlot(i, slot, task, /*fromSpecific*/ true);\n progressed = true;\n }\n }\n\n // 2) Run global queue (choose eligible active with least totalRuns)\n if (this.globalQueue.length > 0) {\n const idx = this.pickBestActiveForGlobal();\n if (idx !== -1) {\n const slot = this.slots[idx] as ActiveSlot<F>;\n const task = this.globalQueue.shift()!;\n this.startTaskOnActiveSlot(idx, slot, task, /*fromSpecific*/ false);\n progressed = true;\n }\n }\n }\n }\n\n private hasAnyActive() {\n return this.slots.some((s) => s.kind === 'active');\n }\n\n private rejectAllQueued(err: any) {\n while (this.globalQueue.length) this.globalQueue.shift()!.reject(err);\n for (const slot of this.slots) {\n while (slot.queue.length) slot.queue.shift()!.reject(err);\n }\n }\n\n private isEligibleActive(i: number, now: number) {\n const slot = this.slots[i];\n if (!slot || slot.kind !== 'active') return false;\n const s = slot.state;\n return !s.running && now >= s.nextAvailableAt;\n // note: specific queues ignore backoff; this is only for global picks.\n }\n\n private pickBestActiveForGlobal(): number {\n const now = Date.now();\n const task = this.globalQueue[0];\n\n // Prefer actives not tried yet\n let best = -1,\n bestRuns = Infinity;\n for (let i = 0; i < this.slots.length; i++) {\n if (!this.isEligibleActive(i, now)) continue;\n if (task?.triedWorkers.has(i)) continue;\n const slot = this.slots[i] as ActiveSlot<F>;\n if (slot.state.totalRuns < bestRuns) {\n bestRuns = slot.state.totalRuns;\n best = i;\n }\n }\n if (best !== -1) return best;\n\n // Allow already-tried actives\n best = -1;\n bestRuns = Infinity;\n for (let i = 0; i < this.slots.length; i++) {\n if (!this.isEligibleActive(i, now)) continue;\n const slot = this.slots[i] as ActiveSlot<F>;\n if (slot.state.totalRuns < bestRuns) {\n bestRuns = slot.state.totalRuns;\n best = i;\n }\n }\n return best;\n }\n\n private startTaskOnActiveSlot(\n index: number,\n slot: ActiveSlot<F>,\n task: Task<F>,\n fromSpecific: boolean,\n ) {\n const st = slot.state;\n st.running = true;\n st.totalRuns += 1;\n\n const finalize = () => {\n st.running = false;\n // If someone is waiting for this worker to finish (removeWorker), resolve them when idle.\n if (\n slot.removalWaiters.length > 0 &&\n !st.running &&\n slot.queue.length === 0\n ) {\n const list = slot.removalWaiters.splice(0);\n for (const w of list) w();\n }\n this.drain();\n };\n\n (async () => {\n try {\n const result = await slot.fn(...task.args);\n st.failCount = Math.max(0, st.failCount - 1);\n task.resolve(result as Awaited<ReturnType<F>>);\n } catch (err) {\n task.lastError = err;\n st.failCount += 1;\n st.nextAvailableAt =\n Date.now() + this.backoffBaseMs * Math.pow(2, st.failCount);\n\n if (fromSpecific) {\n task.attempts += 1;\n if (task.attempts >= this.maxAttempts) {\n task.reject(task.lastError);\n } else {\n // retry on the same worker (ignore backoff)\n slot.queue.push(task);\n }\n } else {\n task.attempts += 1;\n task.triedWorkers.add(index);\n const activeCount = this.slots.filter(\n (s) => s.kind === 'active',\n ).length;\n const allActiveTriedOnce = task.triedWorkers.size >= activeCount;\n const attemptsLimitReached = task.attempts >= this.maxAttempts;\n\n if (allActiveTriedOnce || attemptsLimitReached) {\n task.reject(task.lastError);\n } else {\n this.globalQueue.push(task);\n }\n }\n } finally {\n finalize();\n }\n })();\n }\n}\n", "export class RoundRobin<T> {\n private index = 0;\n\n constructor(public items: T[]) {\n if (items.length === 0) {\n throw new Error('RoundRobin requires at least one item');\n }\n }\n\n next(): T {\n const nextIndex = this.index % this.items.length;\n this.index = (this.index + 1) % this.items.length;\n return this.items[nextIndex];\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './src/workflow';
2
2
  export * from './src/dual-object';
3
3
  export * from './src/workflow-dispatcher';
4
+ export * from './src/round-robin';
package/dist/index.mjs CHANGED
@@ -598,7 +598,24 @@ var WorkflowDispatcher = class {
598
598
  })();
599
599
  }
600
600
  };
601
+
602
+ // src/round-robin.ts
603
+ var RoundRobin = class {
604
+ constructor(items) {
605
+ this.items = items;
606
+ this.index = 0;
607
+ if (items.length === 0) {
608
+ throw new Error("RoundRobin requires at least one item");
609
+ }
610
+ }
611
+ next() {
612
+ const nextIndex = this.index % this.items.length;
613
+ this.index = (this.index + 1) % this.items.length;
614
+ return this.items[nextIndex];
615
+ }
616
+ };
601
617
  export {
618
+ RoundRobin,
602
619
  WF_NODE,
603
620
  WorkflowDispatcher,
604
621
  dualizeAny,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/workflow.ts", "../src/dual-object.ts", "../src/workflow-dispatcher.ts"],
4
- "sourcesContent": ["// ========== \u7C7B\u578B\u5DE5\u5177 ==========\ntype AwaitedLike<T> = T extends Promise<infer R> ? R : T;\ntype AnyFn = (...args: any[]) => any;\n\ntype Chain<T> = Promise<AwaitedLike<T>> &\n (T extends AnyFn\n ? (...a: Parameters<T>) => Chain<AwaitedLike<ReturnType<T>>>\n : {}) & {\n [K in keyof T]: T[K] extends (...a: infer A) => infer R\n ? (...a: A) => Chain<AwaitedLike<R>>\n : Chain<AwaitedLike<T[K]>>;\n };\n\n// ========== \u6838\u5FC3\uFF1A\u4E0D\u53EF\u53D8\u8282\u70B9 ==========\nclass Node {\n private memo?: Promise<any>;\n constructor(\n private readonly source: any, // \u53EA\u6709\u6839\u8282\u70B9\u6709\u610F\u4E49\uFF1B\u5B50\u8282\u70B9\u53EF\u590D\u7528\u6839\u7684 source\n private readonly parent: Node | null, // \u524D\u7F00\n private readonly op: ((x: any) => any) | null, // \u4ECE parent \u7ED3\u679C\u5230\u672C\u8282\u70B9\u7ED3\u679C\u7684\u53D8\u6362\n ) {}\n\n run(): Promise<any> {\n if (!this.memo) {\n this.memo = (async () => {\n if (!this.parent) {\n // \u6839\uFF1A\u628A source \u89E3\u4E00\u6B21\u5373\u53EF\n return await this.source;\n }\n // \u5148\u62FF\u5230\u7236\u8282\u70B9\u7ED3\u679C\uFF08\u4F1A\u8BB0\u5FC6\u5316\uFF09\n const base = await this.parent.run();\n // \u5E94\u7528\u672C\u8282\u70B9\u7684\u53D8\u6362\uFF08\u5141\u8BB8\u8FD4\u56DE\u540C\u6B65\u6216\u5F02\u6B65\uFF09\n return this.op ? this.op(base) : base;\n })();\n }\n return this.memo;\n }\n\n // \u5DE5\u5382\uFF1A\u884D\u751F\u5B50\u8282\u70B9\uFF08\u5206\u53C9 = \u590D\u7528\u540C\u4E00\u4E2A parent\uFF09\n child(op: (x: any) => any): Node {\n return new Node(this.source, this, op);\n }\n\n // \u62FF\u5230\u201C\u76F8\u540C\u8282\u70B9\u201D\u7684\u53E5\u67C4\uFF08\u663E\u5F0F fork\uFF09\n fork(): Node {\n return new Node(this.source, this.parent, this.op);\n }\n}\n\nexport const WF_NODE = Symbol('@@workflow/node');\n\nfunction isWorkflowChain(x: any): x is Chain<any> {\n return !!x && typeof x === 'function' && x[WF_NODE] instanceof Node;\n}\n\n// ========== \u5BF9\u5916 API\uFF1Aworkflow ==========\nexport function workflow<T>(source: T | Promise<T>): Chain<T> {\n if (isWorkflowChain(source)) {\n return source as unknown as Chain<T>;\n }\n const root = new Node(source, null, null);\n return makeProxy<T>(root) as any;\n}\n\n// ========== \u4EE3\u7406\u5C42\uFF1A\u628A Node \u66B4\u9732\u6210\u94FE\u5F0F API ==========\nfunction makeProxy<T>(node: Node): Chain<T> {\n const runOnce = () => node.run(); // \u8BB0\u5FC6\u5316\u5728 Node \u5185\u90E8\n\n const rootHandler: ProxyHandler<any> = {\n get(_t, prop) {\n if (prop === WF_NODE) return node;\n // \u7ED3\u675F\u4FE1\u53F7\uFF1A\u6240\u6709 then/catch/finally \u590D\u7528\u540C\u4E00\u4E2A Promise\n if (prop === 'then')\n return (res: any, rej?: any) => runOnce().then(res, rej);\n if (prop === 'catch') return (rej: any) => runOnce().catch(rej);\n if (prop === 'finally') return (fin: any) => runOnce().finally(fin);\n\n // \u8BBF\u95EE\u4E00\u4E2A\u5C5E\u6027\uFF1A\u751F\u6210\u4E00\u4E2A\u201CGet\u201D\u5B50\u8282\u70B9\uFF0C\u4F46\u4E0D\u6267\u884C\n return linkProxy(prop);\n },\n // \u652F\u6301\u5BF9\u201C\u5F53\u524D\u503C\u201D\u76F4\u63A5\u4E8C\u6B21\u8C03\u7528\uFF1A foo()()\n apply(_t, _this, argArray) {\n const child = node.child((cur: any) => {\n if (typeof cur !== 'function')\n throw new TypeError('Current value is not callable');\n return cur(...argArray);\n });\n return makeProxy<any>(child);\n },\n };\n\n const linkProxy = (prop: PropertyKey) =>\n new Proxy(function () {}, {\n // \u628A \u201C.foo(\u2026args)\u201D \u8BB0\u5F55\u4E3A Call\n apply(_t, _this, argArray) {\n const child = node.child((cur: any) => {\n const fn = (cur as any)[prop];\n if (typeof fn !== 'function') {\n throw new TypeError(`${String(prop)} is not a function`);\n }\n return fn.apply(cur, argArray);\n });\n return makeProxy<any>(child);\n },\n // \u628A \u201C.bar\u201D \u8BB0\u5F55\u4E3A Get\uFF1B\u7EE7\u7EED\u6DF1\u5165\u65F6\u5728\u8FD9\u4E2A Get \u7684\u7ED3\u679C\u4E0A\u518D\u5904\u7406\n get(_t, next) {\n if (next === WF_NODE) return node;\n if (next === 'then')\n return (r: any, j?: any) =>\n node\n .child((cur: any) => (cur as any)[prop])\n .run()\n .then(r, j);\n if (next === 'catch')\n return (rej: any) =>\n node\n .child((cur: any) => (cur as any)[prop])\n .run()\n .catch(rej);\n if (next === 'finally')\n return (fin: any) =>\n node\n .child((cur: any) => (cur as any)[prop])\n .run()\n .finally(fin);\n\n const child = node.child((cur: any) => (cur as any)[prop]);\n return (makeProxy as any)(child)[next];\n },\n });\n\n return new Proxy(function () {}, rootHandler) as any;\n}\n", "// dual-unified.ts\nexport type Dual<T> = T & PromiseLike<T>;\n\ntype ThenKey = 'then' | 'catch' | 'finally';\nconst isThenKey = (k: PropertyKey): k is ThenKey =>\n k === 'then' || k === 'catch' || k === 'finally';\n\ntype State = 'undecided' | 'pending' | 'fulfilled' | 'rejected';\n\n/** \u4EC5\u5141\u8BB8\u586B\u5165 \u201C\u8FD4\u56DE Promise \u7684\u65B9\u6CD5\u540D\u201D */\nexport type AsyncMethodKeys<T> = {\n [K in keyof T]-?: T[K] extends (...args: any[]) => Promise<any> ? K : never;\n}[keyof T];\n\nexport interface DualizeOptions<T> {\n /** \u8FD9\u4E9B\u65B9\u6CD5\u5728 undecided/pending \u65F6\u4F1A\u8FD4\u56DE\u4E00\u4E2A\u5EF6\u8FDF\u6267\u884C\u51FD\u6570\uFF0C\u7B49\u5F85\u5BF9\u8C61 Promise \u5B8C\u6210\u540E\u518D\u8C03\u7528 */\n asyncMethods?: readonly AsyncMethodKeys<T>[];\n}\n\nexport function dualizeAny<T>(\n sync: () => T, // \u540C\u6B65\u6784\u9020\uFF1B\u82E5\u629B\u9519\u5219\u89C6\u4E3A rejected\n asyncFn: () => Promise<T>, // \u5F02\u6B65\u6784\u9020\n options?: DualizeOptions<T>,\n): Dual<T> {\n let state: State = 'undecided';\n\n let value!: T; // fulfilled \u65F6\u7684\u503C\uFF08\u542B\u6765\u81EA sync \u6216 async\uFF09\n let reason: any; // rejected \u7684\u9519\u8BEF\n let p!: Promise<T>; // \u7F13\u5B58 Promise\uFF08resolved/rejected/\u8FDB\u884C\u4E2D\uFF09\n\n const asyncMethodSet = new Set<PropertyKey>(\n (options?.asyncMethods ?? []) as readonly PropertyKey[],\n );\n\n const startAsync = () => {\n if (!p || state === 'undecided') {\n state = 'pending';\n p = Promise.resolve()\n .then(asyncFn)\n .then(\n (v) => {\n value = v;\n state = 'fulfilled';\n return v;\n },\n (e) => {\n reason = e;\n state = 'rejected';\n throw e;\n },\n );\n }\n return p;\n };\n\n const ensureSync = () => {\n if (state === 'undecided') {\n try {\n value = sync();\n state = 'fulfilled';\n } catch (e) {\n reason = e;\n state = 'rejected';\n }\n }\n };\n\n /** \u5728\u201C\u5BF9\u8C61\u53EF\u7528\u201D\u540E\u8C03\u7528\u67D0\u4E2A\u5F02\u6B65\u65B9\u6CD5\uFF08\u7531 asyncMethods \u58F0\u660E\uFF09 */\n const makeDeferredAsyncMethod =\n (prop: PropertyKey) =>\n (...args: any[]) =>\n startAsync().then((obj) => {\n const fn = (obj as any)[prop];\n return fn.apply(obj, args);\n });\n\n // \u4ECE\u67D0\u4E2A\u503C\u4E0A\u53D6\u5C5E\u6027\uFF08\u539F\u59CB\u503C\u4F1A\u88C5\u7BB1\uFF09\uFF0C\u5E76\u7ED1\u5B9A this\n const getFrom = (v: unknown, prop: PropertyKey) => {\n if (prop === Symbol.toPrimitive) {\n return (hint: 'default' | 'number' | 'string') => {\n const x: any = v;\n if (hint === 'number') return Number(x);\n if (hint === 'string') return String(x);\n if (typeof x === 'string') return x;\n const n = Number(x);\n return Number.isNaN(n) ? String(x) : n;\n };\n }\n if (prop === 'valueOf') return () => v as any;\n if (prop === 'toString') return () => String(v);\n\n const boxed: any =\n v !== null && (typeof v === 'object' || typeof v === 'function')\n ? v\n : Object(v as any);\n const out = boxed[prop];\n return typeof out === 'function' ? out.bind(boxed) : out;\n };\n\n const proxy = new Proxy(Object.create(null) as any, {\n get(_t, prop) {\n // then/catch/finally\uFF1A\u8D70 Promise \u901A\u9053\n if (isThenKey(prop)) {\n if (state === 'undecided') {\n startAsync();\n } else if (state === 'fulfilled') {\n // \u82E5\u5DF2 fulfilled\uFF08\u6765\u81EA sync \u6216 async\uFF09\uFF0C\u8865\u4E00\u4E2A\u5DF2\u5B8C\u6210\u7684 Promise\n p ||= Promise.resolve(value);\n } else if (state === 'rejected') {\n p ||= Promise.reject(reason);\n } else {\n // pending\uFF1A\u5DF2\u6709 p\n startAsync();\n }\n const anyP: any = p;\n const m = anyP[prop];\n return typeof m === 'function' ? m.bind(anyP) : m;\n }\n\n // \u58F0\u660E\u4E3A\u5F02\u6B65\u65B9\u6CD5\u7684\u952E\uFF1A\u5728 undecided/pending \u65F6\u8FD4\u56DE\u201C\u5EF6\u8FDF\u51FD\u6570\u201D\n if (asyncMethodSet.has(prop)) {\n if (state === 'undecided' || state === 'pending') {\n startAsync();\n return makeDeferredAsyncMethod(prop);\n }\n if (state === 'fulfilled') {\n return getFrom(value, prop); // \u540C\u6B65\u53EF\u76F4\u63A5\u53D6\u5230\u65B9\u6CD5\uFF08\u5176\u672C\u8EAB\u8FD4\u56DE Promise\uFF09\n }\n if (state === 'rejected') {\n // \u8BBF\u95EE\u5373\u629B\uFF1B\u4E5F\u53EF\u4EE5\u9009\u62E9\u8FD4\u56DE () => Promise.reject(reason)\n throw reason;\n }\n }\n\n // \u5176\u5B83\u5C5E\u6027\u8BBF\u95EE\uFF1A\u9075\u5FAA\u72B6\u6001\u673A\n switch (state) {\n case 'undecided': {\n ensureSync();\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (state === 'fulfilled') return getFrom(value, prop);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (state === 'rejected') throw reason;\n // \u7406\u8BBA\u4E0A\u4E0D\u4F1A\u5230\u8FD9\u91CC\n throw new TypeError('Invalid state transition');\n }\n case 'pending': {\n // \u975E asyncMethods \u7684\u5C5E\u6027\u5728 pending \u65F6\u4E0D\u53EF\u540C\u6B65\u8BFB\u53D6\n throw new TypeError('Value is not ready yet. Please await it first.');\n }\n case 'fulfilled': {\n return getFrom(value, prop);\n }\n case 'rejected': {\n throw reason;\n }\n }\n },\n\n has(_t, key) {\n if (state === 'undecided') {\n ensureSync();\n }\n if (state === 'fulfilled') return key in Object(value as any);\n return false; // pending/rejected\uFF1A\u4FDD\u5B88\u5904\u7406\n },\n\n ownKeys() {\n if (state === 'undecided') ensureSync();\n if (state === 'fulfilled') return Reflect.ownKeys(Object(value as any));\n return [];\n },\n\n getOwnPropertyDescriptor(_t, key) {\n if (state === 'undecided') ensureSync();\n if (state === 'fulfilled')\n return Object.getOwnPropertyDescriptor(Object(value as any), key);\n return undefined;\n },\n });\n\n return proxy as Dual<T>;\n}\n", "export interface DispatcherOptions {\n /** Max attempts per task. Default 3. */\n maxAttempts?: number;\n /** Backoff base in ms. backoff = base * 2^failCount. Default 1000. */\n backoffBaseMs?: number;\n}\n\n// Internal task record\ntype Task<F extends (...args: any[]) => Promise<any>> = {\n args: Parameters<F>;\n resolve: (v: Awaited<ReturnType<F>>) => void;\n reject: (e: any) => void;\n attempts: number;\n lastError?: any;\n triedWorkers: Set<number>; // for global dispatch\n specificWorkerIndex?: number; // for dispatchSpecific only\n};\n\ntype WorkerState = {\n running: boolean;\n failCount: number;\n nextAvailableAt: number;\n totalRuns: number;\n};\n\ntype RemovalWaiter = () => void;\n\ntype ActiveSlot<F extends (...args: any[]) => Promise<any>> = {\n kind: 'active';\n fn: F;\n state: WorkerState;\n queue: Task<F>[];\n removalWaiters: RemovalWaiter[];\n removed?: boolean; // marker when removed while running; retained for completion callback\n};\n\ntype PendingSlot<F extends (...args: any[]) => Promise<any>> = {\n kind: 'pending';\n promise: Promise<F>;\n queue: Task<F>[];\n removalWaiters: RemovalWaiter[];\n error?: any;\n removed?: boolean; // if removed before resolved\n};\n\ntype RejectedSlot<F extends (...args: any[]) => Promise<any>> = {\n kind: 'rejected';\n error: any;\n queue: Task<F>[];\n removalWaiters: RemovalWaiter[];\n removed?: boolean;\n};\n\ntype Slot<F extends (...args: any[]) => Promise<any>> =\n | ActiveSlot<F>\n | PendingSlot<F>\n | RejectedSlot<F>;\n\nexport type WorkerSnapshot<F extends (...args: any[]) => Promise<any>> =\n | {\n index: number;\n status: 'active';\n fn: F;\n running: boolean;\n failCount: number;\n totalRuns: number;\n blockedMs: number;\n specificQueue: number;\n }\n | {\n index: number;\n status: 'pending';\n promise: Promise<F>;\n specificQueue: number;\n }\n | {\n index: number;\n status: 'rejected';\n error: string;\n specificQueue: number;\n };\n\nexport class WorkflowDispatcher<F extends (...args: any[]) => Promise<any>> {\n private readonly maxAttempts: number;\n private readonly backoffBaseMs: number;\n\n private readonly slots: Slot<F>[] = [];\n private readonly globalQueue: Task<F>[] = [];\n\n private pendingInits = 0;\n private everActivated = false;\n private drainScheduled = false;\n\n constructor(\n workersOrPromises: Array<F | Promise<F>>,\n options: DispatcherOptions = {},\n ) {\n // if (!workersOrPromises?.length) throw new Error('workers cannot be empty');\n\n this.maxAttempts = options.maxAttempts ?? 3;\n this.backoffBaseMs = options.backoffBaseMs ?? 1000;\n\n for (let i = 0; i < workersOrPromises.length; i++) {\n const w = workersOrPromises[i];\n if (typeof w === 'function') {\n const slot: ActiveSlot<F> = {\n kind: 'active',\n fn: w,\n state: {\n running: false,\n failCount: 0,\n nextAvailableAt: 0,\n totalRuns: 0,\n },\n queue: [],\n removalWaiters: [],\n };\n this.slots.push(slot);\n this.everActivated = true;\n } else {\n // Create a stable slot object and mutate it in-place on resolve/reject.\n this.pendingInits++;\n const slot: PendingSlot<F> = {\n kind: 'pending',\n promise: Promise.resolve(w),\n queue: [],\n removalWaiters: [],\n };\n this.slots.push(slot);\n\n slot.promise\n .then((fn) => {\n if (slot.removed) return; // was removed; ignore resolution\n // mutate in-place to active\n (slot as any).kind = 'active';\n (slot as any).fn = fn;\n (slot as any).state = {\n running: false,\n failCount: 0,\n nextAvailableAt: 0,\n totalRuns: 0,\n };\n this.everActivated = true;\n // keep queue & removalWaiters arrays as-is\n })\n .catch((err) => {\n if (slot.removed) return; // was removed; ignore\n // mutate in-place to rejected (keep queue/waiters)\n (slot as any).kind = 'rejected';\n (slot as any).error = err;\n })\n .finally(() => {\n this.pendingInits--;\n this.drain();\n if (this.pendingInits === 0 && !this.hasAnyActive()) {\n const err = new Error(\n 'No workers available (all failed to initialize).',\n );\n setTimeout(() => this.rejectAllQueued(err), 0);\n }\n });\n }\n }\n\n if (this.everActivated) this.drain();\n }\n\n /** Dispatch: choose eligible active with least totalRuns; retry across workers on failure. */\n dispatch(...args: Parameters<F>): Promise<Awaited<ReturnType<F>>> {\n return new Promise((resolve, reject) => {\n const task: Task<F> = {\n args,\n resolve,\n reject,\n attempts: 0,\n triedWorkers: new Set(),\n };\n this.globalQueue.push(task);\n this.drain();\n });\n }\n\n /** Dispatch to a specific worker (ignore backoff), wait until it is free; retry on the same worker. */\n dispatchSpecific(\n index: number,\n ...args: Parameters<F>\n ): Promise<Awaited<ReturnType<F>>> {\n if (index < 0 || index >= this.slots.length) {\n return Promise.reject(new Error(`worker index out of range: ${index}`));\n }\n return new Promise((resolve, reject) => {\n const task: Task<F> = {\n args,\n resolve,\n reject,\n attempts: 0,\n triedWorkers: new Set(),\n specificWorkerIndex: index,\n };\n const slot = this.slots[index];\n slot.queue.push(task);\n this.drain();\n });\n }\n\n /** Replace a worker at index with a new active worker function. */\n public replaceWorker(index: number, fn: F): void {\n if (index < 0 || index >= this.slots.length) {\n throw new Error(`worker index out of range: ${index}`);\n }\n const prevHadActive = this.hasAnyActive();\n const slot = this.slots[index];\n\n // Preserve queue & removal waiters; reset failure/backoff; keep totalRuns to avoid skew.\n const preservedQueue = slot.queue;\n const preservedWaiters = slot.removalWaiters ?? [];\n\n const next: ActiveSlot<F> = {\n kind: 'active',\n fn,\n state: {\n running: false,\n failCount: 0,\n nextAvailableAt: 0,\n totalRuns: (slot as any).state?.totalRuns ?? 0,\n },\n queue: preservedQueue,\n removalWaiters: preservedWaiters,\n };\n\n // Mutate in-place if possible (keeps references stable), else replace array entry.\n Object.assign(slot as any, next);\n (slot as any).kind = 'active';\n (slot as any).fn = fn;\n (slot as any).state.failCount = 0;\n (slot as any).state.nextAvailableAt = 0;\n\n this.everActivated = true;\n if (!prevHadActive && this.hasAnyActive()) {\n this.drain();\n } else {\n this.drain();\n }\n }\n\n /** Add a new active worker at the tail; return its index. */\n public addWorker(fn: F): number {\n const slot: ActiveSlot<F> = {\n kind: 'active',\n fn,\n state: { running: false, failCount: 0, nextAvailableAt: 0, totalRuns: 0 },\n queue: [],\n removalWaiters: [],\n };\n const index = this.slots.length;\n this.slots.push(slot);\n this.everActivated = true;\n this.drain();\n return index;\n }\n\n /**\n * Remove a worker completely (splice). It becomes unavailable immediately.\n * Returns a Promise that resolves when its last running task (if any) finishes.\n */\n public removeWorker(index: number): Promise<void> {\n if (index < 0 || index >= this.slots.length) {\n return Promise.reject(new Error(`worker index out of range: ${index}`));\n }\n\n const slot = this.slots[index];\n\n // Reject all queued specific tasks on this worker (macro-task to avoid unhandled)\n const queued = slot.queue.splice(0);\n const removalErr = new Error(`Worker[${index}] removed`);\n setTimeout(() => {\n for (const t of queued) t.reject(removalErr);\n }, 0);\n\n // Decide completion promise:\n let completion: Promise<void>;\n const isRunning = slot.kind === 'active' && slot.state.running;\n if (!isRunning) {\n completion = Promise.resolve();\n } else {\n completion = new Promise<void>((resolve) => {\n slot.removalWaiters.push(resolve);\n });\n }\n\n // Mark as removed (so any pending init resolution is ignored)\n (slot as any).removed = true;\n\n // Physically remove the slot\n this.slots.splice(index, 1);\n\n // Re-map indices in all remaining tasks:\n // 1) Fix specificWorkerIndex in every remaining slot.queue\n for (let i = 0; i < this.slots.length; i++) {\n const s = this.slots[i];\n for (const t of s.queue) {\n if (typeof t.specificWorkerIndex === 'number') {\n if (t.specificWorkerIndex === index) {\n // This should not happen because we just removed and flushed its queue,\n // but guard anyway.\n t.reject(new Error(`Worker[${index}] no longer exists`));\n } else if (t.specificWorkerIndex > index) {\n t.specificWorkerIndex -= 1;\n }\n }\n }\n }\n // 2) Fix triedWorkers sets in globalQueue\n for (const t of this.globalQueue) {\n if (t.triedWorkers.has(index)) t.triedWorkers.delete(index);\n const next = new Set<number>();\n for (const w of t.triedWorkers) {\n next.add(w > index ? w - 1 : w);\n }\n t.triedWorkers = next;\n }\n\n // Trigger scheduling for the remaining system\n this.drain();\n\n return completion;\n }\n\n snapshot(): WorkerSnapshot<F>[] {\n const now = Date.now();\n\n return this.slots.map((slot, i) => {\n switch (slot.kind) {\n case 'active': {\n const s = slot.state;\n return {\n index: i,\n status: 'active' as const,\n fn: slot.fn,\n running: s.running,\n failCount: s.failCount,\n totalRuns: s.totalRuns,\n blockedMs: Math.max(0, s.nextAvailableAt - now),\n specificQueue: slot.queue.length,\n };\n }\n\n case 'pending':\n return {\n index: i,\n status: 'pending' as const,\n promise: slot.promise,\n specificQueue: slot.queue.length,\n };\n\n case 'rejected':\n return {\n index: i,\n status: 'rejected' as const,\n error: String(slot.error ?? 'unknown error'),\n specificQueue: slot.queue.length,\n };\n }\n });\n }\n\n get pending(): number {\n return this.globalQueue.length;\n }\n\n // ---------------- scheduling ----------------\n\n private drain() {\n if (this.drainScheduled) return;\n this.drainScheduled = true;\n queueMicrotask(() => {\n this.drainScheduled = false;\n this._drainLoop();\n });\n }\n\n private _drainLoop() {\n // If no active workers and still initializing, wait; if all inited and none active, constructor already rejects all.\n if (!this.hasAnyActive()) {\n if (this.pendingInits > 0) return;\n return;\n }\n\n // First: flush rejected workers' specific queues (macro-task rejection)\n for (let i = 0; i < this.slots.length; i++) {\n const slot = this.slots[i];\n if (slot.kind === 'rejected' && slot.queue.length > 0) {\n const q = slot.queue.splice(0);\n const err = new Error(\n `Worker[${i}] failed to initialize: ${String(slot.error ?? 'unknown error')}`,\n );\n setTimeout(() => {\n for (const t of q) t.reject(err);\n }, 0);\n }\n }\n\n let progressed = true;\n while (progressed) {\n progressed = false;\n\n // 1) Run specific queues for active workers (ignore backoff)\n for (let i = 0; i < this.slots.length; i++) {\n const slot = this.slots[i];\n if (slot.kind !== 'active') continue;\n const st = slot.state;\n if (!st.running && slot.queue.length > 0) {\n const task = slot.queue.shift()!;\n this.startTaskOnActiveSlot(i, slot, task, /*fromSpecific*/ true);\n progressed = true;\n }\n }\n\n // 2) Run global queue (choose eligible active with least totalRuns)\n if (this.globalQueue.length > 0) {\n const idx = this.pickBestActiveForGlobal();\n if (idx !== -1) {\n const slot = this.slots[idx] as ActiveSlot<F>;\n const task = this.globalQueue.shift()!;\n this.startTaskOnActiveSlot(idx, slot, task, /*fromSpecific*/ false);\n progressed = true;\n }\n }\n }\n }\n\n private hasAnyActive() {\n return this.slots.some((s) => s.kind === 'active');\n }\n\n private rejectAllQueued(err: any) {\n while (this.globalQueue.length) this.globalQueue.shift()!.reject(err);\n for (const slot of this.slots) {\n while (slot.queue.length) slot.queue.shift()!.reject(err);\n }\n }\n\n private isEligibleActive(i: number, now: number) {\n const slot = this.slots[i];\n if (!slot || slot.kind !== 'active') return false;\n const s = slot.state;\n return !s.running && now >= s.nextAvailableAt;\n // note: specific queues ignore backoff; this is only for global picks.\n }\n\n private pickBestActiveForGlobal(): number {\n const now = Date.now();\n const task = this.globalQueue[0];\n\n // Prefer actives not tried yet\n let best = -1,\n bestRuns = Infinity;\n for (let i = 0; i < this.slots.length; i++) {\n if (!this.isEligibleActive(i, now)) continue;\n if (task?.triedWorkers.has(i)) continue;\n const slot = this.slots[i] as ActiveSlot<F>;\n if (slot.state.totalRuns < bestRuns) {\n bestRuns = slot.state.totalRuns;\n best = i;\n }\n }\n if (best !== -1) return best;\n\n // Allow already-tried actives\n best = -1;\n bestRuns = Infinity;\n for (let i = 0; i < this.slots.length; i++) {\n if (!this.isEligibleActive(i, now)) continue;\n const slot = this.slots[i] as ActiveSlot<F>;\n if (slot.state.totalRuns < bestRuns) {\n bestRuns = slot.state.totalRuns;\n best = i;\n }\n }\n return best;\n }\n\n private startTaskOnActiveSlot(\n index: number,\n slot: ActiveSlot<F>,\n task: Task<F>,\n fromSpecific: boolean,\n ) {\n const st = slot.state;\n st.running = true;\n st.totalRuns += 1;\n\n const finalize = () => {\n st.running = false;\n // If someone is waiting for this worker to finish (removeWorker), resolve them when idle.\n if (\n slot.removalWaiters.length > 0 &&\n !st.running &&\n slot.queue.length === 0\n ) {\n const list = slot.removalWaiters.splice(0);\n for (const w of list) w();\n }\n this.drain();\n };\n\n (async () => {\n try {\n const result = await slot.fn(...task.args);\n st.failCount = Math.max(0, st.failCount - 1);\n task.resolve(result as Awaited<ReturnType<F>>);\n } catch (err) {\n task.lastError = err;\n st.failCount += 1;\n st.nextAvailableAt =\n Date.now() + this.backoffBaseMs * Math.pow(2, st.failCount);\n\n if (fromSpecific) {\n task.attempts += 1;\n if (task.attempts >= this.maxAttempts) {\n task.reject(task.lastError);\n } else {\n // retry on the same worker (ignore backoff)\n slot.queue.push(task);\n }\n } else {\n task.attempts += 1;\n task.triedWorkers.add(index);\n const activeCount = this.slots.filter(\n (s) => s.kind === 'active',\n ).length;\n const allActiveTriedOnce = task.triedWorkers.size >= activeCount;\n const attemptsLimitReached = task.attempts >= this.maxAttempts;\n\n if (allActiveTriedOnce || attemptsLimitReached) {\n task.reject(task.lastError);\n } else {\n this.globalQueue.push(task);\n }\n }\n } finally {\n finalize();\n }\n })();\n }\n}\n"],
5
- "mappings": "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",
3
+ "sources": ["../src/workflow.ts", "../src/dual-object.ts", "../src/workflow-dispatcher.ts", "../src/round-robin.ts"],
4
+ "sourcesContent": ["// ========== \u7C7B\u578B\u5DE5\u5177 ==========\ntype AwaitedLike<T> = T extends Promise<infer R> ? R : T;\ntype AnyFn = (...args: any[]) => any;\n\ntype Chain<T> = Promise<AwaitedLike<T>> &\n (T extends AnyFn\n ? (...a: Parameters<T>) => Chain<AwaitedLike<ReturnType<T>>>\n : {}) & {\n [K in keyof T]: T[K] extends (...a: infer A) => infer R\n ? (...a: A) => Chain<AwaitedLike<R>>\n : Chain<AwaitedLike<T[K]>>;\n };\n\n// ========== \u6838\u5FC3\uFF1A\u4E0D\u53EF\u53D8\u8282\u70B9 ==========\nclass Node {\n private memo?: Promise<any>;\n constructor(\n private readonly source: any, // \u53EA\u6709\u6839\u8282\u70B9\u6709\u610F\u4E49\uFF1B\u5B50\u8282\u70B9\u53EF\u590D\u7528\u6839\u7684 source\n private readonly parent: Node | null, // \u524D\u7F00\n private readonly op: ((x: any) => any) | null, // \u4ECE parent \u7ED3\u679C\u5230\u672C\u8282\u70B9\u7ED3\u679C\u7684\u53D8\u6362\n ) {}\n\n run(): Promise<any> {\n if (!this.memo) {\n this.memo = (async () => {\n if (!this.parent) {\n // \u6839\uFF1A\u628A source \u89E3\u4E00\u6B21\u5373\u53EF\n return await this.source;\n }\n // \u5148\u62FF\u5230\u7236\u8282\u70B9\u7ED3\u679C\uFF08\u4F1A\u8BB0\u5FC6\u5316\uFF09\n const base = await this.parent.run();\n // \u5E94\u7528\u672C\u8282\u70B9\u7684\u53D8\u6362\uFF08\u5141\u8BB8\u8FD4\u56DE\u540C\u6B65\u6216\u5F02\u6B65\uFF09\n return this.op ? this.op(base) : base;\n })();\n }\n return this.memo;\n }\n\n // \u5DE5\u5382\uFF1A\u884D\u751F\u5B50\u8282\u70B9\uFF08\u5206\u53C9 = \u590D\u7528\u540C\u4E00\u4E2A parent\uFF09\n child(op: (x: any) => any): Node {\n return new Node(this.source, this, op);\n }\n\n // \u62FF\u5230\u201C\u76F8\u540C\u8282\u70B9\u201D\u7684\u53E5\u67C4\uFF08\u663E\u5F0F fork\uFF09\n fork(): Node {\n return new Node(this.source, this.parent, this.op);\n }\n}\n\nexport const WF_NODE = Symbol('@@workflow/node');\n\nfunction isWorkflowChain(x: any): x is Chain<any> {\n return !!x && typeof x === 'function' && x[WF_NODE] instanceof Node;\n}\n\n// ========== \u5BF9\u5916 API\uFF1Aworkflow ==========\nexport function workflow<T>(source: T | Promise<T>): Chain<T> {\n if (isWorkflowChain(source)) {\n return source as unknown as Chain<T>;\n }\n const root = new Node(source, null, null);\n return makeProxy<T>(root) as any;\n}\n\n// ========== \u4EE3\u7406\u5C42\uFF1A\u628A Node \u66B4\u9732\u6210\u94FE\u5F0F API ==========\nfunction makeProxy<T>(node: Node): Chain<T> {\n const runOnce = () => node.run(); // \u8BB0\u5FC6\u5316\u5728 Node \u5185\u90E8\n\n const rootHandler: ProxyHandler<any> = {\n get(_t, prop) {\n if (prop === WF_NODE) return node;\n // \u7ED3\u675F\u4FE1\u53F7\uFF1A\u6240\u6709 then/catch/finally \u590D\u7528\u540C\u4E00\u4E2A Promise\n if (prop === 'then')\n return (res: any, rej?: any) => runOnce().then(res, rej);\n if (prop === 'catch') return (rej: any) => runOnce().catch(rej);\n if (prop === 'finally') return (fin: any) => runOnce().finally(fin);\n\n // \u8BBF\u95EE\u4E00\u4E2A\u5C5E\u6027\uFF1A\u751F\u6210\u4E00\u4E2A\u201CGet\u201D\u5B50\u8282\u70B9\uFF0C\u4F46\u4E0D\u6267\u884C\n return linkProxy(prop);\n },\n // \u652F\u6301\u5BF9\u201C\u5F53\u524D\u503C\u201D\u76F4\u63A5\u4E8C\u6B21\u8C03\u7528\uFF1A foo()()\n apply(_t, _this, argArray) {\n const child = node.child((cur: any) => {\n if (typeof cur !== 'function')\n throw new TypeError('Current value is not callable');\n return cur(...argArray);\n });\n return makeProxy<any>(child);\n },\n };\n\n const linkProxy = (prop: PropertyKey) =>\n new Proxy(function () {}, {\n // \u628A \u201C.foo(\u2026args)\u201D \u8BB0\u5F55\u4E3A Call\n apply(_t, _this, argArray) {\n const child = node.child((cur: any) => {\n const fn = (cur as any)[prop];\n if (typeof fn !== 'function') {\n throw new TypeError(`${String(prop)} is not a function`);\n }\n return fn.apply(cur, argArray);\n });\n return makeProxy<any>(child);\n },\n // \u628A \u201C.bar\u201D \u8BB0\u5F55\u4E3A Get\uFF1B\u7EE7\u7EED\u6DF1\u5165\u65F6\u5728\u8FD9\u4E2A Get \u7684\u7ED3\u679C\u4E0A\u518D\u5904\u7406\n get(_t, next) {\n if (next === WF_NODE) return node;\n if (next === 'then')\n return (r: any, j?: any) =>\n node\n .child((cur: any) => (cur as any)[prop])\n .run()\n .then(r, j);\n if (next === 'catch')\n return (rej: any) =>\n node\n .child((cur: any) => (cur as any)[prop])\n .run()\n .catch(rej);\n if (next === 'finally')\n return (fin: any) =>\n node\n .child((cur: any) => (cur as any)[prop])\n .run()\n .finally(fin);\n\n const child = node.child((cur: any) => (cur as any)[prop]);\n return (makeProxy as any)(child)[next];\n },\n });\n\n return new Proxy(function () {}, rootHandler) as any;\n}\n", "// dual-unified.ts\nexport type Dual<T> = T & PromiseLike<T>;\n\ntype ThenKey = 'then' | 'catch' | 'finally';\nconst isThenKey = (k: PropertyKey): k is ThenKey =>\n k === 'then' || k === 'catch' || k === 'finally';\n\ntype State = 'undecided' | 'pending' | 'fulfilled' | 'rejected';\n\n/** \u4EC5\u5141\u8BB8\u586B\u5165 \u201C\u8FD4\u56DE Promise \u7684\u65B9\u6CD5\u540D\u201D */\nexport type AsyncMethodKeys<T> = {\n [K in keyof T]-?: T[K] extends (...args: any[]) => Promise<any> ? K : never;\n}[keyof T];\n\nexport interface DualizeOptions<T> {\n /** \u8FD9\u4E9B\u65B9\u6CD5\u5728 undecided/pending \u65F6\u4F1A\u8FD4\u56DE\u4E00\u4E2A\u5EF6\u8FDF\u6267\u884C\u51FD\u6570\uFF0C\u7B49\u5F85\u5BF9\u8C61 Promise \u5B8C\u6210\u540E\u518D\u8C03\u7528 */\n asyncMethods?: readonly AsyncMethodKeys<T>[];\n}\n\nexport function dualizeAny<T>(\n sync: () => T, // \u540C\u6B65\u6784\u9020\uFF1B\u82E5\u629B\u9519\u5219\u89C6\u4E3A rejected\n asyncFn: () => Promise<T>, // \u5F02\u6B65\u6784\u9020\n options?: DualizeOptions<T>,\n): Dual<T> {\n let state: State = 'undecided';\n\n let value!: T; // fulfilled \u65F6\u7684\u503C\uFF08\u542B\u6765\u81EA sync \u6216 async\uFF09\n let reason: any; // rejected \u7684\u9519\u8BEF\n let p!: Promise<T>; // \u7F13\u5B58 Promise\uFF08resolved/rejected/\u8FDB\u884C\u4E2D\uFF09\n\n const asyncMethodSet = new Set<PropertyKey>(\n (options?.asyncMethods ?? []) as readonly PropertyKey[],\n );\n\n const startAsync = () => {\n if (!p || state === 'undecided') {\n state = 'pending';\n p = Promise.resolve()\n .then(asyncFn)\n .then(\n (v) => {\n value = v;\n state = 'fulfilled';\n return v;\n },\n (e) => {\n reason = e;\n state = 'rejected';\n throw e;\n },\n );\n }\n return p;\n };\n\n const ensureSync = () => {\n if (state === 'undecided') {\n try {\n value = sync();\n state = 'fulfilled';\n } catch (e) {\n reason = e;\n state = 'rejected';\n }\n }\n };\n\n /** \u5728\u201C\u5BF9\u8C61\u53EF\u7528\u201D\u540E\u8C03\u7528\u67D0\u4E2A\u5F02\u6B65\u65B9\u6CD5\uFF08\u7531 asyncMethods \u58F0\u660E\uFF09 */\n const makeDeferredAsyncMethod =\n (prop: PropertyKey) =>\n (...args: any[]) =>\n startAsync().then((obj) => {\n const fn = (obj as any)[prop];\n return fn.apply(obj, args);\n });\n\n // \u4ECE\u67D0\u4E2A\u503C\u4E0A\u53D6\u5C5E\u6027\uFF08\u539F\u59CB\u503C\u4F1A\u88C5\u7BB1\uFF09\uFF0C\u5E76\u7ED1\u5B9A this\n const getFrom = (v: unknown, prop: PropertyKey) => {\n if (prop === Symbol.toPrimitive) {\n return (hint: 'default' | 'number' | 'string') => {\n const x: any = v;\n if (hint === 'number') return Number(x);\n if (hint === 'string') return String(x);\n if (typeof x === 'string') return x;\n const n = Number(x);\n return Number.isNaN(n) ? String(x) : n;\n };\n }\n if (prop === 'valueOf') return () => v as any;\n if (prop === 'toString') return () => String(v);\n\n const boxed: any =\n v !== null && (typeof v === 'object' || typeof v === 'function')\n ? v\n : Object(v as any);\n const out = boxed[prop];\n return typeof out === 'function' ? out.bind(boxed) : out;\n };\n\n const proxy = new Proxy(Object.create(null) as any, {\n get(_t, prop) {\n // then/catch/finally\uFF1A\u8D70 Promise \u901A\u9053\n if (isThenKey(prop)) {\n if (state === 'undecided') {\n startAsync();\n } else if (state === 'fulfilled') {\n // \u82E5\u5DF2 fulfilled\uFF08\u6765\u81EA sync \u6216 async\uFF09\uFF0C\u8865\u4E00\u4E2A\u5DF2\u5B8C\u6210\u7684 Promise\n p ||= Promise.resolve(value);\n } else if (state === 'rejected') {\n p ||= Promise.reject(reason);\n } else {\n // pending\uFF1A\u5DF2\u6709 p\n startAsync();\n }\n const anyP: any = p;\n const m = anyP[prop];\n return typeof m === 'function' ? m.bind(anyP) : m;\n }\n\n // \u58F0\u660E\u4E3A\u5F02\u6B65\u65B9\u6CD5\u7684\u952E\uFF1A\u5728 undecided/pending \u65F6\u8FD4\u56DE\u201C\u5EF6\u8FDF\u51FD\u6570\u201D\n if (asyncMethodSet.has(prop)) {\n if (state === 'undecided' || state === 'pending') {\n startAsync();\n return makeDeferredAsyncMethod(prop);\n }\n if (state === 'fulfilled') {\n return getFrom(value, prop); // \u540C\u6B65\u53EF\u76F4\u63A5\u53D6\u5230\u65B9\u6CD5\uFF08\u5176\u672C\u8EAB\u8FD4\u56DE Promise\uFF09\n }\n if (state === 'rejected') {\n // \u8BBF\u95EE\u5373\u629B\uFF1B\u4E5F\u53EF\u4EE5\u9009\u62E9\u8FD4\u56DE () => Promise.reject(reason)\n throw reason;\n }\n }\n\n // \u5176\u5B83\u5C5E\u6027\u8BBF\u95EE\uFF1A\u9075\u5FAA\u72B6\u6001\u673A\n switch (state) {\n case 'undecided': {\n ensureSync();\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (state === 'fulfilled') return getFrom(value, prop);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (state === 'rejected') throw reason;\n // \u7406\u8BBA\u4E0A\u4E0D\u4F1A\u5230\u8FD9\u91CC\n throw new TypeError('Invalid state transition');\n }\n case 'pending': {\n // \u975E asyncMethods \u7684\u5C5E\u6027\u5728 pending \u65F6\u4E0D\u53EF\u540C\u6B65\u8BFB\u53D6\n throw new TypeError('Value is not ready yet. Please await it first.');\n }\n case 'fulfilled': {\n return getFrom(value, prop);\n }\n case 'rejected': {\n throw reason;\n }\n }\n },\n\n has(_t, key) {\n if (state === 'undecided') {\n ensureSync();\n }\n if (state === 'fulfilled') return key in Object(value as any);\n return false; // pending/rejected\uFF1A\u4FDD\u5B88\u5904\u7406\n },\n\n ownKeys() {\n if (state === 'undecided') ensureSync();\n if (state === 'fulfilled') return Reflect.ownKeys(Object(value as any));\n return [];\n },\n\n getOwnPropertyDescriptor(_t, key) {\n if (state === 'undecided') ensureSync();\n if (state === 'fulfilled')\n return Object.getOwnPropertyDescriptor(Object(value as any), key);\n return undefined;\n },\n });\n\n return proxy as Dual<T>;\n}\n", "export interface DispatcherOptions {\n /** Max attempts per task. Default 3. */\n maxAttempts?: number;\n /** Backoff base in ms. backoff = base * 2^failCount. Default 1000. */\n backoffBaseMs?: number;\n}\n\n// Internal task record\ntype Task<F extends (...args: any[]) => Promise<any>> = {\n args: Parameters<F>;\n resolve: (v: Awaited<ReturnType<F>>) => void;\n reject: (e: any) => void;\n attempts: number;\n lastError?: any;\n triedWorkers: Set<number>; // for global dispatch\n specificWorkerIndex?: number; // for dispatchSpecific only\n};\n\ntype WorkerState = {\n running: boolean;\n failCount: number;\n nextAvailableAt: number;\n totalRuns: number;\n};\n\ntype RemovalWaiter = () => void;\n\ntype ActiveSlot<F extends (...args: any[]) => Promise<any>> = {\n kind: 'active';\n fn: F;\n state: WorkerState;\n queue: Task<F>[];\n removalWaiters: RemovalWaiter[];\n removed?: boolean; // marker when removed while running; retained for completion callback\n};\n\ntype PendingSlot<F extends (...args: any[]) => Promise<any>> = {\n kind: 'pending';\n promise: Promise<F>;\n queue: Task<F>[];\n removalWaiters: RemovalWaiter[];\n error?: any;\n removed?: boolean; // if removed before resolved\n};\n\ntype RejectedSlot<F extends (...args: any[]) => Promise<any>> = {\n kind: 'rejected';\n error: any;\n queue: Task<F>[];\n removalWaiters: RemovalWaiter[];\n removed?: boolean;\n};\n\ntype Slot<F extends (...args: any[]) => Promise<any>> =\n | ActiveSlot<F>\n | PendingSlot<F>\n | RejectedSlot<F>;\n\nexport type WorkerSnapshot<F extends (...args: any[]) => Promise<any>> =\n | {\n index: number;\n status: 'active';\n fn: F;\n running: boolean;\n failCount: number;\n totalRuns: number;\n blockedMs: number;\n specificQueue: number;\n }\n | {\n index: number;\n status: 'pending';\n promise: Promise<F>;\n specificQueue: number;\n }\n | {\n index: number;\n status: 'rejected';\n error: string;\n specificQueue: number;\n };\n\nexport class WorkflowDispatcher<F extends (...args: any[]) => Promise<any>> {\n private readonly maxAttempts: number;\n private readonly backoffBaseMs: number;\n\n private readonly slots: Slot<F>[] = [];\n private readonly globalQueue: Task<F>[] = [];\n\n private pendingInits = 0;\n private everActivated = false;\n private drainScheduled = false;\n\n constructor(\n workersOrPromises: Array<F | Promise<F>>,\n options: DispatcherOptions = {},\n ) {\n // if (!workersOrPromises?.length) throw new Error('workers cannot be empty');\n\n this.maxAttempts = options.maxAttempts ?? 3;\n this.backoffBaseMs = options.backoffBaseMs ?? 1000;\n\n for (let i = 0; i < workersOrPromises.length; i++) {\n const w = workersOrPromises[i];\n if (typeof w === 'function') {\n const slot: ActiveSlot<F> = {\n kind: 'active',\n fn: w,\n state: {\n running: false,\n failCount: 0,\n nextAvailableAt: 0,\n totalRuns: 0,\n },\n queue: [],\n removalWaiters: [],\n };\n this.slots.push(slot);\n this.everActivated = true;\n } else {\n // Create a stable slot object and mutate it in-place on resolve/reject.\n this.pendingInits++;\n const slot: PendingSlot<F> = {\n kind: 'pending',\n promise: Promise.resolve(w),\n queue: [],\n removalWaiters: [],\n };\n this.slots.push(slot);\n\n slot.promise\n .then((fn) => {\n if (slot.removed) return; // was removed; ignore resolution\n // mutate in-place to active\n (slot as any).kind = 'active';\n (slot as any).fn = fn;\n (slot as any).state = {\n running: false,\n failCount: 0,\n nextAvailableAt: 0,\n totalRuns: 0,\n };\n this.everActivated = true;\n // keep queue & removalWaiters arrays as-is\n })\n .catch((err) => {\n if (slot.removed) return; // was removed; ignore\n // mutate in-place to rejected (keep queue/waiters)\n (slot as any).kind = 'rejected';\n (slot as any).error = err;\n })\n .finally(() => {\n this.pendingInits--;\n this.drain();\n if (this.pendingInits === 0 && !this.hasAnyActive()) {\n const err = new Error(\n 'No workers available (all failed to initialize).',\n );\n setTimeout(() => this.rejectAllQueued(err), 0);\n }\n });\n }\n }\n\n if (this.everActivated) this.drain();\n }\n\n /** Dispatch: choose eligible active with least totalRuns; retry across workers on failure. */\n dispatch(...args: Parameters<F>): Promise<Awaited<ReturnType<F>>> {\n return new Promise((resolve, reject) => {\n const task: Task<F> = {\n args,\n resolve,\n reject,\n attempts: 0,\n triedWorkers: new Set(),\n };\n this.globalQueue.push(task);\n this.drain();\n });\n }\n\n /** Dispatch to a specific worker (ignore backoff), wait until it is free; retry on the same worker. */\n dispatchSpecific(\n index: number,\n ...args: Parameters<F>\n ): Promise<Awaited<ReturnType<F>>> {\n if (index < 0 || index >= this.slots.length) {\n return Promise.reject(new Error(`worker index out of range: ${index}`));\n }\n return new Promise((resolve, reject) => {\n const task: Task<F> = {\n args,\n resolve,\n reject,\n attempts: 0,\n triedWorkers: new Set(),\n specificWorkerIndex: index,\n };\n const slot = this.slots[index];\n slot.queue.push(task);\n this.drain();\n });\n }\n\n /** Replace a worker at index with a new active worker function. */\n public replaceWorker(index: number, fn: F): void {\n if (index < 0 || index >= this.slots.length) {\n throw new Error(`worker index out of range: ${index}`);\n }\n const prevHadActive = this.hasAnyActive();\n const slot = this.slots[index];\n\n // Preserve queue & removal waiters; reset failure/backoff; keep totalRuns to avoid skew.\n const preservedQueue = slot.queue;\n const preservedWaiters = slot.removalWaiters ?? [];\n\n const next: ActiveSlot<F> = {\n kind: 'active',\n fn,\n state: {\n running: false,\n failCount: 0,\n nextAvailableAt: 0,\n totalRuns: (slot as any).state?.totalRuns ?? 0,\n },\n queue: preservedQueue,\n removalWaiters: preservedWaiters,\n };\n\n // Mutate in-place if possible (keeps references stable), else replace array entry.\n Object.assign(slot as any, next);\n (slot as any).kind = 'active';\n (slot as any).fn = fn;\n (slot as any).state.failCount = 0;\n (slot as any).state.nextAvailableAt = 0;\n\n this.everActivated = true;\n if (!prevHadActive && this.hasAnyActive()) {\n this.drain();\n } else {\n this.drain();\n }\n }\n\n /** Add a new active worker at the tail; return its index. */\n public addWorker(fn: F): number {\n const slot: ActiveSlot<F> = {\n kind: 'active',\n fn,\n state: { running: false, failCount: 0, nextAvailableAt: 0, totalRuns: 0 },\n queue: [],\n removalWaiters: [],\n };\n const index = this.slots.length;\n this.slots.push(slot);\n this.everActivated = true;\n this.drain();\n return index;\n }\n\n /**\n * Remove a worker completely (splice). It becomes unavailable immediately.\n * Returns a Promise that resolves when its last running task (if any) finishes.\n */\n public removeWorker(index: number): Promise<void> {\n if (index < 0 || index >= this.slots.length) {\n return Promise.reject(new Error(`worker index out of range: ${index}`));\n }\n\n const slot = this.slots[index];\n\n // Reject all queued specific tasks on this worker (macro-task to avoid unhandled)\n const queued = slot.queue.splice(0);\n const removalErr = new Error(`Worker[${index}] removed`);\n setTimeout(() => {\n for (const t of queued) t.reject(removalErr);\n }, 0);\n\n // Decide completion promise:\n let completion: Promise<void>;\n const isRunning = slot.kind === 'active' && slot.state.running;\n if (!isRunning) {\n completion = Promise.resolve();\n } else {\n completion = new Promise<void>((resolve) => {\n slot.removalWaiters.push(resolve);\n });\n }\n\n // Mark as removed (so any pending init resolution is ignored)\n (slot as any).removed = true;\n\n // Physically remove the slot\n this.slots.splice(index, 1);\n\n // Re-map indices in all remaining tasks:\n // 1) Fix specificWorkerIndex in every remaining slot.queue\n for (let i = 0; i < this.slots.length; i++) {\n const s = this.slots[i];\n for (const t of s.queue) {\n if (typeof t.specificWorkerIndex === 'number') {\n if (t.specificWorkerIndex === index) {\n // This should not happen because we just removed and flushed its queue,\n // but guard anyway.\n t.reject(new Error(`Worker[${index}] no longer exists`));\n } else if (t.specificWorkerIndex > index) {\n t.specificWorkerIndex -= 1;\n }\n }\n }\n }\n // 2) Fix triedWorkers sets in globalQueue\n for (const t of this.globalQueue) {\n if (t.triedWorkers.has(index)) t.triedWorkers.delete(index);\n const next = new Set<number>();\n for (const w of t.triedWorkers) {\n next.add(w > index ? w - 1 : w);\n }\n t.triedWorkers = next;\n }\n\n // Trigger scheduling for the remaining system\n this.drain();\n\n return completion;\n }\n\n snapshot(): WorkerSnapshot<F>[] {\n const now = Date.now();\n\n return this.slots.map((slot, i) => {\n switch (slot.kind) {\n case 'active': {\n const s = slot.state;\n return {\n index: i,\n status: 'active' as const,\n fn: slot.fn,\n running: s.running,\n failCount: s.failCount,\n totalRuns: s.totalRuns,\n blockedMs: Math.max(0, s.nextAvailableAt - now),\n specificQueue: slot.queue.length,\n };\n }\n\n case 'pending':\n return {\n index: i,\n status: 'pending' as const,\n promise: slot.promise,\n specificQueue: slot.queue.length,\n };\n\n case 'rejected':\n return {\n index: i,\n status: 'rejected' as const,\n error: String(slot.error ?? 'unknown error'),\n specificQueue: slot.queue.length,\n };\n }\n });\n }\n\n get pending(): number {\n return this.globalQueue.length;\n }\n\n // ---------------- scheduling ----------------\n\n private drain() {\n if (this.drainScheduled) return;\n this.drainScheduled = true;\n queueMicrotask(() => {\n this.drainScheduled = false;\n this._drainLoop();\n });\n }\n\n private _drainLoop() {\n // If no active workers and still initializing, wait; if all inited and none active, constructor already rejects all.\n if (!this.hasAnyActive()) {\n if (this.pendingInits > 0) return;\n return;\n }\n\n // First: flush rejected workers' specific queues (macro-task rejection)\n for (let i = 0; i < this.slots.length; i++) {\n const slot = this.slots[i];\n if (slot.kind === 'rejected' && slot.queue.length > 0) {\n const q = slot.queue.splice(0);\n const err = new Error(\n `Worker[${i}] failed to initialize: ${String(slot.error ?? 'unknown error')}`,\n );\n setTimeout(() => {\n for (const t of q) t.reject(err);\n }, 0);\n }\n }\n\n let progressed = true;\n while (progressed) {\n progressed = false;\n\n // 1) Run specific queues for active workers (ignore backoff)\n for (let i = 0; i < this.slots.length; i++) {\n const slot = this.slots[i];\n if (slot.kind !== 'active') continue;\n const st = slot.state;\n if (!st.running && slot.queue.length > 0) {\n const task = slot.queue.shift()!;\n this.startTaskOnActiveSlot(i, slot, task, /*fromSpecific*/ true);\n progressed = true;\n }\n }\n\n // 2) Run global queue (choose eligible active with least totalRuns)\n if (this.globalQueue.length > 0) {\n const idx = this.pickBestActiveForGlobal();\n if (idx !== -1) {\n const slot = this.slots[idx] as ActiveSlot<F>;\n const task = this.globalQueue.shift()!;\n this.startTaskOnActiveSlot(idx, slot, task, /*fromSpecific*/ false);\n progressed = true;\n }\n }\n }\n }\n\n private hasAnyActive() {\n return this.slots.some((s) => s.kind === 'active');\n }\n\n private rejectAllQueued(err: any) {\n while (this.globalQueue.length) this.globalQueue.shift()!.reject(err);\n for (const slot of this.slots) {\n while (slot.queue.length) slot.queue.shift()!.reject(err);\n }\n }\n\n private isEligibleActive(i: number, now: number) {\n const slot = this.slots[i];\n if (!slot || slot.kind !== 'active') return false;\n const s = slot.state;\n return !s.running && now >= s.nextAvailableAt;\n // note: specific queues ignore backoff; this is only for global picks.\n }\n\n private pickBestActiveForGlobal(): number {\n const now = Date.now();\n const task = this.globalQueue[0];\n\n // Prefer actives not tried yet\n let best = -1,\n bestRuns = Infinity;\n for (let i = 0; i < this.slots.length; i++) {\n if (!this.isEligibleActive(i, now)) continue;\n if (task?.triedWorkers.has(i)) continue;\n const slot = this.slots[i] as ActiveSlot<F>;\n if (slot.state.totalRuns < bestRuns) {\n bestRuns = slot.state.totalRuns;\n best = i;\n }\n }\n if (best !== -1) return best;\n\n // Allow already-tried actives\n best = -1;\n bestRuns = Infinity;\n for (let i = 0; i < this.slots.length; i++) {\n if (!this.isEligibleActive(i, now)) continue;\n const slot = this.slots[i] as ActiveSlot<F>;\n if (slot.state.totalRuns < bestRuns) {\n bestRuns = slot.state.totalRuns;\n best = i;\n }\n }\n return best;\n }\n\n private startTaskOnActiveSlot(\n index: number,\n slot: ActiveSlot<F>,\n task: Task<F>,\n fromSpecific: boolean,\n ) {\n const st = slot.state;\n st.running = true;\n st.totalRuns += 1;\n\n const finalize = () => {\n st.running = false;\n // If someone is waiting for this worker to finish (removeWorker), resolve them when idle.\n if (\n slot.removalWaiters.length > 0 &&\n !st.running &&\n slot.queue.length === 0\n ) {\n const list = slot.removalWaiters.splice(0);\n for (const w of list) w();\n }\n this.drain();\n };\n\n (async () => {\n try {\n const result = await slot.fn(...task.args);\n st.failCount = Math.max(0, st.failCount - 1);\n task.resolve(result as Awaited<ReturnType<F>>);\n } catch (err) {\n task.lastError = err;\n st.failCount += 1;\n st.nextAvailableAt =\n Date.now() + this.backoffBaseMs * Math.pow(2, st.failCount);\n\n if (fromSpecific) {\n task.attempts += 1;\n if (task.attempts >= this.maxAttempts) {\n task.reject(task.lastError);\n } else {\n // retry on the same worker (ignore backoff)\n slot.queue.push(task);\n }\n } else {\n task.attempts += 1;\n task.triedWorkers.add(index);\n const activeCount = this.slots.filter(\n (s) => s.kind === 'active',\n ).length;\n const allActiveTriedOnce = task.triedWorkers.size >= activeCount;\n const attemptsLimitReached = task.attempts >= this.maxAttempts;\n\n if (allActiveTriedOnce || attemptsLimitReached) {\n task.reject(task.lastError);\n } else {\n this.globalQueue.push(task);\n }\n }\n } finally {\n finalize();\n }\n })();\n }\n}\n", "export class RoundRobin<T> {\n private index = 0;\n\n constructor(public items: T[]) {\n if (items.length === 0) {\n throw new Error('RoundRobin requires at least one item');\n }\n }\n\n next(): T {\n const nextIndex = this.index % this.items.length;\n this.index = (this.index + 1) % this.items.length;\n return this.items[nextIndex];\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,6 @@
1
+ export declare class RoundRobin<T> {
2
+ items: T[];
3
+ private index;
4
+ constructor(items: T[]);
5
+ next(): T;
6
+ }
package/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './src/workflow';
2
2
  export * from './src/dual-object';
3
3
  export * from './src/workflow-dispatcher';
4
+ export * from './src/round-robin';
package/package.json CHANGED
@@ -1,18 +1,26 @@
1
1
  {
2
2
  "name": "nfkit",
3
3
  "description": "Common kits",
4
- "version": "1.0.4",
4
+ "version": "1.0.6",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.cjs",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
8
15
  "scripts": {
9
16
  "lint": "eslint --fix .",
10
- "compile:cjs": "esbuild index.ts --outfile=dist/index.cjs --bundle --sourcemap --platform=node --target=es2019 --external:js-base64",
11
- "compile:esm": "esbuild index.ts --outfile=dist/index.mjs --bundle --sourcemap --platform=neutral --target=esnext --external:js-base64",
12
- "compile:types": "tsc --emitDeclarationOnly --declaration",
13
- "build": "rimraf dist && npm run compile:cjs && npm run compile:esm && npm run compile:types",
17
+ "build": "node build.js",
18
+ "build:cjs": "node build.js cjs",
19
+ "build:esm": "node build.js esm",
20
+ "build:types": "node build.js types",
21
+ "clean": "node build.js clean",
14
22
  "test": "jest --passWithNoTests",
15
- "start": "node dist/index.js"
23
+ "start": "node dist/index.cjs"
16
24
  },
17
25
  "repository": {
18
26
  "type": "git",
@@ -54,7 +62,6 @@
54
62
  "eslint-plugin-prettier": "^5.5.4",
55
63
  "jest": "^30.2.0",
56
64
  "prettier": "^3.6.2",
57
- "rimraf": "^6.0.1",
58
65
  "ts-jest": "^29.4.5",
59
66
  "typescript": "^5.9.3"
60
67
  }