@zucker-framework/queue 1.0.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.
@@ -0,0 +1,384 @@
1
+ import { OnModuleDestroy, Type, DynamicModule, InjectionToken, OptionalFactoryDependency } from '@nestjs/common';
2
+ import { ConnectionOptions, QueueOptions, Queue, Job as Job$1, WorkerOptions, Worker, QueueEventsOptions, QueueEvents, JobProgress as JobProgress$1 } from 'bullmq';
3
+
4
+ /**
5
+ * 任务队列接口 — 不绑定 BullMQ,通过接口抽象允许替换实现。
6
+ */
7
+ interface QueueProvider {
8
+ /** 添加任务到队列 */
9
+ add<T>(queueName: string, data: T, options?: JobOptions): Promise<Job<T>>;
10
+ /** Ensure a stable job exists, replacing a stale terminal transport record when necessary. */
11
+ ensure<T>(queueName: string, data: T, options: JobOptions & {
12
+ jobId: string;
13
+ }): Promise<Job<T>>;
14
+ /** 添加延迟任务 */
15
+ addDelayed<T>(queueName: string, data: T, delayMs: number, options?: JobOptions): Promise<Job<T>>;
16
+ /** 添加定时任务 */
17
+ addRepeatable<T>(queueName: string, data: T, pattern: string, options?: JobOptions): Promise<Job<T>>;
18
+ /** 获取任务状态 */
19
+ getJob<T>(queueName: string, jobId: string): Promise<Job<T> | null>;
20
+ /** 移除任务 */
21
+ removeJob(queueName: string, jobId: string): Promise<void>;
22
+ /** 暂停队列 */
23
+ pause(queueName: string): Promise<void>;
24
+ /** 恢复队列 */
25
+ resume(queueName: string): Promise<void>;
26
+ /** 获取队列统计 */
27
+ getStats(queueName: string): Promise<QueueStats>;
28
+ }
29
+ interface JobOptions {
30
+ name?: string;
31
+ jobId?: string;
32
+ deduplicationId?: string;
33
+ priority?: number;
34
+ attempts?: number;
35
+ backoff?: {
36
+ type: 'fixed' | 'exponential';
37
+ delay: number;
38
+ };
39
+ removeOnComplete?: boolean | number;
40
+ removeOnFail?: boolean | number;
41
+ }
42
+ type JobProgress = number | string | boolean | object;
43
+ interface Job<T = unknown> {
44
+ id: string;
45
+ data: T;
46
+ status: 'waiting' | 'active' | 'completed' | 'failed' | 'delayed' | 'unknown';
47
+ progress: JobProgress;
48
+ attempts: number;
49
+ failedReason?: string;
50
+ createdAt: Date;
51
+ processedAt?: Date;
52
+ completedAt?: Date;
53
+ }
54
+ interface QueueStats {
55
+ waiting: number;
56
+ active: number;
57
+ completed: number;
58
+ failed: number;
59
+ delayed: number;
60
+ }
61
+ declare const QUEUE_PROVIDER = "QUEUE_PROVIDER";
62
+
63
+ /**
64
+ * 内存队列实现 — 开发/测试用途,不保证持久化。
65
+ * 生产环境请替换为 BullMQ 等实现。
66
+ */
67
+ declare class InMemoryQueue implements QueueProvider, OnModuleDestroy {
68
+ private readonly logger;
69
+ private queues;
70
+ private paused;
71
+ private counter;
72
+ /** timer 引用:queueName:jobId → timer */
73
+ private readonly delayTimers;
74
+ private getQueue;
75
+ private nextId;
76
+ add<T>(queueName: string, data: T, options?: JobOptions): Promise<Job<T>>;
77
+ ensure<T>(queueName: string, data: T, options: JobOptions & {
78
+ jobId: string;
79
+ }): Promise<Job<T>>;
80
+ addDelayed<T>(queueName: string, data: T, delayMs: number, options?: JobOptions): Promise<Job<T>>;
81
+ addRepeatable<T>(queueName: string, data: T, pattern: string, options?: JobOptions): Promise<Job<T>>;
82
+ getJob<T>(queueName: string, jobId: string): Promise<Job<T> | null>;
83
+ removeJob(queueName: string, jobId: string): Promise<void>;
84
+ pause(queueName: string): Promise<void>;
85
+ resume(queueName: string): Promise<void>;
86
+ getStats(queueName: string): Promise<QueueStats>;
87
+ onModuleDestroy(): void;
88
+ }
89
+
90
+ type QueueFactory = (name: string, options: QueueOptions) => Queue;
91
+ interface BullMqQueueProviderOptions {
92
+ connection: ConnectionOptions;
93
+ prefix?: string;
94
+ defaultJobName?: string;
95
+ queueFactory?: QueueFactory;
96
+ }
97
+ declare class BullMqQueueProvider implements QueueProvider {
98
+ private readonly options;
99
+ private readonly queues;
100
+ private readonly defaultJobName;
101
+ private readonly queueFactory;
102
+ constructor(options: BullMqQueueProviderOptions);
103
+ add<T>(queueName: string, data: T, options?: JobOptions): Promise<Job<T>>;
104
+ ensure<T>(queueName: string, data: T, options: JobOptions & {
105
+ jobId: string;
106
+ }): Promise<Job<T>>;
107
+ addDelayed<T>(queueName: string, data: T, delayMs: number, options?: JobOptions): Promise<Job<T>>;
108
+ addRepeatable<T>(queueName: string, data: T, pattern: string, options?: JobOptions): Promise<Job<T>>;
109
+ getJob<T>(queueName: string, jobId: string): Promise<Job<T> | null>;
110
+ removeJob(queueName: string, jobId: string): Promise<void>;
111
+ pause(queueName: string): Promise<void>;
112
+ resume(queueName: string): Promise<void>;
113
+ getStats(queueName: string): Promise<QueueStats>;
114
+ waitUntilReady(): Promise<void>;
115
+ close(): Promise<void>;
116
+ onModuleDestroy(): Promise<void>;
117
+ private getQueue;
118
+ private toBullMqOptions;
119
+ private toBullMqSchedulerOptions;
120
+ private assertValidJobId;
121
+ private toJob;
122
+ private mapState;
123
+ }
124
+
125
+ interface BullMqConnectionFromUrlOptions {
126
+ role?: 'producer' | 'worker';
127
+ }
128
+ /** Converts a redis:// or rediss:// URL into BullMQ/ioredis connection options. */
129
+ declare function bullMqConnectionFromUrl(redisUrl: string, options?: BullMqConnectionFromUrlOptions): ConnectionOptions;
130
+
131
+ interface QueueWorkerJob<TData> {
132
+ id: string;
133
+ name: string;
134
+ data: TData;
135
+ attempt: number;
136
+ updateProgress(progress: JobProgress): Promise<void>;
137
+ log(message: string): Promise<number>;
138
+ }
139
+ type QueueJobHandler<TData, TResult> = (job: QueueWorkerJob<TData>) => Promise<TResult>;
140
+ interface QueueWorkerDefinition<TData = unknown, TResult = unknown> {
141
+ queueName: string;
142
+ handler: QueueJobHandler<TData, TResult>;
143
+ concurrency?: number;
144
+ lockDurationMs?: number;
145
+ autorun?: boolean;
146
+ }
147
+ type WorkerFactory = (queueName: string, processor: (job: Job$1) => Promise<unknown>, options: WorkerOptions) => Worker;
148
+ interface BullMqWorkerHostOptions {
149
+ connection: ConnectionOptions;
150
+ prefix?: string;
151
+ onError?: (queueName: string, error: Error) => void;
152
+ workerFactory?: WorkerFactory;
153
+ }
154
+ interface QueueWorkerHealth {
155
+ ready: boolean;
156
+ registeredQueues: readonly string[];
157
+ runningQueues: readonly string[];
158
+ }
159
+ declare class BullMqWorkerHost {
160
+ private readonly options;
161
+ private readonly workers;
162
+ private readonly readyQueues;
163
+ private readonly workerFactory;
164
+ constructor(options: BullMqWorkerHostOptions);
165
+ register<TData, TResult>(definition: QueueWorkerDefinition<TData, TResult>): void;
166
+ waitUntilReady(): Promise<void>;
167
+ health(): QueueWorkerHealth;
168
+ /**
169
+ * Actively verifies the Redis connections behind every worker.
170
+ *
171
+ * BullMQ's ready/error events cannot detect a half-open connection where the
172
+ * TCP socket still exists but Redis no longer answers. Readiness endpoints
173
+ * should use this bounded probe instead of relying on lifecycle events alone.
174
+ */
175
+ probeHealth(timeoutMs?: number): Promise<QueueWorkerHealth>;
176
+ run(queueName: string): void;
177
+ pause(): Promise<void>;
178
+ resume(): Promise<void>;
179
+ close(force?: boolean): Promise<void>;
180
+ onModuleDestroy(): Promise<void>;
181
+ private requireWorker;
182
+ }
183
+
184
+ type QueueEventsFactory = (queueName: string, options: QueueEventsOptions) => QueueEvents;
185
+ interface QueueCompletedEvent {
186
+ queueName: string;
187
+ jobId: string;
188
+ returnvalue: string;
189
+ }
190
+ interface QueueFailedEvent {
191
+ queueName: string;
192
+ jobId: string;
193
+ failedReason: string;
194
+ }
195
+ interface QueueProgressEvent {
196
+ queueName: string;
197
+ jobId: string;
198
+ data: JobProgress$1;
199
+ }
200
+ interface QueueStateEvent {
201
+ queueName: string;
202
+ jobId: string;
203
+ }
204
+ interface QueueEventHandlers {
205
+ completed?: (event: QueueCompletedEvent) => void;
206
+ failed?: (event: QueueFailedEvent) => void;
207
+ progress?: (event: QueueProgressEvent) => void;
208
+ waiting?: (event: QueueStateEvent) => void;
209
+ active?: (event: QueueStateEvent) => void;
210
+ }
211
+ interface BullMqQueueEventsOptions {
212
+ connection: ConnectionOptions;
213
+ prefix?: string;
214
+ onError?: (queueName: string, error: Error) => void;
215
+ queueEventsFactory?: QueueEventsFactory;
216
+ }
217
+ declare class BullMqQueueEvents {
218
+ private readonly options;
219
+ private readonly listeners;
220
+ private readonly queueEventsFactory;
221
+ constructor(options: BullMqQueueEventsOptions);
222
+ listen(queueName: string, handlers: QueueEventHandlers): () => void;
223
+ waitUntilReady(): Promise<void>;
224
+ close(): Promise<void>;
225
+ onModuleDestroy(): Promise<void>;
226
+ private getQueueEvents;
227
+ }
228
+
229
+ /**
230
+ * QueueService — 队列管理服务,对 QueueProvider 做薄封装,
231
+ * 方便在业务代码中注入使用。
232
+ */
233
+ declare class QueueService {
234
+ private readonly provider;
235
+ constructor(provider: QueueProvider);
236
+ /** 添加任务到队列 */
237
+ add<T>(queueName: string, data: T, options?: JobOptions): Promise<Job<T>>;
238
+ /** Ensure a stable transport job exists for durable queued work. */
239
+ ensure<T>(queueName: string, data: T, options: JobOptions & {
240
+ jobId: string;
241
+ }): Promise<Job<T>>;
242
+ /** 添加延迟任务 */
243
+ addDelayed<T>(queueName: string, data: T, delayMs: number, options?: JobOptions): Promise<Job<T>>;
244
+ /** 添加定时任务 */
245
+ addRepeatable<T>(queueName: string, data: T, pattern: string, options?: JobOptions): Promise<Job<T>>;
246
+ /** 获取任务状态 */
247
+ getJob<T>(queueName: string, jobId: string): Promise<Job<T> | null>;
248
+ /** 移除任务 */
249
+ removeJob(queueName: string, jobId: string): Promise<void>;
250
+ /** 暂停队列 */
251
+ pause(queueName: string): Promise<void>;
252
+ /** 恢复队列 */
253
+ resume(queueName: string): Promise<void>;
254
+ /** 获取队列统计 */
255
+ getStats(queueName: string): Promise<QueueStats>;
256
+ }
257
+
258
+ interface QueueModuleOptions {
259
+ /** 自定义 QueueProvider 实例;缺省使用 InMemoryQueue */
260
+ provider?: QueueProvider;
261
+ }
262
+ interface QueueModuleAsyncOptions {
263
+ imports?: Array<Type | DynamicModule>;
264
+ useFactory?: (...args: unknown[]) => QueueModuleOptions | Promise<QueueModuleOptions>;
265
+ useClass?: Type<QueueModuleOptionsFactory>;
266
+ useExisting?: Type<QueueModuleOptionsFactory>;
267
+ inject?: Array<InjectionToken | OptionalFactoryDependency>;
268
+ }
269
+ interface QueueModuleOptionsFactory {
270
+ createQueueOptions(): QueueModuleOptions | Promise<QueueModuleOptions>;
271
+ }
272
+ declare class ZuckerQueueModule {
273
+ static forRoot(options?: QueueModuleOptions): DynamicModule;
274
+ static forRootAsync(options: QueueModuleAsyncOptions): DynamicModule;
275
+ private static createAsyncProviders;
276
+ }
277
+
278
+ declare const QUEUE_WORKER_KEY = "ZUCKER_QUEUE_WORKER";
279
+ interface QueueWorkerOptions {
280
+ queue: string;
281
+ concurrency?: number;
282
+ }
283
+ /**
284
+ * @QueueWorker — 标记一个方法为队列消费者。
285
+ * 对标 BullMQ 的 @Process() 装饰器。
286
+ */
287
+ declare function QueueWorker(options: QueueWorkerOptions | string): MethodDecorator;
288
+
289
+ /**
290
+ * 后台任务生命周期管理 — 对标 Claude Code Task.ts 状态机
291
+ *
292
+ * 管理后台任务的完整生命周期: pending → running → completed/failed/killed
293
+ * 支持进度追踪、超时控制、死信队列。
294
+ *
295
+ * 用法:
296
+ * ```ts
297
+ * const manager = new TaskLifecycleManager();
298
+ *
299
+ * const taskId = manager.submit({
300
+ * name: 'export-csv',
301
+ * handler: async (ctx) => {
302
+ * ctx.updateProgress(0, 'Starting...');
303
+ * for (const batch of batches) {
304
+ * await process(batch);
305
+ * ctx.updateProgress(++done / total);
306
+ * }
307
+ * return { file: outputPath };
308
+ * },
309
+ * timeoutMs: 60_000,
310
+ * maxRetries: 2,
311
+ * });
312
+ *
313
+ * const status = manager.getTask(taskId);
314
+ * ```
315
+ */
316
+ type TaskStatus = 'pending' | 'running' | 'completed' | 'failed' | 'killed';
317
+ interface TaskContext {
318
+ /** 更新任务进度 (0~1) */
319
+ updateProgress(progress: number, message?: string): void;
320
+ /** 检查任务是否被取消 */
321
+ isCancelled(): boolean;
322
+ /** 任务 ID */
323
+ readonly taskId: string;
324
+ }
325
+ interface TaskDefinition<T = unknown> {
326
+ name: string;
327
+ handler: (ctx: TaskContext) => Promise<T>;
328
+ timeoutMs?: number;
329
+ maxRetries?: number;
330
+ metadata?: Record<string, unknown>;
331
+ }
332
+ interface TaskInfo<T = unknown> {
333
+ id: string;
334
+ name: string;
335
+ status: TaskStatus;
336
+ progress: number;
337
+ progressMessage?: string;
338
+ result?: T;
339
+ error?: string;
340
+ createdAt: number;
341
+ startedAt?: number;
342
+ completedAt?: number;
343
+ attempts: number;
344
+ metadata?: Record<string, unknown>;
345
+ }
346
+ declare class TaskLifecycleManager {
347
+ private readonly logger;
348
+ private readonly tasks;
349
+ private readonly cancelledTasks;
350
+ private readonly deadLetterQueue;
351
+ private readonly maxDlqSize;
352
+ constructor(options?: {
353
+ maxDlqSize?: number;
354
+ });
355
+ /**
356
+ * 提交任务并异步执行
357
+ */
358
+ submit<T>(definition: TaskDefinition<T>): string;
359
+ /**
360
+ * 获取任务状态
361
+ */
362
+ getTask(id: string): TaskInfo | undefined;
363
+ /**
364
+ * 列出所有任务
365
+ */
366
+ listTasks(filter?: {
367
+ status?: TaskStatus;
368
+ }): TaskInfo[];
369
+ /**
370
+ * 取消任务
371
+ */
372
+ kill(id: string): boolean;
373
+ /**
374
+ * 获取死信队列中的失败任务
375
+ */
376
+ getDeadLetterQueue(): TaskInfo[];
377
+ /**
378
+ * 清理已完成的任务(释放内存)
379
+ */
380
+ cleanup(olderThanMs?: number): number;
381
+ private executeTask;
382
+ }
383
+
384
+ export { type BullMqConnectionFromUrlOptions, BullMqQueueEvents, type BullMqQueueEventsOptions, BullMqQueueProvider, type BullMqQueueProviderOptions, BullMqWorkerHost, type BullMqWorkerHostOptions, InMemoryQueue, type Job, type JobOptions, type JobProgress, QUEUE_PROVIDER, QUEUE_WORKER_KEY, type QueueCompletedEvent, type QueueEventHandlers, type QueueFailedEvent, type QueueJobHandler, type QueueModuleAsyncOptions, type QueueModuleOptions, type QueueModuleOptionsFactory, type QueueProgressEvent, type QueueProvider, QueueService, type QueueStateEvent, type QueueStats, QueueWorker, type QueueWorkerDefinition, type QueueWorkerHealth, type QueueWorkerJob, type QueueWorkerOptions, type TaskContext, type TaskDefinition, type TaskInfo, TaskLifecycleManager, type TaskStatus, ZuckerQueueModule, bullMqConnectionFromUrl };