@libeilong/mq 0.2.1 → 0.2.3

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/dist/index.d.mts CHANGED
@@ -60,7 +60,7 @@ declare abstract class BaseTask<D = any> {
60
60
  concurrency?: number;
61
61
  }): Promise<void>;
62
62
  start(opts: AddOptions$1<D> | FlowOptions$1<D, D>): Promise<Job$1<D> & {
63
- finished: () => Promise<any>;
63
+ finished: (timeoutMs?: number) => Promise<any>;
64
64
  }>;
65
65
  close(): Promise<void>;
66
66
  }
package/dist/index.d.ts CHANGED
@@ -60,7 +60,7 @@ declare abstract class BaseTask<D = any> {
60
60
  concurrency?: number;
61
61
  }): Promise<void>;
62
62
  start(opts: AddOptions$1<D> | FlowOptions$1<D, D>): Promise<Job$1<D> & {
63
- finished: () => Promise<any>;
63
+ finished: (timeoutMs?: number) => Promise<any>;
64
64
  }>;
65
65
  close(): Promise<void>;
66
66
  }
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`groupmq-plus`);c=s(c);var l=class extends Error{constructor(e,t){super(e),this.name=`TaskRetryLaterError`,this.customDelay=t}},u=class{get name(){return this.opts?.name||this.constructor.name}constructor(e,t){this.connection=e,this.opts=Object.assign({debug:!1,autoStart:!0,queueOptions:{},workerOptions:{}},t),this.opts.queueOptions=Object.assign({redis:e,namespace:this.name,keepCompleted:0,maxAttempts:3,jobTimeoutMs:5e3},this.opts.queueOptions),this.opts.workerOptions=Object.assign({concurrency:1,name:this.name},this.opts.workerOptions),this.opts.debug&&(this.opts.queueOptions.logger=!0,this.opts.workerOptions.logger=!0),this.queue=new c.Queue(this.opts.queueOptions),this.worker=new c.Worker({...this.opts.workerOptions,queue:this.queue,handler:async e=>this.handle(e,{token:e.id,retryLater:t=>{let n=e.attemptsMade,r=e.opts.attempts,i={};i=t instanceof Error?{error:t,message:t.message}:typeof t==`string`?{message:t}:t||{};let{error:a,delay:o}=i,s=i.message||(a instanceof Error?a.message:void 0)||`retry later`,c=a instanceof Error?a:void 0;if(n+1>=r)throw c||Error(s);let u=new l(s,o);throw c&&(u.stack=c.stack,u.cause=c),u},abort:e=>{throw new c.UnrecoverableError(e||`failed`)}}),backoff:(e,t)=>{if(t instanceof l&&typeof t.customDelay==`number`)return t.customDelay;let n=this.opts.workerOptions?.backoff;if(typeof n==`function`)return n(e,t);if(n&&typeof n==`object`){let{type:t,delay:r=1e3,jitter:i=0}=n,a;if(a=t===`fixed`?r:t===`exponential`?r*2**(e-1):1e3*2**(e-1),i>0){let e=a*i,t=Math.random()*e*2-e;a+=t}return Math.max(0,Math.round(a))}return 1e3*2**(e-1)}}),this.setupEventListeners()}setupEventListeners(){this.worker.on(`completed`,e=>{this.opts.debug&&console.log(`[COMPLETED] ${this.name}-${e.id} (Group: ${e.groupId})`),this.onCompleted(e)}),this.worker.on(`failed`,async e=>{let t=e.isFailed(),n=Error(e.failedReason||`task failed`);e.stacktrace&&(n.stack=e.stacktrace),this.opts.debug&&(t?console.error(`[FINAL FAILED] ${this.name}-${e.id}: ${n.message}`):console.log(`[RETRY] ${this.name}-${e.id}: ${n.message}`)),await this.onFailed(e,n),t&&await this.onFinalFailed(e,n)}),this.worker.on(`error`,e=>{this.opts.debug&&console.error(`[WORKER ERROR] ${this.name}`,e)})}async run(){return this.worker.run()}async onFailed(e,t){}async onFinalFailed(e,t){}async onCompleted(e){}setGroupConfig(e,t){return this.queue.groups.setConfig(e,t)}async start(e){let t;if(`children`in e&&Array.isArray(e.children)){if(!e.parent)throw Error(`Flow must include a parent job`);if(e.children.length===0)throw Error(`Flow must include at least one child job`);t=await this.queue.addFlow(e)}else t=await this.queue.add(e);return t.finished=async()=>t.waitUntilFinished(),t}async close(){await this.worker.close()}};exports.BaseTask=u,Object.defineProperty(exports,`Job`,{enumerable:!0,get:function(){return c.Job}}),Object.defineProperty(exports,`PriorityStrategy`,{enumerable:!0,get:function(){return c.PriorityStrategy}}),Object.defineProperty(exports,`Queue`,{enumerable:!0,get:function(){return c.Queue}}),exports.TaskRetryLaterError=l,Object.defineProperty(exports,`UnrecoverableError`,{enumerable:!0,get:function(){return c.UnrecoverableError}}),Object.defineProperty(exports,`Worker`,{enumerable:!0,get:function(){return c.Worker}});
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`groupmq-plus`);c=s(c);var l=class extends Error{constructor(e,t){super(e),this.name=`TaskRetryLaterError`,this.customDelay=t}},u=class{get name(){return this.opts?.name||this.constructor.name}constructor(e,t){this.connection=e,this.opts=Object.assign({debug:!1,autoStart:!0,queueOptions:{},workerOptions:{}},t),this.opts.queueOptions=Object.assign({redis:e,namespace:this.name,keepCompleted:0,maxAttempts:3,jobTimeoutMs:5e3},this.opts.queueOptions),this.opts.workerOptions=Object.assign({concurrency:1,name:this.name},this.opts.workerOptions),this.queue=new c.Queue(this.opts.queueOptions),this.worker=new c.Worker({...this.opts.workerOptions,autoStart:this.opts.autoStart,queue:this.queue,handler:async e=>this.handle(e,{token:e.token,retryLater:t=>{let n=e.attemptsMade,r=e.opts.attempts,i={};i=t instanceof Error?{error:t,message:t.message}:typeof t==`string`?{message:t}:t||{};let{error:a,delay:o}=i,s=i.message||(a instanceof Error?a.message:void 0)||`retry later`,c=a instanceof Error?a:void 0;if(n+1>=r)throw c||Error(s);let u=new l(s,o);throw c&&(u.stack=c.stack,u.cause=c),u},abort:e=>{throw new c.UnrecoverableError(e||`failed`)}}),backoff:(e,t)=>{if(t instanceof l&&typeof t.customDelay==`number`)return t.customDelay;let n=this.opts.workerOptions?.backoff;if(typeof n==`function`)return n(e,t);if(n&&typeof n==`object`){let{type:t,delay:r=1e3,jitter:i=0}=n,a;if(a=t===`fixed`?r:t===`exponential`?r*2**(e-1):1e3*2**(e-1),i>0){let e=a*i,t=Math.random()*e*2-e;a+=t}return Math.max(0,Math.round(a))}return 1e3*2**(e-1)}}),this.setupEventListeners()}setupEventListeners(){this.worker.on(`completed`,e=>{this.opts.debug&&console.log(`[COMPLETED] ${this.name}-${e.id} (Group: ${e.groupId})`),this.onCompleted(e)}),this.worker.on(`failed`,async e=>{let t=e.isFailed(),n=Error(e.failedReason||`task failed`);e.stacktrace&&(n.stack=e.stacktrace),this.opts.debug&&(t?console.error(`[FINAL FAILED] ${this.name}-${e.id}: ${n.message}`):console.log(`[RETRY] ${this.name}-${e.id}: ${n.message}`)),await this.onFailed(e,n),t&&await this.onFinalFailed(e,n)}),this.worker.on(`error`,e=>{this.opts.debug&&console.error(`[WORKER ERROR] ${this.name}`,e)})}async run(){return this.worker.run()}async onFailed(e,t){}async onFinalFailed(e,t){}async onCompleted(e){}setGroupConfig(e,t){return this.queue.groups.setConfig(e,t)}async start(e){let t;if(`children`in e&&Array.isArray(e.children)){if(!e.parent)throw Error(`Flow must include a parent job`);if(e.children.length===0)throw Error(`Flow must include at least one child job`);t=await this.queue.addFlow(e)}else t=await this.queue.add(e);return t.finished=async e=>t.waitUntilFinished(e),t}async close(){await this.worker.close()}};exports.BaseTask=u,Object.defineProperty(exports,`Job`,{enumerable:!0,get:function(){return c.Job}}),Object.defineProperty(exports,`PriorityStrategy`,{enumerable:!0,get:function(){return c.PriorityStrategy}}),Object.defineProperty(exports,`Queue`,{enumerable:!0,get:function(){return c.Queue}}),exports.TaskRetryLaterError=l,Object.defineProperty(exports,`UnrecoverableError`,{enumerable:!0,get:function(){return c.UnrecoverableError}}),Object.defineProperty(exports,`Worker`,{enumerable:!0,get:function(){return c.Worker}});
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["connection: IORedis","Queue","Worker","options: RetryOptions","UnrecoverableError","baseDelay: number","job: Job<D>"],"sources":["../src/BaseTask.ts"],"sourcesContent":["import {\n AddOptions,\n FlowJob,\n FlowOptions,\n GroupOptions,\n Job,\n Queue,\n QueueOptions,\n UnrecoverableError,\n Worker,\n WorkerOptions,\n} from 'groupmq-plus'\nimport IORedis from 'ioredis'\n\nexport type { FlowChildResult } from 'groupmq-plus'\n\nexport interface BackoffOptions {\n /** 延迟策略:固定间隔、指数递增 */\n type: 'fixed' | 'exponential'\n /** 延迟时间为毫秒 */\n delay?: number\n /**\n * 添加到延迟中的随机抖动比例,取值范围为 0 到 1 之间的小数。\n * 抖动用于增加随机性,以防止因多个任务同时重试而导致的惊群效应。\n * 最终的延迟时间将在 `delay ± (delay * jitter)` 的范围内随机波动。\n * @defaultValue 0\n * @example 0.1 // 为延迟添加 ±10% 的随机抖动\n * @example 0.25 // 为延迟添加 ±25% 的随机抖动\n */\n jitter?: number\n}\n\nexport interface RetryOptions {\n error?: Error | unknown\n message?: string\n delay?: number\n}\n\nexport interface HandleOptions {\n token: string\n retryLater(options?: RetryOptions): void\n retryLater(errorOrMessage?: Error | string): void\n retryLater(arg?: RetryOptions | Error | string): void\n abort(message?: string): void\n}\n\nexport interface BaseTaskOptions {\n name?: string\n autoStart?: boolean\n queueOptions?: Partial<QueueOptions>\n workerOptions?: Omit<Partial<WorkerOptions<any>>, 'backoff'> & {\n backoff?: BackoffOptions | ((attempt: number, error: unknown) => number)\n }\n debug?: boolean\n}\n\n/**\n * 任务启动选项,用于单个任务或 Flow 中的子任务\n */\nexport type TaskStartOptions<D> = {\n groupId: string\n data: D\n jobId?: string\n delay?: number\n groupConfig?: GroupOptions\n} & Omit<AddOptions<D>, 'groupId' | 'data' | 'groupConfig'>\n\n/**\n * Flow 任务选项\n */\nexport type TaskFlowOptions<D> = {\n groupId: string\n data: D\n jobId?: string\n groupConfig?: GroupOptions\n children: Array<\n {\n groupId: string\n data: D\n jobId?: string\n groupConfig?: GroupOptions\n } & Omit<FlowJob<D>, 'groupId' | 'data'>\n >\n} & Omit<FlowJob<D>, 'groupId' | 'data'>\n\nexport class TaskRetryLaterError extends Error {\n public customDelay?: number\n\n constructor(message?: string, delay?: number) {\n super(message)\n this.name = 'TaskRetryLaterError'\n this.customDelay = delay\n }\n}\n\nexport abstract class BaseTask<D = any> {\n public queue: Queue<D>\n public worker: Worker<D>\n protected opts: BaseTaskOptions\n\n get name() {\n return this.opts?.name || this.constructor.name\n }\n\n constructor(protected connection: IORedis, opts?: Partial<BaseTaskOptions>) {\n this.opts = Object.assign(\n {\n debug: false,\n autoStart: true,\n queueOptions: {},\n workerOptions: {},\n },\n opts,\n )\n\n this.opts.queueOptions = Object.assign(\n {\n redis: connection,\n namespace: this.name,\n keepCompleted: 0,\n maxAttempts: 3,\n jobTimeoutMs: 5000,\n },\n this.opts.queueOptions,\n )\n\n this.opts.workerOptions = Object.assign(\n {\n concurrency: 1,\n name: this.name,\n },\n this.opts.workerOptions,\n )\n\n if (this.opts.debug) {\n this.opts.queueOptions.logger = true\n this.opts.workerOptions.logger = true\n }\n\n this.queue = new Queue<D>(this.opts.queueOptions as QueueOptions)\n\n this.worker = new Worker<D>({\n ...(this.opts.workerOptions as WorkerOptions<D>),\n queue: this.queue,\n handler: async (job) => {\n return this.handle(job, {\n token: job.id,\n retryLater: (arg: RetryOptions | Error | string) => {\n const currentAttempts = job.attemptsMade\n const maxAttempts = job.opts.attempts\n\n let options: RetryOptions = {}\n if (arg instanceof Error) {\n options = { error: arg, message: arg.message }\n } else if (typeof arg === 'string') {\n options = { message: arg }\n } else {\n options = arg || {}\n }\n\n const { error, delay } = options\n const message = options.message || (error instanceof Error ? error.message : undefined) || 'retry later'\n const errorObj = error instanceof Error ? error : undefined\n\n if (currentAttempts + 1 >= maxAttempts) {\n if (errorObj) throw errorObj\n throw new Error(message)\n }\n\n const retryErr = new TaskRetryLaterError(message, delay)\n if (errorObj) {\n retryErr.stack = errorObj.stack\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore - preserve cause on older runtimes\n retryErr.cause = errorObj\n }\n throw retryErr\n },\n abort: (message?: string) => {\n throw new UnrecoverableError(message || 'failed')\n },\n })\n },\n backoff: (attempt: number, error: unknown) => {\n // 优先使用 TaskRetryLaterError 的 customDelay\n if (error instanceof TaskRetryLaterError && typeof error.customDelay === 'number') {\n return error.customDelay\n }\n\n const backoffConfig = this.opts.workerOptions?.backoff\n\n // 使用自定义 backoff 函数\n if (typeof backoffConfig === 'function') {\n return backoffConfig(attempt, error)\n }\n\n // 使用 BackoffOptions 配置\n if (backoffConfig && typeof backoffConfig === 'object') {\n const { type, delay = 1000, jitter = 0 } = backoffConfig\n let baseDelay: number\n\n if (type === 'fixed') {\n baseDelay = delay\n } else if (type === 'exponential') {\n baseDelay = delay * Math.pow(2, attempt - 1)\n } else {\n // 不支持的 type,使用默认指数退避\n baseDelay = 1000 * Math.pow(2, attempt - 1)\n }\n\n // 应用 jitter(抖动):确保结果为正整数\n if (jitter > 0) {\n const jitterAmount = baseDelay * jitter\n const randomJitter = Math.random() * jitterAmount * 2 - jitterAmount\n baseDelay = baseDelay + randomJitter\n }\n\n return Math.max(0, Math.round(baseDelay))\n }\n\n // 默认指数退避策略\n return 1000 * Math.pow(2, attempt - 1)\n },\n })\n\n this.setupEventListeners()\n }\n\n private setupEventListeners() {\n this.worker.on('completed', (job) => {\n if (this.opts.debug) {\n console.log(`[COMPLETED] ${this.name}-${job.id} (Group: ${job.groupId})`)\n }\n this.onCompleted(job)\n })\n\n this.worker.on('failed', async (job) => {\n const isFinalFailure = job.isFailed()\n const error = new Error(job.failedReason || 'task failed')\n if (job.stacktrace) {\n error.stack = job.stacktrace\n }\n\n if (this.opts.debug) {\n if (!isFinalFailure) {\n console.log(`[RETRY] ${this.name}-${job.id}: ${error.message}`)\n } else {\n console.error(`[FINAL FAILED] ${this.name}-${job.id}: ${error.message}`)\n }\n }\n\n await this.onFailed(job, error)\n\n if (isFinalFailure) {\n await this.onFinalFailed(job, error)\n }\n })\n\n this.worker.on('error', (err) => {\n if (this.opts.debug) {\n console.error(`[WORKER ERROR] ${this.name}`, err)\n }\n })\n }\n\n async run() {\n return this.worker.run()\n }\n\n abstract handle(job: Job<D>, opts: HandleOptions): Promise<any>\n\n async onFailed(job: Job<D>, error: Error) {}\n async onFinalFailed(job: Job<D>, error: Error) {}\n async onCompleted(job: Job<D>) {}\n\n setGroupConfig(groupId: string, config: { priority?: number; concurrency?: number }) {\n return this.queue.groups.setConfig(groupId, config)\n }\n\n async start(opts: AddOptions<D> | FlowOptions<D, D>) {\n let job: Job<D>\n\n // 检查是否为 Flow (包含 children)\n if ('children' in opts && Array.isArray(opts.children)) {\n if (!opts.parent) {\n throw new Error('Flow must include a parent job')\n }\n\n if (opts.children.length === 0) {\n throw new Error('Flow must include at least one child job')\n }\n\n job = await this.queue.addFlow(opts)\n } else {\n job = await this.queue.add(opts as AddOptions<D>)\n }\n\n // provide a BullMQ-like finished helper\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n job['finished'] = async () => {\n return job.waitUntilFinished()\n }\n\n return job as Job<D> & { finished: () => Promise<any> }\n }\n\n async close() {\n await this.worker.close()\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["connection: IORedis","Queue","Worker","options: RetryOptions","UnrecoverableError","baseDelay: number","job: Job<D>"],"sources":["../src/BaseTask.ts"],"sourcesContent":["import {\n AddOptions,\n FlowJob,\n FlowOptions,\n GroupOptions,\n Job,\n Queue,\n QueueOptions,\n UnrecoverableError,\n Worker,\n WorkerOptions,\n} from 'groupmq-plus'\nimport IORedis from 'ioredis'\n\nexport type { FlowChildResult } from 'groupmq-plus'\n\nexport interface BackoffOptions {\n /** 延迟策略:固定间隔、指数递增 */\n type: 'fixed' | 'exponential'\n /** 延迟时间为毫秒 */\n delay?: number\n /**\n * 添加到延迟中的随机抖动比例,取值范围为 0 到 1 之间的小数。\n * 抖动用于增加随机性,以防止因多个任务同时重试而导致的惊群效应。\n * 最终的延迟时间将在 `delay ± (delay * jitter)` 的范围内随机波动。\n * @defaultValue 0\n * @example 0.1 // 为延迟添加 ±10% 的随机抖动\n * @example 0.25 // 为延迟添加 ±25% 的随机抖动\n */\n jitter?: number\n}\n\nexport interface RetryOptions {\n error?: Error | unknown\n message?: string\n delay?: number\n}\n\nexport interface HandleOptions {\n token: string\n retryLater(options?: RetryOptions): void\n retryLater(errorOrMessage?: Error | string): void\n retryLater(arg?: RetryOptions | Error | string): void\n abort(message?: string): void\n}\n\nexport interface BaseTaskOptions {\n name?: string\n autoStart?: boolean\n queueOptions?: Partial<QueueOptions>\n workerOptions?: Omit<Partial<WorkerOptions<any>>, 'backoff'> & {\n backoff?: BackoffOptions | ((attempt: number, error: unknown) => number)\n }\n debug?: boolean\n}\n\n/**\n * 任务启动选项,用于单个任务或 Flow 中的子任务\n */\nexport type TaskStartOptions<D> = {\n groupId: string\n data: D\n jobId?: string\n delay?: number\n groupConfig?: GroupOptions\n} & Omit<AddOptions<D>, 'groupId' | 'data' | 'groupConfig'>\n\n/**\n * Flow 任务选项\n */\nexport type TaskFlowOptions<D> = {\n groupId: string\n data: D\n jobId?: string\n groupConfig?: GroupOptions\n children: Array<\n {\n groupId: string\n data: D\n jobId?: string\n groupConfig?: GroupOptions\n } & Omit<FlowJob<D>, 'groupId' | 'data'>\n >\n} & Omit<FlowJob<D>, 'groupId' | 'data'>\n\nexport class TaskRetryLaterError extends Error {\n public customDelay?: number\n\n constructor(message?: string, delay?: number) {\n super(message)\n this.name = 'TaskRetryLaterError'\n this.customDelay = delay\n }\n}\n\nexport abstract class BaseTask<D = any> {\n public queue: Queue<D>\n public worker: Worker<D>\n protected opts: BaseTaskOptions\n\n get name() {\n return this.opts?.name || this.constructor.name\n }\n\n constructor(protected connection: IORedis, opts?: Partial<BaseTaskOptions>) {\n this.opts = Object.assign(\n {\n debug: false,\n autoStart: true,\n queueOptions: {},\n workerOptions: {},\n },\n opts,\n )\n\n this.opts.queueOptions = Object.assign(\n {\n redis: connection,\n namespace: this.name,\n keepCompleted: 0,\n maxAttempts: 3,\n jobTimeoutMs: 5000,\n },\n this.opts.queueOptions,\n )\n\n this.opts.workerOptions = Object.assign(\n {\n concurrency: 1,\n name: this.name,\n },\n this.opts.workerOptions,\n )\n\n this.queue = new Queue<D>(this.opts.queueOptions as QueueOptions)\n\n this.worker = new Worker<D>({\n ...(this.opts.workerOptions as WorkerOptions<D>),\n autoStart: this.opts.autoStart,\n queue: this.queue,\n handler: async (job) => {\n return this.handle(job, {\n token: job.token!,\n retryLater: (arg: RetryOptions | Error | string) => {\n const currentAttempts = job.attemptsMade\n const maxAttempts = job.opts.attempts\n\n let options: RetryOptions = {}\n if (arg instanceof Error) {\n options = { error: arg, message: arg.message }\n } else if (typeof arg === 'string') {\n options = { message: arg }\n } else {\n options = arg || {}\n }\n\n const { error, delay } = options\n const message = options.message || (error instanceof Error ? error.message : undefined) || 'retry later'\n const errorObj = error instanceof Error ? error : undefined\n\n // 这里的检查是为了在最后一次尝试失败时,直接抛出原始 Error 对象\n // 这样 Redis 中的 failedName 将记录为原始错误类型(如 TypeError),而非 TaskRetryLaterError\n if (currentAttempts + 1 >= maxAttempts) {\n if (errorObj) throw errorObj\n throw new Error(message)\n }\n\n const retryErr = new TaskRetryLaterError(message, delay)\n if (errorObj) {\n retryErr.stack = errorObj.stack\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore - preserve cause on older runtimes\n retryErr.cause = errorObj\n }\n throw retryErr\n },\n abort: (message?: string) => {\n throw new UnrecoverableError(message || 'failed')\n },\n })\n },\n backoff: (attempt: number, error: unknown) => {\n // 优先使用 TaskRetryLaterError 的 customDelay\n if (error instanceof TaskRetryLaterError && typeof error.customDelay === 'number') {\n return error.customDelay\n }\n\n const backoffConfig = this.opts.workerOptions?.backoff\n\n // 使用自定义 backoff 函数\n if (typeof backoffConfig === 'function') {\n return backoffConfig(attempt, error)\n }\n\n // 使用 BackoffOptions 配置\n if (backoffConfig && typeof backoffConfig === 'object') {\n const { type, delay = 1000, jitter = 0 } = backoffConfig\n let baseDelay: number\n\n if (type === 'fixed') {\n baseDelay = delay\n } else if (type === 'exponential') {\n baseDelay = delay * Math.pow(2, attempt - 1)\n } else {\n // 不支持的 type,使用默认指数退避\n baseDelay = 1000 * Math.pow(2, attempt - 1)\n }\n\n // 应用 jitter(抖动):确保结果为正整数\n if (jitter > 0) {\n const jitterAmount = baseDelay * jitter\n const randomJitter = Math.random() * jitterAmount * 2 - jitterAmount\n baseDelay = baseDelay + randomJitter\n }\n\n return Math.max(0, Math.round(baseDelay))\n }\n\n // 默认指数退避策略\n return 1000 * Math.pow(2, attempt - 1)\n },\n })\n\n this.setupEventListeners()\n }\n\n private setupEventListeners() {\n this.worker.on('completed', (job) => {\n if (this.opts.debug) {\n console.log(`[COMPLETED] ${this.name}-${job.id} (Group: ${job.groupId})`)\n }\n this.onCompleted(job)\n })\n\n this.worker.on('failed', async (job) => {\n const isFinalFailure = job.isFailed()\n const error = new Error(job.failedReason || 'task failed')\n if (job.stacktrace) {\n error.stack = job.stacktrace\n }\n\n if (this.opts.debug) {\n if (!isFinalFailure) {\n console.log(`[RETRY] ${this.name}-${job.id}: ${error.message}`)\n } else {\n console.error(`[FINAL FAILED] ${this.name}-${job.id}: ${error.message}`)\n }\n }\n\n await this.onFailed(job, error)\n\n if (isFinalFailure) {\n await this.onFinalFailed(job, error)\n }\n })\n\n this.worker.on('error', (err) => {\n if (this.opts.debug) {\n console.error(`[WORKER ERROR] ${this.name}`, err)\n }\n })\n }\n\n async run() {\n return this.worker.run()\n }\n\n abstract handle(job: Job<D>, opts: HandleOptions): Promise<any>\n\n async onFailed(job: Job<D>, error: Error) {}\n async onFinalFailed(job: Job<D>, error: Error) {}\n async onCompleted(job: Job<D>) {}\n\n setGroupConfig(groupId: string, config: { priority?: number; concurrency?: number }) {\n return this.queue.groups.setConfig(groupId, config)\n }\n\n async start(opts: AddOptions<D> | FlowOptions<D, D>) {\n let job: Job<D>\n\n // 检查是否为 Flow (包含 children)\n if ('children' in opts && Array.isArray(opts.children)) {\n if (!opts.parent) {\n throw new Error('Flow must include a parent job')\n }\n\n if (opts.children.length === 0) {\n throw new Error('Flow must include at least one child job')\n }\n\n job = await this.queue.addFlow(opts)\n } else {\n job = await this.queue.add(opts as AddOptions<D>)\n }\n\n // provide a BullMQ-like finished helper\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n job['finished'] = async (timeoutMs?: number) => {\n return job.waitUntilFinished(timeoutMs)\n }\n\n return job as Job<D> & { finished: (timeoutMs?: number) => Promise<any> }\n }\n\n async close() {\n await this.worker.close()\n }\n}\n"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{Job as e,PriorityStrategy as t,Queue as n,Queue as r,UnrecoverableError as i,UnrecoverableError as a,Worker as o,Worker as s}from"groupmq-plus";var c=class extends Error{constructor(e,t){super(e),this.name=`TaskRetryLaterError`,this.customDelay=t}},l=class{get name(){return this.opts?.name||this.constructor.name}constructor(e,t){this.connection=e,this.opts=Object.assign({debug:!1,autoStart:!0,queueOptions:{},workerOptions:{}},t),this.opts.queueOptions=Object.assign({redis:e,namespace:this.name,keepCompleted:0,maxAttempts:3,jobTimeoutMs:5e3},this.opts.queueOptions),this.opts.workerOptions=Object.assign({concurrency:1,name:this.name},this.opts.workerOptions),this.opts.debug&&(this.opts.queueOptions.logger=!0,this.opts.workerOptions.logger=!0),this.queue=new r(this.opts.queueOptions),this.worker=new s({...this.opts.workerOptions,queue:this.queue,handler:async e=>this.handle(e,{token:e.id,retryLater:t=>{let n=e.attemptsMade,r=e.opts.attempts,i={};i=t instanceof Error?{error:t,message:t.message}:typeof t==`string`?{message:t}:t||{};let{error:a,delay:o}=i,s=i.message||(a instanceof Error?a.message:void 0)||`retry later`,l=a instanceof Error?a:void 0;if(n+1>=r)throw l||Error(s);let u=new c(s,o);throw l&&(u.stack=l.stack,u.cause=l),u},abort:e=>{throw new a(e||`failed`)}}),backoff:(e,t)=>{if(t instanceof c&&typeof t.customDelay==`number`)return t.customDelay;let n=this.opts.workerOptions?.backoff;if(typeof n==`function`)return n(e,t);if(n&&typeof n==`object`){let{type:t,delay:r=1e3,jitter:i=0}=n,a;if(a=t===`fixed`?r:t===`exponential`?r*2**(e-1):1e3*2**(e-1),i>0){let e=a*i,t=Math.random()*e*2-e;a+=t}return Math.max(0,Math.round(a))}return 1e3*2**(e-1)}}),this.setupEventListeners()}setupEventListeners(){this.worker.on(`completed`,e=>{this.opts.debug&&console.log(`[COMPLETED] ${this.name}-${e.id} (Group: ${e.groupId})`),this.onCompleted(e)}),this.worker.on(`failed`,async e=>{let t=e.isFailed(),n=Error(e.failedReason||`task failed`);e.stacktrace&&(n.stack=e.stacktrace),this.opts.debug&&(t?console.error(`[FINAL FAILED] ${this.name}-${e.id}: ${n.message}`):console.log(`[RETRY] ${this.name}-${e.id}: ${n.message}`)),await this.onFailed(e,n),t&&await this.onFinalFailed(e,n)}),this.worker.on(`error`,e=>{this.opts.debug&&console.error(`[WORKER ERROR] ${this.name}`,e)})}async run(){return this.worker.run()}async onFailed(e,t){}async onFinalFailed(e,t){}async onCompleted(e){}setGroupConfig(e,t){return this.queue.groups.setConfig(e,t)}async start(e){let t;if(`children`in e&&Array.isArray(e.children)){if(!e.parent)throw Error(`Flow must include a parent job`);if(e.children.length===0)throw Error(`Flow must include at least one child job`);t=await this.queue.addFlow(e)}else t=await this.queue.add(e);return t.finished=async()=>t.waitUntilFinished(),t}async close(){await this.worker.close()}};export{l as BaseTask,e as Job,t as PriorityStrategy,n as Queue,c as TaskRetryLaterError,i as UnrecoverableError,o as Worker};
1
+ import{Job as e,PriorityStrategy as t,Queue as n,Queue as r,UnrecoverableError as i,UnrecoverableError as a,Worker as o,Worker as s}from"groupmq-plus";var c=class extends Error{constructor(e,t){super(e),this.name=`TaskRetryLaterError`,this.customDelay=t}},l=class{get name(){return this.opts?.name||this.constructor.name}constructor(e,t){this.connection=e,this.opts=Object.assign({debug:!1,autoStart:!0,queueOptions:{},workerOptions:{}},t),this.opts.queueOptions=Object.assign({redis:e,namespace:this.name,keepCompleted:0,maxAttempts:3,jobTimeoutMs:5e3},this.opts.queueOptions),this.opts.workerOptions=Object.assign({concurrency:1,name:this.name},this.opts.workerOptions),this.queue=new r(this.opts.queueOptions),this.worker=new s({...this.opts.workerOptions,autoStart:this.opts.autoStart,queue:this.queue,handler:async e=>this.handle(e,{token:e.token,retryLater:t=>{let n=e.attemptsMade,r=e.opts.attempts,i={};i=t instanceof Error?{error:t,message:t.message}:typeof t==`string`?{message:t}:t||{};let{error:a,delay:o}=i,s=i.message||(a instanceof Error?a.message:void 0)||`retry later`,l=a instanceof Error?a:void 0;if(n+1>=r)throw l||Error(s);let u=new c(s,o);throw l&&(u.stack=l.stack,u.cause=l),u},abort:e=>{throw new a(e||`failed`)}}),backoff:(e,t)=>{if(t instanceof c&&typeof t.customDelay==`number`)return t.customDelay;let n=this.opts.workerOptions?.backoff;if(typeof n==`function`)return n(e,t);if(n&&typeof n==`object`){let{type:t,delay:r=1e3,jitter:i=0}=n,a;if(a=t===`fixed`?r:t===`exponential`?r*2**(e-1):1e3*2**(e-1),i>0){let e=a*i,t=Math.random()*e*2-e;a+=t}return Math.max(0,Math.round(a))}return 1e3*2**(e-1)}}),this.setupEventListeners()}setupEventListeners(){this.worker.on(`completed`,e=>{this.opts.debug&&console.log(`[COMPLETED] ${this.name}-${e.id} (Group: ${e.groupId})`),this.onCompleted(e)}),this.worker.on(`failed`,async e=>{let t=e.isFailed(),n=Error(e.failedReason||`task failed`);e.stacktrace&&(n.stack=e.stacktrace),this.opts.debug&&(t?console.error(`[FINAL FAILED] ${this.name}-${e.id}: ${n.message}`):console.log(`[RETRY] ${this.name}-${e.id}: ${n.message}`)),await this.onFailed(e,n),t&&await this.onFinalFailed(e,n)}),this.worker.on(`error`,e=>{this.opts.debug&&console.error(`[WORKER ERROR] ${this.name}`,e)})}async run(){return this.worker.run()}async onFailed(e,t){}async onFinalFailed(e,t){}async onCompleted(e){}setGroupConfig(e,t){return this.queue.groups.setConfig(e,t)}async start(e){let t;if(`children`in e&&Array.isArray(e.children)){if(!e.parent)throw Error(`Flow must include a parent job`);if(e.children.length===0)throw Error(`Flow must include at least one child job`);t=await this.queue.addFlow(e)}else t=await this.queue.add(e);return t.finished=async e=>t.waitUntilFinished(e),t}async close(){await this.worker.close()}};export{l as BaseTask,e as Job,t as PriorityStrategy,n as Queue,c as TaskRetryLaterError,i as UnrecoverableError,o as Worker};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["connection: IORedis","Queue","Worker","options: RetryOptions","UnrecoverableError","baseDelay: number","job: Job<D>"],"sources":["../src/BaseTask.ts"],"sourcesContent":["import {\n AddOptions,\n FlowJob,\n FlowOptions,\n GroupOptions,\n Job,\n Queue,\n QueueOptions,\n UnrecoverableError,\n Worker,\n WorkerOptions,\n} from 'groupmq-plus'\nimport IORedis from 'ioredis'\n\nexport type { FlowChildResult } from 'groupmq-plus'\n\nexport interface BackoffOptions {\n /** 延迟策略:固定间隔、指数递增 */\n type: 'fixed' | 'exponential'\n /** 延迟时间为毫秒 */\n delay?: number\n /**\n * 添加到延迟中的随机抖动比例,取值范围为 0 到 1 之间的小数。\n * 抖动用于增加随机性,以防止因多个任务同时重试而导致的惊群效应。\n * 最终的延迟时间将在 `delay ± (delay * jitter)` 的范围内随机波动。\n * @defaultValue 0\n * @example 0.1 // 为延迟添加 ±10% 的随机抖动\n * @example 0.25 // 为延迟添加 ±25% 的随机抖动\n */\n jitter?: number\n}\n\nexport interface RetryOptions {\n error?: Error | unknown\n message?: string\n delay?: number\n}\n\nexport interface HandleOptions {\n token: string\n retryLater(options?: RetryOptions): void\n retryLater(errorOrMessage?: Error | string): void\n retryLater(arg?: RetryOptions | Error | string): void\n abort(message?: string): void\n}\n\nexport interface BaseTaskOptions {\n name?: string\n autoStart?: boolean\n queueOptions?: Partial<QueueOptions>\n workerOptions?: Omit<Partial<WorkerOptions<any>>, 'backoff'> & {\n backoff?: BackoffOptions | ((attempt: number, error: unknown) => number)\n }\n debug?: boolean\n}\n\n/**\n * 任务启动选项,用于单个任务或 Flow 中的子任务\n */\nexport type TaskStartOptions<D> = {\n groupId: string\n data: D\n jobId?: string\n delay?: number\n groupConfig?: GroupOptions\n} & Omit<AddOptions<D>, 'groupId' | 'data' | 'groupConfig'>\n\n/**\n * Flow 任务选项\n */\nexport type TaskFlowOptions<D> = {\n groupId: string\n data: D\n jobId?: string\n groupConfig?: GroupOptions\n children: Array<\n {\n groupId: string\n data: D\n jobId?: string\n groupConfig?: GroupOptions\n } & Omit<FlowJob<D>, 'groupId' | 'data'>\n >\n} & Omit<FlowJob<D>, 'groupId' | 'data'>\n\nexport class TaskRetryLaterError extends Error {\n public customDelay?: number\n\n constructor(message?: string, delay?: number) {\n super(message)\n this.name = 'TaskRetryLaterError'\n this.customDelay = delay\n }\n}\n\nexport abstract class BaseTask<D = any> {\n public queue: Queue<D>\n public worker: Worker<D>\n protected opts: BaseTaskOptions\n\n get name() {\n return this.opts?.name || this.constructor.name\n }\n\n constructor(protected connection: IORedis, opts?: Partial<BaseTaskOptions>) {\n this.opts = Object.assign(\n {\n debug: false,\n autoStart: true,\n queueOptions: {},\n workerOptions: {},\n },\n opts,\n )\n\n this.opts.queueOptions = Object.assign(\n {\n redis: connection,\n namespace: this.name,\n keepCompleted: 0,\n maxAttempts: 3,\n jobTimeoutMs: 5000,\n },\n this.opts.queueOptions,\n )\n\n this.opts.workerOptions = Object.assign(\n {\n concurrency: 1,\n name: this.name,\n },\n this.opts.workerOptions,\n )\n\n if (this.opts.debug) {\n this.opts.queueOptions.logger = true\n this.opts.workerOptions.logger = true\n }\n\n this.queue = new Queue<D>(this.opts.queueOptions as QueueOptions)\n\n this.worker = new Worker<D>({\n ...(this.opts.workerOptions as WorkerOptions<D>),\n queue: this.queue,\n handler: async (job) => {\n return this.handle(job, {\n token: job.id,\n retryLater: (arg: RetryOptions | Error | string) => {\n const currentAttempts = job.attemptsMade\n const maxAttempts = job.opts.attempts\n\n let options: RetryOptions = {}\n if (arg instanceof Error) {\n options = { error: arg, message: arg.message }\n } else if (typeof arg === 'string') {\n options = { message: arg }\n } else {\n options = arg || {}\n }\n\n const { error, delay } = options\n const message = options.message || (error instanceof Error ? error.message : undefined) || 'retry later'\n const errorObj = error instanceof Error ? error : undefined\n\n if (currentAttempts + 1 >= maxAttempts) {\n if (errorObj) throw errorObj\n throw new Error(message)\n }\n\n const retryErr = new TaskRetryLaterError(message, delay)\n if (errorObj) {\n retryErr.stack = errorObj.stack\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore - preserve cause on older runtimes\n retryErr.cause = errorObj\n }\n throw retryErr\n },\n abort: (message?: string) => {\n throw new UnrecoverableError(message || 'failed')\n },\n })\n },\n backoff: (attempt: number, error: unknown) => {\n // 优先使用 TaskRetryLaterError 的 customDelay\n if (error instanceof TaskRetryLaterError && typeof error.customDelay === 'number') {\n return error.customDelay\n }\n\n const backoffConfig = this.opts.workerOptions?.backoff\n\n // 使用自定义 backoff 函数\n if (typeof backoffConfig === 'function') {\n return backoffConfig(attempt, error)\n }\n\n // 使用 BackoffOptions 配置\n if (backoffConfig && typeof backoffConfig === 'object') {\n const { type, delay = 1000, jitter = 0 } = backoffConfig\n let baseDelay: number\n\n if (type === 'fixed') {\n baseDelay = delay\n } else if (type === 'exponential') {\n baseDelay = delay * Math.pow(2, attempt - 1)\n } else {\n // 不支持的 type,使用默认指数退避\n baseDelay = 1000 * Math.pow(2, attempt - 1)\n }\n\n // 应用 jitter(抖动):确保结果为正整数\n if (jitter > 0) {\n const jitterAmount = baseDelay * jitter\n const randomJitter = Math.random() * jitterAmount * 2 - jitterAmount\n baseDelay = baseDelay + randomJitter\n }\n\n return Math.max(0, Math.round(baseDelay))\n }\n\n // 默认指数退避策略\n return 1000 * Math.pow(2, attempt - 1)\n },\n })\n\n this.setupEventListeners()\n }\n\n private setupEventListeners() {\n this.worker.on('completed', (job) => {\n if (this.opts.debug) {\n console.log(`[COMPLETED] ${this.name}-${job.id} (Group: ${job.groupId})`)\n }\n this.onCompleted(job)\n })\n\n this.worker.on('failed', async (job) => {\n const isFinalFailure = job.isFailed()\n const error = new Error(job.failedReason || 'task failed')\n if (job.stacktrace) {\n error.stack = job.stacktrace\n }\n\n if (this.opts.debug) {\n if (!isFinalFailure) {\n console.log(`[RETRY] ${this.name}-${job.id}: ${error.message}`)\n } else {\n console.error(`[FINAL FAILED] ${this.name}-${job.id}: ${error.message}`)\n }\n }\n\n await this.onFailed(job, error)\n\n if (isFinalFailure) {\n await this.onFinalFailed(job, error)\n }\n })\n\n this.worker.on('error', (err) => {\n if (this.opts.debug) {\n console.error(`[WORKER ERROR] ${this.name}`, err)\n }\n })\n }\n\n async run() {\n return this.worker.run()\n }\n\n abstract handle(job: Job<D>, opts: HandleOptions): Promise<any>\n\n async onFailed(job: Job<D>, error: Error) {}\n async onFinalFailed(job: Job<D>, error: Error) {}\n async onCompleted(job: Job<D>) {}\n\n setGroupConfig(groupId: string, config: { priority?: number; concurrency?: number }) {\n return this.queue.groups.setConfig(groupId, config)\n }\n\n async start(opts: AddOptions<D> | FlowOptions<D, D>) {\n let job: Job<D>\n\n // 检查是否为 Flow (包含 children)\n if ('children' in opts && Array.isArray(opts.children)) {\n if (!opts.parent) {\n throw new Error('Flow must include a parent job')\n }\n\n if (opts.children.length === 0) {\n throw new Error('Flow must include at least one child job')\n }\n\n job = await this.queue.addFlow(opts)\n } else {\n job = await this.queue.add(opts as AddOptions<D>)\n }\n\n // provide a BullMQ-like finished helper\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n job['finished'] = async () => {\n return job.waitUntilFinished()\n }\n\n return job as Job<D> & { finished: () => Promise<any> }\n }\n\n async close() {\n await this.worker.close()\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["connection: IORedis","Queue","Worker","options: RetryOptions","UnrecoverableError","baseDelay: number","job: Job<D>"],"sources":["../src/BaseTask.ts"],"sourcesContent":["import {\n AddOptions,\n FlowJob,\n FlowOptions,\n GroupOptions,\n Job,\n Queue,\n QueueOptions,\n UnrecoverableError,\n Worker,\n WorkerOptions,\n} from 'groupmq-plus'\nimport IORedis from 'ioredis'\n\nexport type { FlowChildResult } from 'groupmq-plus'\n\nexport interface BackoffOptions {\n /** 延迟策略:固定间隔、指数递增 */\n type: 'fixed' | 'exponential'\n /** 延迟时间为毫秒 */\n delay?: number\n /**\n * 添加到延迟中的随机抖动比例,取值范围为 0 到 1 之间的小数。\n * 抖动用于增加随机性,以防止因多个任务同时重试而导致的惊群效应。\n * 最终的延迟时间将在 `delay ± (delay * jitter)` 的范围内随机波动。\n * @defaultValue 0\n * @example 0.1 // 为延迟添加 ±10% 的随机抖动\n * @example 0.25 // 为延迟添加 ±25% 的随机抖动\n */\n jitter?: number\n}\n\nexport interface RetryOptions {\n error?: Error | unknown\n message?: string\n delay?: number\n}\n\nexport interface HandleOptions {\n token: string\n retryLater(options?: RetryOptions): void\n retryLater(errorOrMessage?: Error | string): void\n retryLater(arg?: RetryOptions | Error | string): void\n abort(message?: string): void\n}\n\nexport interface BaseTaskOptions {\n name?: string\n autoStart?: boolean\n queueOptions?: Partial<QueueOptions>\n workerOptions?: Omit<Partial<WorkerOptions<any>>, 'backoff'> & {\n backoff?: BackoffOptions | ((attempt: number, error: unknown) => number)\n }\n debug?: boolean\n}\n\n/**\n * 任务启动选项,用于单个任务或 Flow 中的子任务\n */\nexport type TaskStartOptions<D> = {\n groupId: string\n data: D\n jobId?: string\n delay?: number\n groupConfig?: GroupOptions\n} & Omit<AddOptions<D>, 'groupId' | 'data' | 'groupConfig'>\n\n/**\n * Flow 任务选项\n */\nexport type TaskFlowOptions<D> = {\n groupId: string\n data: D\n jobId?: string\n groupConfig?: GroupOptions\n children: Array<\n {\n groupId: string\n data: D\n jobId?: string\n groupConfig?: GroupOptions\n } & Omit<FlowJob<D>, 'groupId' | 'data'>\n >\n} & Omit<FlowJob<D>, 'groupId' | 'data'>\n\nexport class TaskRetryLaterError extends Error {\n public customDelay?: number\n\n constructor(message?: string, delay?: number) {\n super(message)\n this.name = 'TaskRetryLaterError'\n this.customDelay = delay\n }\n}\n\nexport abstract class BaseTask<D = any> {\n public queue: Queue<D>\n public worker: Worker<D>\n protected opts: BaseTaskOptions\n\n get name() {\n return this.opts?.name || this.constructor.name\n }\n\n constructor(protected connection: IORedis, opts?: Partial<BaseTaskOptions>) {\n this.opts = Object.assign(\n {\n debug: false,\n autoStart: true,\n queueOptions: {},\n workerOptions: {},\n },\n opts,\n )\n\n this.opts.queueOptions = Object.assign(\n {\n redis: connection,\n namespace: this.name,\n keepCompleted: 0,\n maxAttempts: 3,\n jobTimeoutMs: 5000,\n },\n this.opts.queueOptions,\n )\n\n this.opts.workerOptions = Object.assign(\n {\n concurrency: 1,\n name: this.name,\n },\n this.opts.workerOptions,\n )\n\n this.queue = new Queue<D>(this.opts.queueOptions as QueueOptions)\n\n this.worker = new Worker<D>({\n ...(this.opts.workerOptions as WorkerOptions<D>),\n autoStart: this.opts.autoStart,\n queue: this.queue,\n handler: async (job) => {\n return this.handle(job, {\n token: job.token!,\n retryLater: (arg: RetryOptions | Error | string) => {\n const currentAttempts = job.attemptsMade\n const maxAttempts = job.opts.attempts\n\n let options: RetryOptions = {}\n if (arg instanceof Error) {\n options = { error: arg, message: arg.message }\n } else if (typeof arg === 'string') {\n options = { message: arg }\n } else {\n options = arg || {}\n }\n\n const { error, delay } = options\n const message = options.message || (error instanceof Error ? error.message : undefined) || 'retry later'\n const errorObj = error instanceof Error ? error : undefined\n\n // 这里的检查是为了在最后一次尝试失败时,直接抛出原始 Error 对象\n // 这样 Redis 中的 failedName 将记录为原始错误类型(如 TypeError),而非 TaskRetryLaterError\n if (currentAttempts + 1 >= maxAttempts) {\n if (errorObj) throw errorObj\n throw new Error(message)\n }\n\n const retryErr = new TaskRetryLaterError(message, delay)\n if (errorObj) {\n retryErr.stack = errorObj.stack\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore - preserve cause on older runtimes\n retryErr.cause = errorObj\n }\n throw retryErr\n },\n abort: (message?: string) => {\n throw new UnrecoverableError(message || 'failed')\n },\n })\n },\n backoff: (attempt: number, error: unknown) => {\n // 优先使用 TaskRetryLaterError 的 customDelay\n if (error instanceof TaskRetryLaterError && typeof error.customDelay === 'number') {\n return error.customDelay\n }\n\n const backoffConfig = this.opts.workerOptions?.backoff\n\n // 使用自定义 backoff 函数\n if (typeof backoffConfig === 'function') {\n return backoffConfig(attempt, error)\n }\n\n // 使用 BackoffOptions 配置\n if (backoffConfig && typeof backoffConfig === 'object') {\n const { type, delay = 1000, jitter = 0 } = backoffConfig\n let baseDelay: number\n\n if (type === 'fixed') {\n baseDelay = delay\n } else if (type === 'exponential') {\n baseDelay = delay * Math.pow(2, attempt - 1)\n } else {\n // 不支持的 type,使用默认指数退避\n baseDelay = 1000 * Math.pow(2, attempt - 1)\n }\n\n // 应用 jitter(抖动):确保结果为正整数\n if (jitter > 0) {\n const jitterAmount = baseDelay * jitter\n const randomJitter = Math.random() * jitterAmount * 2 - jitterAmount\n baseDelay = baseDelay + randomJitter\n }\n\n return Math.max(0, Math.round(baseDelay))\n }\n\n // 默认指数退避策略\n return 1000 * Math.pow(2, attempt - 1)\n },\n })\n\n this.setupEventListeners()\n }\n\n private setupEventListeners() {\n this.worker.on('completed', (job) => {\n if (this.opts.debug) {\n console.log(`[COMPLETED] ${this.name}-${job.id} (Group: ${job.groupId})`)\n }\n this.onCompleted(job)\n })\n\n this.worker.on('failed', async (job) => {\n const isFinalFailure = job.isFailed()\n const error = new Error(job.failedReason || 'task failed')\n if (job.stacktrace) {\n error.stack = job.stacktrace\n }\n\n if (this.opts.debug) {\n if (!isFinalFailure) {\n console.log(`[RETRY] ${this.name}-${job.id}: ${error.message}`)\n } else {\n console.error(`[FINAL FAILED] ${this.name}-${job.id}: ${error.message}`)\n }\n }\n\n await this.onFailed(job, error)\n\n if (isFinalFailure) {\n await this.onFinalFailed(job, error)\n }\n })\n\n this.worker.on('error', (err) => {\n if (this.opts.debug) {\n console.error(`[WORKER ERROR] ${this.name}`, err)\n }\n })\n }\n\n async run() {\n return this.worker.run()\n }\n\n abstract handle(job: Job<D>, opts: HandleOptions): Promise<any>\n\n async onFailed(job: Job<D>, error: Error) {}\n async onFinalFailed(job: Job<D>, error: Error) {}\n async onCompleted(job: Job<D>) {}\n\n setGroupConfig(groupId: string, config: { priority?: number; concurrency?: number }) {\n return this.queue.groups.setConfig(groupId, config)\n }\n\n async start(opts: AddOptions<D> | FlowOptions<D, D>) {\n let job: Job<D>\n\n // 检查是否为 Flow (包含 children)\n if ('children' in opts && Array.isArray(opts.children)) {\n if (!opts.parent) {\n throw new Error('Flow must include a parent job')\n }\n\n if (opts.children.length === 0) {\n throw new Error('Flow must include at least one child job')\n }\n\n job = await this.queue.addFlow(opts)\n } else {\n job = await this.queue.add(opts as AddOptions<D>)\n }\n\n // provide a BullMQ-like finished helper\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n job['finished'] = async (timeoutMs?: number) => {\n return job.waitUntilFinished(timeoutMs)\n }\n\n return job as Job<D> & { finished: (timeoutMs?: number) => Promise<any> }\n }\n\n async close() {\n await this.worker.close()\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@libeilong/mq",
3
3
  "author": "lblblong",
4
- "version": "0.2.1",
4
+ "version": "0.2.3",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",