@weifuwujs/tasks 0.9.0

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.
Files changed (50) hide show
  1. package/README.md +170 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +319 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/index.d.ts +4 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +3 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/postgres.d.ts +3 -0
  11. package/dist/postgres.d.ts.map +1 -0
  12. package/dist/postgres.js +2 -0
  13. package/dist/postgres.js.map +1 -0
  14. package/dist/redis.d.ts +3 -0
  15. package/dist/redis.d.ts.map +1 -0
  16. package/dist/redis.js +2 -0
  17. package/dist/redis.js.map +1 -0
  18. package/dist/sqlite.d.ts +3 -0
  19. package/dist/sqlite.d.ts.map +1 -0
  20. package/dist/sqlite.js +2 -0
  21. package/dist/sqlite.js.map +1 -0
  22. package/dist/stores/memory.d.ts +6 -0
  23. package/dist/stores/memory.d.ts.map +1 -0
  24. package/dist/stores/memory.js +169 -0
  25. package/dist/stores/memory.js.map +1 -0
  26. package/dist/stores/postgres.d.ts +22 -0
  27. package/dist/stores/postgres.d.ts.map +1 -0
  28. package/dist/stores/postgres.js +233 -0
  29. package/dist/stores/postgres.js.map +1 -0
  30. package/dist/stores/redis.d.ts +21 -0
  31. package/dist/stores/redis.d.ts.map +1 -0
  32. package/dist/stores/redis.js +340 -0
  33. package/dist/stores/redis.js.map +1 -0
  34. package/dist/stores/sqlite.d.ts +13 -0
  35. package/dist/stores/sqlite.d.ts.map +1 -0
  36. package/dist/stores/sqlite.js +216 -0
  37. package/dist/stores/sqlite.js.map +1 -0
  38. package/dist/tasks.d.ts +11 -0
  39. package/dist/tasks.d.ts.map +1 -0
  40. package/dist/tasks.js +214 -0
  41. package/dist/tasks.js.map +1 -0
  42. package/dist/testing.d.ts +13 -0
  43. package/dist/testing.d.ts.map +1 -0
  44. package/dist/testing.js +211 -0
  45. package/dist/testing.js.map +1 -0
  46. package/dist/types.d.ts +158 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +3 -0
  49. package/dist/types.js.map +1 -0
  50. package/package.json +61 -0
package/dist/tasks.js ADDED
@@ -0,0 +1,214 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ /**
3
+ * 任务队列:handler 注册在进程内,库里只存 `name + payload`。
4
+ *
5
+ * - 至少一次:claim → 执行 → complete;崩溃后锁过期自动回队重跑;
6
+ * - 未知 handler:不领取(保持 pending)并告警一次;改名遗留用 CLI `tasks prune`;
7
+ * - 周期任务 `every`:首次立即到期,完成后排下一次(宕机后 catch-up);
8
+ * - 注入时钟 + runOnce/drain:测试不 sleep。
9
+ */
10
+ export function createTasks(options) {
11
+ const store = options.store;
12
+ const concurrency = Math.max(1, options.concurrency ?? 1);
13
+ const pollIntervalMs = Math.max(10, options.pollIntervalMs ?? 1000);
14
+ const warnAfterMs = options.warnAfterMs ?? 30_000;
15
+ const visibilityTimeoutMs = options.visibilityTimeoutMs ?? 60_000;
16
+ const baseMs = options.retry?.baseMs ?? 1000;
17
+ const maxMs = options.retry?.maxMs ?? 15 * 60_000;
18
+ const now = options.now ?? (() => new Date());
19
+ const workerId = options.workerId ?? `worker-${process.pid}-${randomUUID().slice(0, 8)}`;
20
+ const logger = options.logger ?? console;
21
+ const handlers = new Map();
22
+ const periodic = new Map();
23
+ const warnedUnknown = new Set();
24
+ const inFlight = new Map();
25
+ let timer = null;
26
+ let stopped = false;
27
+ let ticking = false;
28
+ const backoffMs = (attempt) => Math.min(baseMs * 2 ** Math.max(0, attempt - 1), maxMs);
29
+ async function ensureScheduled(name) {
30
+ const schedule = periodic.get(name);
31
+ if (!schedule)
32
+ return;
33
+ const active = await store.list({
34
+ name,
35
+ statuses: ['pending', 'running'],
36
+ limit: 1,
37
+ });
38
+ if (active.length > 0)
39
+ return;
40
+ await store.enqueue({
41
+ name,
42
+ payload: schedule.payload,
43
+ runAt: now(),
44
+ });
45
+ }
46
+ async function warnUnknown() {
47
+ const names = await store.pendingNames(now());
48
+ for (const name of names) {
49
+ if (handlers.has(name) || warnedUnknown.has(name))
50
+ continue;
51
+ warnedUnknown.add(name);
52
+ logger.warn(`[tasks] 未注册 handler:${name}(保持 pending;注册后再执行,改名遗留可 tasks prune)`);
53
+ }
54
+ }
55
+ async function execute(task) {
56
+ const handler = handlers.get(task.name);
57
+ if (!handler)
58
+ return;
59
+ const started = Date.now();
60
+ const ctx = {
61
+ id: task.id,
62
+ name: task.name,
63
+ attempt: task.attempts,
64
+ };
65
+ try {
66
+ await handler(task.payload, ctx);
67
+ const elapsed = Date.now() - started;
68
+ if (elapsed > warnAfterMs) {
69
+ logger.warn(`[tasks] ${task.name}#${task.id} 运行 ${elapsed}ms 超过 warnAfterMs=${warnAfterMs}(只告警不中断)`);
70
+ }
71
+ await store.complete(task.id, now());
72
+ const schedule = periodic.get(task.name);
73
+ if (schedule) {
74
+ await store.enqueue({
75
+ name: task.name,
76
+ payload: schedule.payload,
77
+ runAt: new Date(now().getTime() + schedule.intervalMs),
78
+ });
79
+ }
80
+ }
81
+ catch (error) {
82
+ const message = error instanceof Error ? error.message : String(error);
83
+ if (task.attempts >= task.maxAttempts) {
84
+ await store.fail(task.id, { error: message, retryAt: null }, now());
85
+ }
86
+ else {
87
+ await store.fail(task.id, {
88
+ error: message,
89
+ retryAt: new Date(now().getTime() + backoffMs(task.attempts)),
90
+ }, now());
91
+ }
92
+ }
93
+ }
94
+ async function runOnce() {
95
+ for (const name of periodic.keys())
96
+ await ensureScheduled(name);
97
+ await warnUnknown();
98
+ const claimed = await store.claim({
99
+ now: now(),
100
+ workerId,
101
+ limit: concurrency,
102
+ visibilityTimeoutMs,
103
+ names: [...handlers.keys()],
104
+ });
105
+ if (claimed.length === 0)
106
+ return 0;
107
+ await Promise.all(claimed.map((task) => {
108
+ const promise = execute(task).finally(() => {
109
+ inFlight.delete(task.id);
110
+ });
111
+ inFlight.set(task.id, promise);
112
+ return promise;
113
+ }));
114
+ return claimed.length;
115
+ }
116
+ async function drain(drainOptions = {}) {
117
+ const maxIterations = drainOptions.maxIterations ?? 10_000;
118
+ for (let index = 0; index < maxIterations; index++) {
119
+ const count = await runOnce();
120
+ if (count === 0)
121
+ return;
122
+ }
123
+ }
124
+ async function tick() {
125
+ if (ticking)
126
+ return;
127
+ ticking = true;
128
+ try {
129
+ await runOnce();
130
+ }
131
+ catch (error) {
132
+ logger.error(`[tasks] 轮询失败:${error instanceof Error ? error.message : String(error)}`);
133
+ }
134
+ finally {
135
+ ticking = false;
136
+ }
137
+ }
138
+ const api = {
139
+ store,
140
+ handle(name, handler) {
141
+ handlers.set(name, handler);
142
+ return api;
143
+ },
144
+ async enqueue(name, payload, enqueueOptions = {}) {
145
+ const runAt = enqueueOptions.runAt ??
146
+ new Date(now().getTime() + (enqueueOptions.delay ?? 0));
147
+ const result = await store.enqueue({
148
+ name,
149
+ payload,
150
+ runAt,
151
+ maxAttempts: enqueueOptions.maxAttempts,
152
+ idempotencyKey: enqueueOptions.idempotencyKey ?? null,
153
+ });
154
+ if (options.autoStart !== false && !timer && !stopped)
155
+ api.start();
156
+ return { id: result.task.id, created: result.created, task: result.task };
157
+ },
158
+ install(app, installOptions = {}) {
159
+ const timeoutMs = installOptions.timeoutMs ?? 5000;
160
+ app.onClose(() => api.stop({ timeoutMs }));
161
+ api.start();
162
+ return api;
163
+ },
164
+ every(name, intervalMs, payload) {
165
+ periodic.set(name, { intervalMs, payload: payload ?? null });
166
+ return api;
167
+ },
168
+ start() {
169
+ stopped = false;
170
+ if (timer)
171
+ return;
172
+ for (const name of periodic.keys()) {
173
+ void ensureScheduled(name).catch((error) => logger.error(String(error)));
174
+ }
175
+ timer = setInterval(() => {
176
+ void tick();
177
+ }, pollIntervalMs);
178
+ timer.unref?.();
179
+ void tick();
180
+ },
181
+ async stop(stopOptions = {}) {
182
+ stopped = true;
183
+ if (timer) {
184
+ clearInterval(timer);
185
+ timer = null;
186
+ }
187
+ if (inFlight.size === 0)
188
+ return;
189
+ const timeoutMs = stopOptions.timeoutMs ?? 5000;
190
+ const deadline = Date.now() + timeoutMs;
191
+ while (inFlight.size > 0 && Date.now() < deadline) {
192
+ await Promise.race([
193
+ Promise.all([...inFlight.values()]),
194
+ new Promise((resolve) => setTimeout(resolve, 20)),
195
+ ]);
196
+ }
197
+ // 超时未完成:归还队列(继续跑完不阻塞进程,at-least-once 允许重跑)
198
+ if (inFlight.size > 0) {
199
+ for (const id of [...inFlight.keys()]) {
200
+ await store.release(id, now(), now());
201
+ }
202
+ }
203
+ },
204
+ runOnce,
205
+ drain,
206
+ retry: (id) => store.retry(id, now()),
207
+ list: (filter) => store.list(filter),
208
+ get running() {
209
+ return timer !== null;
210
+ },
211
+ };
212
+ return api;
213
+ }
214
+ //# sourceMappingURL=tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAaxC;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,OAA2B;IACrD,MAAM,KAAK,GAAc,OAAO,CAAC,KAAK,CAAA;IACtC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC,CAAA;IACzD,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC,CAAA;IACnE,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,MAAM,CAAA;IACjD,MAAM,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,IAAI,MAAM,CAAA;IACjE,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,MAAM,IAAI,IAAI,CAAA;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,GAAG,MAAM,CAAA;IACjD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;IAC7C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,UAAU,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAA;IACxF,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAA;IAExC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAA;IAC/C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoD,CAAA;IAC5E,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAA;IACvC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAA;IACjD,IAAI,KAAK,GAA0C,IAAI,CAAA;IACvD,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,IAAI,OAAO,GAAG,KAAK,CAAA;IAEnB,MAAM,SAAS,GAAG,CAAC,OAAe,EAAU,EAAE,CAC5C,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IAEzD,KAAK,UAAU,eAAe,CAAC,IAAY;QACzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACnC,IAAI,CAAC,QAAQ;YAAE,OAAM;QACrB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC;YAC9B,IAAI;YACJ,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;YAChC,KAAK,EAAE,CAAC;SACT,CAAC,CAAA;QACF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,OAAM;QAC7B,MAAM,KAAK,CAAC,OAAO,CAAC;YAClB,IAAI;YACJ,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,KAAK,EAAE,GAAG,EAAE;SACb,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,UAAU,WAAW;QACxB,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,CAAA;QAC7C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAQ;YAC3D,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YACvB,MAAM,CAAC,IAAI,CACT,uBAAuB,IAAI,uCAAuC,CACnE,CAAA;QACH,CAAC;IACH,CAAC;IAED,KAAK,UAAU,OAAO,CAAC,IAAU;QAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACvC,IAAI,CAAC,OAAO;YAAE,OAAM;QACpB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC1B,MAAM,GAAG,GAAgB;YACvB,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,QAAQ;SACvB,CAAA;QACD,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;YAChC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAA;YACpC,IAAI,OAAO,GAAG,WAAW,EAAE,CAAC;gBAC1B,MAAM,CAAC,IAAI,CACT,WAAW,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,OAAO,OAAO,qBAAqB,WAAW,UAAU,CACxF,CAAA;YACH,CAAC;YACD,MAAM,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;YACpC,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACxC,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,KAAK,CAAC,OAAO,CAAC;oBAClB,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,OAAO,EAAE,QAAQ,CAAC,OAAO;oBACzB,KAAK,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,UAAU,CAAC;iBACvD,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACtE,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;YACrE,CAAC;iBAAM,CAAC;gBACN,MAAM,KAAK,CAAC,IAAI,CACd,IAAI,CAAC,EAAE,EACP;oBACE,KAAK,EAAE,OAAO;oBACd,OAAO,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;iBAC9D,EACD,GAAG,EAAE,CACN,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,UAAU,OAAO;QACpB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE;YAAE,MAAM,eAAe,CAAC,IAAI,CAAC,CAAA;QAC/D,MAAM,WAAW,EAAE,CAAA;QACnB,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;YAChC,GAAG,EAAE,GAAG,EAAE;YACV,QAAQ;YACR,KAAK,EAAE,WAAW;YAClB,mBAAmB;YACnB,KAAK,EAAE,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;SAC5B,CAAC,CAAA;QACF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAA;QAClC,MAAM,OAAO,CAAC,GAAG,CACf,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACnB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;gBACzC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC1B,CAAC,CAAC,CAAA;YACF,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;YAC9B,OAAO,OAAO,CAAA;QAChB,CAAC,CAAC,CACH,CAAA;QACD,OAAO,OAAO,CAAC,MAAM,CAAA;IACvB,CAAC;IAED,KAAK,UAAU,KAAK,CAAC,eAA2C,EAAE;QAChE,MAAM,aAAa,GAAG,YAAY,CAAC,aAAa,IAAI,MAAM,CAAA;QAC1D,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,aAAa,EAAE,KAAK,EAAE,EAAE,CAAC;YACnD,MAAM,KAAK,GAAG,MAAM,OAAO,EAAE,CAAA;YAC7B,IAAI,KAAK,KAAK,CAAC;gBAAE,OAAM;QACzB,CAAC;IACH,CAAC;IAED,KAAK,UAAU,IAAI;QACjB,IAAI,OAAO;YAAE,OAAM;QACnB,OAAO,GAAG,IAAI,CAAA;QACd,IAAI,CAAC;YACH,MAAM,OAAO,EAAE,CAAA;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CACV,gBAAgB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACzE,CAAA;QACH,CAAC;gBAAS,CAAC;YACT,OAAO,GAAG,KAAK,CAAA;QACjB,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAU;QACjB,KAAK;QAEL,MAAM,CAAC,IAAY,EAAE,OAAoB;YACvC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YAC3B,OAAO,GAAG,CAAA;QACZ,CAAC;QAED,KAAK,CAAC,OAAO,CACX,IAAY,EACZ,OAAiB,EACjB,iBAAiC,EAAE;YAEnC,MAAM,KAAK,GACT,cAAc,CAAC,KAAK;gBACpB,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAA;YACzD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;gBACjC,IAAI;gBACJ,OAAO;gBACP,KAAK;gBACL,WAAW,EAAE,cAAc,CAAC,WAAW;gBACvC,cAAc,EAAE,cAAc,CAAC,cAAc,IAAI,IAAI;aACtD,CAAC,CAAA;YACF,IAAI,OAAO,CAAC,SAAS,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO;gBAAE,GAAG,CAAC,KAAK,EAAE,CAAA;YAClE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAA;QAC3E,CAAC;QAED,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,EAAE;YAC9B,MAAM,SAAS,GAAG,cAAc,CAAC,SAAS,IAAI,IAAI,CAAA;YAClD,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAA;YAC1C,GAAG,CAAC,KAAK,EAAE,CAAA;YACX,OAAO,GAAG,CAAA;QACZ,CAAC;QAED,KAAK,CAAC,IAAY,EAAE,UAAkB,EAAE,OAAiB;YACvD,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,CAAC,CAAA;YAC5D,OAAO,GAAG,CAAA;QACZ,CAAC;QAED,KAAK;YACH,OAAO,GAAG,KAAK,CAAA;YACf,IAAI,KAAK;gBAAE,OAAM;YACjB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;gBACnC,KAAK,eAAe,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;YAC1E,CAAC;YACD,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;gBACvB,KAAK,IAAI,EAAE,CAAA;YACb,CAAC,EAAE,cAAc,CAAC,CAAA;YAClB,KAAK,CAAC,KAAK,EAAE,EAAE,CAAA;YACf,KAAK,IAAI,EAAE,CAAA;QACb,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,cAAsC,EAAE;YACjD,OAAO,GAAG,IAAI,CAAA;YACd,IAAI,KAAK,EAAE,CAAC;gBACV,aAAa,CAAC,KAAK,CAAC,CAAA;gBACpB,KAAK,GAAG,IAAI,CAAA;YACd,CAAC;YACD,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC;gBAAE,OAAM;YAC/B,MAAM,SAAS,GAAG,WAAW,CAAC,SAAS,IAAI,IAAI,CAAA;YAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAA;YACvC,OAAO,QAAQ,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;gBAClD,MAAM,OAAO,CAAC,IAAI,CAAC;oBACjB,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;oBACnC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;iBAClD,CAAC,CAAA;YACJ,CAAC;YACD,2CAA2C;YAC3C,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBACtB,KAAK,MAAM,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;oBACtC,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;gBACvC,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO;QACP,KAAK;QACL,KAAK,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC;QAC7C,IAAI,EAAE,CAAC,MAAmB,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;QACjD,IAAI,OAAO;YACT,OAAO,KAAK,KAAK,IAAI,CAAA;QACvB,CAAC;KACF,CAAA;IAED,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { TaskStore } from './types.ts';
2
+ /**
3
+ * 任务存储契约套件:memory / sqlite / postgres / redis 与自定义驱动共用。
4
+ *
5
+ * ```ts
6
+ * import { tasksStoreContract } from '@weifuwujs/tasks/testing'
7
+ * tasksStoreContract('my-store', () => myTaskStore())
8
+ * ```
9
+ */
10
+ export declare function tasksStoreContract(name: string, create: () => TaskStore | Promise<TaskStore>, options?: {
11
+ skip?: boolean | string;
12
+ }): void;
13
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAI3C;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,EAC5C,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;CAAO,GACxC,IAAI,CAoON"}
@@ -0,0 +1,211 @@
1
+ import assert from 'node:assert/strict';
2
+ import { describe, test } from 'node:test';
3
+ const T0 = new Date('2026-01-01T00:00:00.000Z');
4
+ /**
5
+ * 任务存储契约套件:memory / sqlite / postgres / redis 与自定义驱动共用。
6
+ *
7
+ * ```ts
8
+ * import { tasksStoreContract } from '@weifuwujs/tasks/testing'
9
+ * tasksStoreContract('my-store', () => myTaskStore())
10
+ * ```
11
+ */
12
+ export function tasksStoreContract(name, create, options = {}) {
13
+ describe(`task store contract (${name})`, { skip: options.skip }, () => {
14
+ test('enqueue/get/幂等键', async () => {
15
+ const store = await create();
16
+ const first = await store.enqueue({
17
+ name: 'a',
18
+ payload: { n: 1 },
19
+ runAt: T0,
20
+ idempotencyKey: 'k-1',
21
+ });
22
+ assert.equal(first.created, true);
23
+ assert.equal(first.task.status, 'pending');
24
+ assert.equal(first.task.attempts, 0);
25
+ assert.equal(first.task.lockedBy, null);
26
+ assert.equal(first.task.maxAttempts, 5);
27
+ assert.deepEqual(first.task.payload, { n: 1 });
28
+ assert.deepEqual((await store.get(first.task.id))?.payload, { n: 1 });
29
+ const again = await store.enqueue({
30
+ name: 'a',
31
+ payload: { n: 2 },
32
+ runAt: T0,
33
+ idempotencyKey: 'k-1',
34
+ });
35
+ assert.equal(again.created, false);
36
+ assert.equal(again.task.id, first.task.id);
37
+ assert.deepEqual(again.task.payload, { n: 1 }, '幂等命中不得覆盖原任务');
38
+ const noKey = await store.enqueue({ name: 'a', runAt: T0 });
39
+ assert.equal(noKey.created, true);
40
+ assert.equal((await store.list()).length, 2);
41
+ assert.equal(await store.get('missing'), null);
42
+ assert.ok((await store.pendingNames(T0)).includes('a'));
43
+ });
44
+ test('claim:原子、attempts、names 过滤、锁过期回收', async () => {
45
+ const store = await create();
46
+ await store.enqueue({ name: 'a', runAt: T0 });
47
+ await store.enqueue({ name: 'a', runAt: T0 });
48
+ await store.enqueue({ name: 'b', runAt: T0 });
49
+ const claimed = await store.claim({
50
+ now: T0,
51
+ workerId: 'w1',
52
+ limit: 2,
53
+ visibilityTimeoutMs: 60_000,
54
+ });
55
+ assert.equal(claimed.length, 2);
56
+ for (const task of claimed) {
57
+ assert.equal(task.status, 'running');
58
+ assert.equal(task.lockedBy, 'w1');
59
+ assert.ok(task.lockedAt);
60
+ assert.equal(task.attempts, 1);
61
+ }
62
+ const second = await store.claim({
63
+ now: T0,
64
+ workerId: 'w2',
65
+ limit: 5,
66
+ visibilityTimeoutMs: 60_000,
67
+ });
68
+ assert.equal(second.length, 1, '同一任务不得双取');
69
+ await store.complete(claimed[0].id, T0);
70
+ assert.equal((await store.get(claimed[0].id))?.status, 'done');
71
+ const beforeExpiry = await store.claim({
72
+ now: new Date(T0.getTime() + 59_000),
73
+ workerId: 'w3',
74
+ limit: 5,
75
+ visibilityTimeoutMs: 60_000,
76
+ });
77
+ assert.equal(beforeExpiry.length, 0, '锁未过期不得重取');
78
+ const reclaimed = await store.claim({
79
+ now: new Date(T0.getTime() + 61_000),
80
+ workerId: 'w3',
81
+ limit: 5,
82
+ visibilityTimeoutMs: 60_000,
83
+ });
84
+ assert.equal(reclaimed.length, 2, '锁过期必须回队');
85
+ assert.equal(reclaimed[0].attempts, 2, '重领即第二次尝试');
86
+ assert.equal(reclaimed[0].lockedBy, 'w3');
87
+ const none = await store.claim({
88
+ now: new Date(T0.getTime() + 200_000),
89
+ workerId: 'w4',
90
+ limit: 5,
91
+ visibilityTimeoutMs: 60_000,
92
+ names: [],
93
+ });
94
+ assert.equal(none.length, 0, 'names 为空不得领取');
95
+ });
96
+ test('fail/retry/release:退避、死信、手动重驱', async () => {
97
+ const store = await create();
98
+ const { task } = await store.enqueue({
99
+ name: 'a',
100
+ runAt: T0,
101
+ maxAttempts: 2,
102
+ });
103
+ const [claimed] = await store.claim({
104
+ now: T0,
105
+ workerId: 'w',
106
+ limit: 1,
107
+ visibilityTimeoutMs: 60_000,
108
+ });
109
+ assert.equal(claimed.attempts, 1);
110
+ await store.fail(task.id, { error: 'boom-1', retryAt: new Date(T0.getTime() + 5000) }, T0);
111
+ let row = (await store.get(task.id));
112
+ assert.equal(row.status, 'pending');
113
+ assert.equal(row.lastError, 'boom-1');
114
+ assert.equal(row.runAt.getTime(), T0.getTime() + 5000);
115
+ assert.equal(row.lockedBy, null);
116
+ const notYet = await store.claim({
117
+ now: T0,
118
+ workerId: 'w',
119
+ limit: 1,
120
+ visibilityTimeoutMs: 60_000,
121
+ });
122
+ assert.equal(notYet.length, 0, '未到 retryAt 不得领取');
123
+ const [again] = await store.claim({
124
+ now: new Date(T0.getTime() + 5000),
125
+ workerId: 'w',
126
+ limit: 1,
127
+ visibilityTimeoutMs: 60_000,
128
+ });
129
+ assert.equal(again.attempts, 2);
130
+ await store.fail(task.id, { error: 'boom-2', retryAt: null }, T0);
131
+ row = (await store.get(task.id));
132
+ assert.equal(row.status, 'dead');
133
+ assert.equal(row.lastError, 'boom-2');
134
+ assert.equal(await store.retry(task.id, T0), true);
135
+ row = (await store.get(task.id));
136
+ assert.equal(row.status, 'pending');
137
+ assert.equal(row.attempts, 0, '手动重驱 attempts 归零');
138
+ assert.equal(await store.retry('missing', T0), false);
139
+ const released = await store.enqueue({ name: 'r', runAt: T0 });
140
+ const [claimedRelease] = await store.claim({
141
+ now: T0,
142
+ workerId: 'w',
143
+ limit: 1,
144
+ visibilityTimeoutMs: 60_000,
145
+ names: ['r'],
146
+ });
147
+ await store.release(claimedRelease.id, new Date(T0.getTime() + 1000), T0);
148
+ const releasedRow = (await store.get(released.task.id));
149
+ assert.equal(releasedRow.status, 'pending');
150
+ assert.equal(releasedRow.attempts, 1, 'release 保留 attempts');
151
+ assert.equal(releasedRow.runAt.getTime(), T0.getTime() + 1000);
152
+ });
153
+ test('硬崩溃:锁过期且 attempts 达上限 → dead,不无限重跑', async () => {
154
+ const store = await create();
155
+ const { task } = await store.enqueue({
156
+ name: 'a',
157
+ runAt: T0,
158
+ maxAttempts: 1,
159
+ });
160
+ await store.claim({
161
+ now: T0,
162
+ workerId: 'w',
163
+ limit: 1,
164
+ visibilityTimeoutMs: 60_000,
165
+ });
166
+ const reclaimed = await store.claim({
167
+ now: new Date(T0.getTime() + 61_000),
168
+ workerId: 'w2',
169
+ limit: 1,
170
+ visibilityTimeoutMs: 60_000,
171
+ });
172
+ assert.equal(reclaimed.length, 0);
173
+ const row = (await store.get(task.id));
174
+ assert.equal(row.status, 'dead');
175
+ assert.match(row.lastError ?? '', /visibility/i);
176
+ });
177
+ test('prune:清理 done/dead,不碰 pending', async () => {
178
+ const store = await create();
179
+ const done = await store.enqueue({ name: 'a', runAt: T0 });
180
+ await store.claim({
181
+ now: T0,
182
+ workerId: 'w',
183
+ limit: 1,
184
+ visibilityTimeoutMs: 60_000,
185
+ });
186
+ await store.complete(done.task.id, T0);
187
+ const dead = await store.enqueue({ name: 'b', runAt: T0 });
188
+ const [claimedDead] = await store.claim({
189
+ now: T0,
190
+ workerId: 'w',
191
+ limit: 1,
192
+ visibilityTimeoutMs: 60_000,
193
+ });
194
+ await store.fail(claimedDead.id, { error: 'dead', retryAt: null }, T0);
195
+ const pending = await store.enqueue({
196
+ name: 'c',
197
+ runAt: new Date(T0.getTime() + 10 * 60_000),
198
+ });
199
+ const removed = await store.prune({
200
+ now: new Date(T0.getTime() + 60_000),
201
+ olderThanMs: 30_000,
202
+ statuses: ['done', 'dead'],
203
+ });
204
+ assert.equal(removed, 2);
205
+ assert.equal(await store.get(done.task.id), null);
206
+ assert.equal(await store.get(dead.task.id), null);
207
+ assert.ok(await store.get(pending.task.id));
208
+ });
209
+ });
210
+ }
211
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAG1C,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,0BAA0B,CAAC,CAAA;AAE/C;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,MAA4C,EAC5C,UAAuC,EAAE;IAEzC,QAAQ,CAAC,wBAAwB,IAAI,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE;QACrE,IAAI,CAAC,iBAAiB,EAAE,KAAK,IAAI,EAAE;YACjC,MAAM,KAAK,GAAG,MAAM,MAAM,EAAE,CAAA;YAC5B,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;gBAChC,IAAI,EAAE,GAAG;gBACT,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE;gBACjB,KAAK,EAAE,EAAE;gBACT,cAAc,EAAE,KAAK;aACtB,CAAC,CAAA;YACF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;YAC1C,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;YACpC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;YACvC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;YACvC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;YAC9C,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;YAErE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;gBAChC,IAAI,EAAE,GAAG;gBACT,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE;gBACjB,KAAK,EAAE,EAAE;gBACT,cAAc,EAAE,KAAK;aACtB,CAAC,CAAA;YACF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC1C,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,CAAA;YAE7D,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAA;YAC3D,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;YAE5C,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAA;YAC9C,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;QACzD,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;YAClD,MAAM,KAAK,GAAG,MAAM,MAAM,EAAE,CAAA;YAC5B,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAA;YAC7C,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAA;YAC7C,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAA;YAE7C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;gBAChC,GAAG,EAAE,EAAE;gBACP,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,CAAC;gBACR,mBAAmB,EAAE,MAAM;aAC5B,CAAC,CAAA;YACF,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;YAC/B,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;gBAC3B,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;gBACpC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;gBACjC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;gBACxB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;YAChC,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;gBAC/B,GAAG,EAAE,EAAE;gBACP,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,CAAC;gBACR,mBAAmB,EAAE,MAAM;aAC5B,CAAC,CAAA;YACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,UAAU,CAAC,CAAA;YAE1C,MAAM,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;YACxC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;YAE/D,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;gBACrC,GAAG,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC;gBACpC,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,CAAC;gBACR,mBAAmB,EAAE,MAAM;aAC5B,CAAC,CAAA;YACF,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,UAAU,CAAC,CAAA;YAEhD,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;gBAClC,GAAG,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC;gBACpC,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,CAAC;gBACR,mBAAmB,EAAE,MAAM;aAC5B,CAAC,CAAA;YACF,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,SAAS,CAAC,CAAA;YAC5C,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAE,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAA;YACnD,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;YAE1C,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;gBAC7B,GAAG,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC;gBACrC,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,CAAC;gBACR,mBAAmB,EAAE,MAAM;gBAC3B,KAAK,EAAE,EAAE;aACV,CAAC,CAAA;YACF,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,cAAc,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,KAAK,GAAG,MAAM,MAAM,EAAE,CAAA;YAC5B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;gBACnC,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,EAAE;gBACT,WAAW,EAAE,CAAC;aACf,CAAC,CAAA;YACF,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;gBAClC,GAAG,EAAE,EAAE;gBACP,QAAQ,EAAE,GAAG;gBACb,KAAK,EAAE,CAAC;gBACR,mBAAmB,EAAE,MAAM;aAC5B,CAAC,CAAA;YACF,MAAM,CAAC,KAAK,CAAC,OAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;YAElC,MAAM,KAAK,CAAC,IAAI,CACd,IAAI,CAAC,EAAE,EACP,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,EAAE,EAC3D,EAAE,CACH,CAAA;YACD,IAAI,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAE,CAAA;YACrC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;YACnC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;YACrC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAA;YACtD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;YAEhC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;gBAC/B,GAAG,EAAE,EAAE;gBACP,QAAQ,EAAE,GAAG;gBACb,KAAK,EAAE,CAAC;gBACR,mBAAmB,EAAE,MAAM;aAC5B,CAAC,CAAA;YACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAAA;YAEjD,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;gBAChC,GAAG,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;gBAClC,QAAQ,EAAE,GAAG;gBACb,KAAK,EAAE,CAAC;gBACR,mBAAmB,EAAE,MAAM;aAC5B,CAAC,CAAA;YACF,MAAM,CAAC,KAAK,CAAC,KAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;YAEhC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;YACjE,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAE,CAAA;YACjC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YAChC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;YAErC,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;YAClD,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAE,CAAA;YACjC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;YACnC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,kBAAkB,CAAC,CAAA;YACjD,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;YAErD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAA;YAC9D,MAAM,CAAC,cAAc,CAAC,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;gBACzC,GAAG,EAAE,EAAE;gBACP,QAAQ,EAAE,GAAG;gBACb,KAAK,EAAE,CAAC;gBACR,mBAAmB,EAAE,MAAM;gBAC3B,KAAK,EAAE,CAAC,GAAG,CAAC;aACb,CAAC,CAAA;YACF,MAAM,KAAK,CAAC,OAAO,CACjB,cAAe,CAAC,EAAE,EAClB,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,EAC7B,EAAE,CACH,CAAA;YACD,MAAM,WAAW,GAAG,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAE,CAAA;YACxD,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;YAC3C,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,EAAE,qBAAqB,CAAC,CAAA;YAC5D,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAA;QAChE,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;YACpD,MAAM,KAAK,GAAG,MAAM,MAAM,EAAE,CAAA;YAC5B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;gBACnC,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,EAAE;gBACT,WAAW,EAAE,CAAC;aACf,CAAC,CAAA;YACF,MAAM,KAAK,CAAC,KAAK,CAAC;gBAChB,GAAG,EAAE,EAAE;gBACP,QAAQ,EAAE,GAAG;gBACb,KAAK,EAAE,CAAC;gBACR,mBAAmB,EAAE,MAAM;aAC5B,CAAC,CAAA;YACF,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;gBAClC,GAAG,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC;gBACpC,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,CAAC;gBACR,mBAAmB,EAAE,MAAM;aAC5B,CAAC,CAAA;YACF,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;YACjC,MAAM,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAE,CAAA;YACvC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YAChC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,EAAE,aAAa,CAAC,CAAA;QAClD,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,KAAK,GAAG,MAAM,MAAM,EAAE,CAAA;YAC5B,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAA;YAC1D,MAAM,KAAK,CAAC,KAAK,CAAC;gBAChB,GAAG,EAAE,EAAE;gBACP,QAAQ,EAAE,GAAG;gBACb,KAAK,EAAE,CAAC;gBACR,mBAAmB,EAAE,MAAM;aAC5B,CAAC,CAAA;YACF,MAAM,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;YAEtC,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAA;YAC1D,MAAM,CAAC,WAAW,CAAC,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;gBACtC,GAAG,EAAE,EAAE;gBACP,QAAQ,EAAE,GAAG;gBACb,KAAK,EAAE,CAAC;gBACR,mBAAmB,EAAE,MAAM;aAC5B,CAAC,CAAA;YACF,MAAM,KAAK,CAAC,IAAI,CAAC,WAAY,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;YAEvE,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;gBAClC,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;aAC5C,CAAC,CAAA;YAEF,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC;gBAChC,GAAG,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC;gBACpC,WAAW,EAAE,MAAM;gBACnB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;aAC3B,CAAC,CAAA;YACF,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;YACxB,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;YACjD,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;YACjD,MAAM,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;QAC7C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,158 @@
1
+ /** 任务队列核心类型(驱动与执行器共用,四驱动契约一致) */
2
+ export type TaskStatus = 'pending' | 'running' | 'done' | 'dead';
3
+ export interface Task {
4
+ id: string;
5
+ name: string;
6
+ /** 必须 JSON 可序列化(判负;驱动按此持久化) */
7
+ payload: unknown;
8
+ runAt: Date;
9
+ /** 已尝试次数(claim 即 +1,硬崩溃也会计入) */
10
+ attempts: number;
11
+ maxAttempts: number;
12
+ status: TaskStatus;
13
+ lockedBy: string | null;
14
+ lockedAt: Date | null;
15
+ /** 防重复入队;冲突时 enqueue 返回已有任务 */
16
+ idempotencyKey: string | null;
17
+ lastError: string | null;
18
+ createdAt: Date;
19
+ updatedAt: Date;
20
+ }
21
+ export interface EnqueueInput {
22
+ name: string;
23
+ payload?: unknown;
24
+ /** 默认立即到期 */
25
+ runAt?: Date;
26
+ maxAttempts?: number;
27
+ idempotencyKey?: string | null;
28
+ }
29
+ export interface EnqueueResult {
30
+ /** 任务 id(幂等命中时为已有任务) */
31
+ id: string;
32
+ /** false = 幂等键命中已有任务 */
33
+ created: boolean;
34
+ task: Task;
35
+ }
36
+ /** 驱动层返回(契约套件直接用) */
37
+ export interface StoreEnqueueResult {
38
+ task: Task;
39
+ created: boolean;
40
+ }
41
+ export interface ClaimOptions {
42
+ now: Date;
43
+ workerId: string;
44
+ limit: number;
45
+ /** 超过此时长仍 running 的任务回队(硬崩溃恢复) */
46
+ visibilityTimeoutMs: number;
47
+ /** 只领取这些 handler 名下的任务;不传 = 全部 */
48
+ names?: string[];
49
+ }
50
+ export interface FailInput {
51
+ error: string;
52
+ /** 下次运行时间;null = 进死信 */
53
+ retryAt: Date | null;
54
+ }
55
+ export interface ListFilter {
56
+ statuses?: TaskStatus[];
57
+ name?: string;
58
+ limit?: number;
59
+ }
60
+ export interface PruneOptions {
61
+ now: Date;
62
+ olderThanMs: number;
63
+ /** 默认 ['done', 'dead'] */
64
+ statuses?: TaskStatus[];
65
+ }
66
+ /**
67
+ * 存储契约(memory / sqlite / postgres / redis 同一套)。
68
+ *
69
+ * 语义要点:
70
+ * - `claim` 原子且不双取;锁过期的 running 任务可被重领(attempts +1);
71
+ * 锁过期且 attempts 已达 maxAttempts → 置 dead(lastError 含 visibility),不无限重跑;
72
+ * - `enqueue` 幂等键冲突返回已有任务(created=false),不报错;
73
+ * - `payload` 必须 JSON 可序列化。
74
+ */
75
+ export interface TaskStore {
76
+ enqueue(input: EnqueueInput): Promise<StoreEnqueueResult>;
77
+ claim(options: ClaimOptions): Promise<Task[]>;
78
+ complete(id: string, now: Date): Promise<void>;
79
+ fail(id: string, input: FailInput, now: Date): Promise<void>;
80
+ /** 归还任务(关闭超时/未知 handler):running → pending,attempts 保留 */
81
+ release(id: string, runAt: Date, now: Date): Promise<void>;
82
+ /** 死信手动重驱:dead → pending,attempts 归零 */
83
+ retry(id: string, now: Date): Promise<boolean>;
84
+ get(id: string): Promise<Task | null>;
85
+ list(filter?: ListFilter): Promise<Task[]>;
86
+ /** 清理终态任务(默认 done/dead),按 updatedAt 早于 now-olderThanMs */
87
+ prune(options: PruneOptions): Promise<number>;
88
+ /** 到期待执行的 distinct name(未知 handler 告警用) */
89
+ pendingNames(now: Date): Promise<string[]>;
90
+ migrate?(): Promise<void>;
91
+ }
92
+ export interface TaskContext {
93
+ id: string;
94
+ name: string;
95
+ /** 本次是第几次尝试(从 1 开始) */
96
+ attempt: number;
97
+ }
98
+ export type TaskHandler = (payload: any, ctx: TaskContext) => void | Promise<void>;
99
+ export interface TaskLogger {
100
+ warn(message: string): void;
101
+ error(message: string): void;
102
+ }
103
+ /** `tasks.install(app)` 只需要 onClose 能力 */
104
+ export interface CloseableApp {
105
+ onClose(disposer: () => void | Promise<void>): unknown;
106
+ }
107
+ export interface CreateTasksOptions {
108
+ store: TaskStore;
109
+ /** 单进程并发执行数,默认 1 */
110
+ concurrency?: number;
111
+ /** 轮询间隔,默认 1000ms */
112
+ pollIntervalMs?: number;
113
+ /** 单任务运行超过该时长只告警不中断,默认 30s */
114
+ warnAfterMs?: number;
115
+ /** 可见性超时(崩溃恢复),默认 60s */
116
+ visibilityTimeoutMs?: number;
117
+ /** 指数退避:默认 base 1s / max 15min */
118
+ retry?: {
119
+ baseMs?: number;
120
+ maxMs?: number;
121
+ };
122
+ now?: () => Date;
123
+ workerId?: string;
124
+ logger?: TaskLogger;
125
+ /** 进程内 worker 默认开启;测试可关 */
126
+ autoStart?: boolean;
127
+ }
128
+ export interface EnqueueOptions {
129
+ delay?: number;
130
+ runAt?: Date;
131
+ idempotencyKey?: string;
132
+ maxAttempts?: number;
133
+ }
134
+ export interface Tasks {
135
+ readonly store: TaskStore;
136
+ handle(name: string, handler: TaskHandler): Tasks;
137
+ enqueue(name: string, payload?: unknown, options?: EnqueueOptions): Promise<EnqueueResult>;
138
+ /** 周期任务:首次立即到期,完成后排下一次(宕机后 catch-up) */
139
+ every(name: string, intervalMs: number, payload?: unknown): Tasks;
140
+ /** 接入应用生命周期:启动 worker + `app.close()` 时优雅停止(默认 5s) */
141
+ install(app: CloseableApp, options?: {
142
+ timeoutMs?: number;
143
+ }): Tasks;
144
+ start(): void;
145
+ stop(options?: {
146
+ timeoutMs?: number;
147
+ }): Promise<void>;
148
+ /** 取一批(≤ concurrency)到期任务执行一次,返回执行数 */
149
+ runOnce(): Promise<number>;
150
+ /** 反复 runOnce 直到无到期任务(测试/内嵌调度) */
151
+ drain(options?: {
152
+ maxIterations?: number;
153
+ }): Promise<void>;
154
+ retry(id: string): Promise<boolean>;
155
+ list(filter?: ListFilter): Promise<Task[]>;
156
+ readonly running: boolean;
157
+ }
158
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ /** 任务队列核心类型(驱动与执行器共用,四驱动契约一致) */
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,iCAAiC"}