@fluojs/queue
Advanced tools
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKhE,OAAO,KAAK,EAAgC,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAqCnF;;GAEG;AACH,qBAAa,WAAW;IACtB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,kBAAuB,GAAG,UAAU;CAS7D"} | ||
| {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKhE,OAAO,KAAK,EAAgC,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAsCnF;;GAEG;AACH,qBAAa,WAAW;IACtB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,kBAAuB,GAAG,UAAU;CAS7D"} |
+2
-1
@@ -16,3 +16,4 @@ import { defineModule } from '@fluojs/runtime'; | ||
| defaultDeadLetterMaxEntries: normalizePositiveIntegerOrFalse(options.defaultDeadLetterMaxEntries, 1_000), | ||
| defaultRateLimiter | ||
| defaultRateLimiter, | ||
| workerShutdownTimeoutMs: normalizePositiveInteger(options.workerShutdownTimeoutMs, 30_000) | ||
| }; | ||
@@ -19,0 +20,0 @@ } |
| import type { Container } from '@fluojs/di'; | ||
| import type { ApplicationLogger, CompiledModule, OnApplicationBootstrap, OnApplicationShutdown, OnModuleDestroy } from '@fluojs/runtime'; | ||
| import { type BootstrapReadySignal } from '@fluojs/runtime/internal'; | ||
| import type { NormalizedQueueModuleOptions, Queue } from './types.js'; | ||
@@ -15,2 +16,3 @@ /** | ||
| private readonly logger; | ||
| private readonly bootstrapReadySignal; | ||
| private readonly descriptorsByJobType; | ||
@@ -21,2 +23,3 @@ private readonly queuesByJobName; | ||
| private readonly deadLetterManager; | ||
| private readonly readyWorkers; | ||
| private lifecycleState; | ||
@@ -26,3 +29,3 @@ private redisClient; | ||
| private shutdownPromise; | ||
| constructor(options: NormalizedQueueModuleOptions, runtimeContainer: Container, compiledModules: readonly CompiledModule[], logger: ApplicationLogger); | ||
| constructor(options: NormalizedQueueModuleOptions, runtimeContainer: Container, compiledModules: readonly CompiledModule[], logger: ApplicationLogger, bootstrapReadySignal?: BootstrapReadySignal); | ||
| onApplicationBootstrap(): Promise<void>; | ||
@@ -59,2 +62,4 @@ onApplicationShutdown(): Promise<void>; | ||
| private registerInitializedWorker; | ||
| private scheduleReadyWorkers; | ||
| private runWorker; | ||
| private cleanupWorkerInitializationFailure; | ||
@@ -61,0 +66,0 @@ private createOwnedConnection; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,EAChB,MAAM,iBAAiB,CAAC;AASzB,OAAO,KAAK,EACV,4BAA4B,EAC5B,KAAK,EAIN,MAAM,YAAY,CAAC;AAkGpB;;;;;GAKG;AACH,qBACa,qBAAsB,YAAW,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,eAAe;IAY/G,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAdzB,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAkD;IACvF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoC;IACpE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqC;IACtE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA8B;IAC/D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAyB;IAC3D,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,eAAe,CAA4B;gBAGhC,OAAO,EAAE,4BAA4B,EACrC,gBAAgB,EAAE,SAAS,EAC3B,eAAe,EAAE,SAAS,cAAc,EAAE,EAC1C,MAAM,EAAE,iBAAiB;IAKtC,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC;;;;;;;OAOG;IACG,OAAO,CAAC,IAAI,SAAS,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IA2B9D;;;;OAIG;IACH,4BAA4B;YAWd,aAAa;YAwBb,cAAc;YAed,oBAAoB;YASpB,kBAAkB;IAgBhC,OAAO,CAAC,cAAc;YAQR,iBAAiB;YAOjB,yBAAyB;IAyBvC,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,mBAAmB;IAkB3B,OAAO,CAAC,0BAA0B;IAkBlC,OAAO,CAAC,0BAA0B;IASlC,OAAO,CAAC,yBAAyB;YASnB,kCAAkC;YAkBlC,qBAAqB;YAiBrB,aAAa;YAOb,oBAAoB;IAyBlC,OAAO,CAAC,sBAAsB;YAQhB,QAAQ;YAyBR,sBAAsB;YAgBtB,yBAAyB;YAqBzB,cAAc;YAQd,aAAa;YAQb,uBAAuB;CAOtC"} | ||
| {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,EAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAKL,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAQlC,OAAO,KAAK,EACV,4BAA4B,EAC5B,KAAK,EAIN,MAAM,YAAY,CAAC;AAqHpB;;;;;GAKG;AACH,qBACa,qBAAsB,YAAW,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,eAAe;IAa/G,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,oBAAoB;IAhBvC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAkD;IACvF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoC;IACpE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqC;IACtE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA8B;IAC/D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAyB;IAC3D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,eAAe,CAA4B;gBAGhC,OAAO,EAAE,4BAA4B,EACrC,gBAAgB,EAAE,SAAS,EAC3B,eAAe,EAAE,SAAS,cAAc,EAAE,EAC1C,MAAM,EAAE,iBAAiB,EACzB,oBAAoB,GAAE,oBAAuD;IAK1F,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC;;;;;;;OAOG;IACG,OAAO,CAAC,IAAI,SAAS,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IA2B9D;;;;OAIG;IACH,4BAA4B;YAYd,aAAa;YAwBb,cAAc;YAgBd,oBAAoB;YASpB,kBAAkB;IAgBhC,OAAO,CAAC,cAAc;YAQR,iBAAiB;YAOjB,yBAAyB;IAyBvC,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,0BAA0B;IAkBlC,OAAO,CAAC,0BAA0B;IASlC,OAAO,CAAC,yBAAyB;IAUjC,OAAO,CAAC,oBAAoB;IAwB5B,OAAO,CAAC,SAAS;YAgBH,kCAAkC;YAkBlC,qBAAqB;YAiBrB,aAAa;YAOb,oBAAoB;IAyBlC,OAAO,CAAC,sBAAsB;YAQhB,QAAQ;YAyBR,sBAAsB;YAgBtB,yBAAyB;YAsBzB,cAAc;YAkBd,aAAa;YAQb,uBAAuB;CAOtC"} |
+52
-6
@@ -10,9 +10,12 @@ let _initClass; | ||
| import { getRedisClientToken, getRedisComponentId } from '@fluojs/redis'; | ||
| import { APPLICATION_LOGGER, COMPILED_MODULES, RUNTIME_CONTAINER } from '@fluojs/runtime/internal'; | ||
| import { APPLICATION_LOGGER, BOOTSTRAP_READY_SIGNAL, COMPILED_MODULES, RUNTIME_CONTAINER } from '@fluojs/runtime/internal'; | ||
| import { Queue as BullQueue, Worker as BullWorker } from 'bullmq'; | ||
| import { QueueDeadLetterManager } from './dead-letter-manager.js'; | ||
| import { normalizePositiveInteger } from './helpers.js'; | ||
| import { normalizePositiveInteger, withTimeout } from './helpers.js'; | ||
| import { createQueuePlatformStatusSnapshot } from './status.js'; | ||
| import { QUEUE_OPTIONS } from './tokens.js'; | ||
| import { discoverQueueWorkerDescriptors } from './worker-discovery.js'; | ||
| const IMMEDIATE_BOOTSTRAP_READY_SIGNAL = { | ||
| wait: () => Promise.resolve() | ||
| }; | ||
| function hasQueueRedisClient(value) { | ||
@@ -70,3 +73,3 @@ if (typeof value !== 'object' || value === null) { | ||
| static { | ||
| [_QueueLifecycleServic, _initClass] = _applyDecs(this, [Inject(QUEUE_OPTIONS, RUNTIME_CONTAINER, COMPILED_MODULES, APPLICATION_LOGGER)], []).c; | ||
| [_QueueLifecycleServic, _initClass] = _applyDecs(this, [Inject(QUEUE_OPTIONS, RUNTIME_CONTAINER, COMPILED_MODULES, APPLICATION_LOGGER, BOOTSTRAP_READY_SIGNAL)], []).c; | ||
| } | ||
@@ -78,2 +81,3 @@ descriptorsByJobType = new Map(); | ||
| deadLetterManager; | ||
| readyWorkers = []; | ||
| lifecycleState = 'idle'; | ||
@@ -83,3 +87,3 @@ redisClient; | ||
| shutdownPromise; | ||
| constructor(options, runtimeContainer, compiledModules, logger) { | ||
| constructor(options, runtimeContainer, compiledModules, logger, bootstrapReadySignal = IMMEDIATE_BOOTSTRAP_READY_SIGNAL) { | ||
| this.options = options; | ||
@@ -89,2 +93,3 @@ this.runtimeContainer = runtimeContainer; | ||
| this.logger = logger; | ||
| this.bootstrapReadySignal = bootstrapReadySignal; | ||
| this.deadLetterManager = new QueueDeadLetterManager(this.options, this.logger, () => this.getRedisClient()); | ||
@@ -141,2 +146,3 @@ } | ||
| queuesReady: this.queuesByJobName.size, | ||
| workerShutdownTimeoutMs: this.options.workerShutdownTimeoutMs, | ||
| workersDiscovered: this.descriptorsByJobType.size, | ||
@@ -175,2 +181,3 @@ workersReady: this.workersByJobName.size | ||
| this.lifecycleState = 'started'; | ||
| this.scheduleReadyWorkers(); | ||
| } | ||
@@ -240,2 +247,3 @@ } | ||
| return { | ||
| autorun: false, | ||
| concurrency: descriptor.concurrency, | ||
@@ -266,3 +274,35 @@ connection: workerConnection, | ||
| this.ownedConnections.push(resources.queueConnection, resources.workerConnection); | ||
| this.readyWorkers.push({ | ||
| descriptor, | ||
| worker: resources.worker | ||
| }); | ||
| } | ||
| scheduleReadyWorkers() { | ||
| const workers = this.readyWorkers.splice(0); | ||
| void this.bootstrapReadySignal.wait().then(() => { | ||
| if (this.lifecycleState !== 'started') { | ||
| return; | ||
| } | ||
| for (const { | ||
| descriptor, | ||
| worker | ||
| } of workers) { | ||
| this.runWorker(descriptor, worker); | ||
| } | ||
| }).catch(error => { | ||
| if (this.lifecycleState !== 'started') { | ||
| return; | ||
| } | ||
| this.logger.error('Failed to start queue workers after application bootstrap readiness.', error, 'QueueLifecycleService'); | ||
| }); | ||
| } | ||
| runWorker(descriptor, worker) { | ||
| const runnableWorker = worker; | ||
| if (typeof runnableWorker.run !== 'function') { | ||
| return; | ||
| } | ||
| void Promise.resolve(runnableWorker.run()).catch(error => { | ||
| this.logger.error(`Failed to start queue worker ${descriptor.workerName} after application bootstrap.`, error, 'QueueLifecycleService'); | ||
| }); | ||
| } | ||
| async cleanupWorkerInitializationFailure(resources) { | ||
@@ -361,2 +401,3 @@ if (resources.worker) { | ||
| this.queuesByJobName.clear(); | ||
| this.readyWorkers.splice(0); | ||
| for (const worker of workers) { | ||
@@ -374,5 +415,10 @@ await this.tryCloseWorker(worker); | ||
| try { | ||
| await worker.close(); | ||
| await withTimeout(worker.close(), this.options.workerShutdownTimeoutMs, () => new Error('queue worker shutdown timed out')); | ||
| } catch (error) { | ||
| this.logger.error('Failed to close queue worker during shutdown.', error, 'QueueLifecycleService'); | ||
| this.logger.error('Failed to close queue worker within shutdown timeout.', error, 'QueueLifecycleService'); | ||
| try { | ||
| await worker.close(true); | ||
| } catch (forceCloseError) { | ||
| this.logger.error('Failed to force close queue worker during shutdown.', forceCloseError, 'QueueLifecycleService'); | ||
| } | ||
| } | ||
@@ -379,0 +425,0 @@ } |
+1
-0
@@ -10,2 +10,3 @@ import type { PlatformHealthReport, PlatformReadinessReport, PlatformSnapshot } from '@fluojs/runtime'; | ||
| queuesReady: number; | ||
| workerShutdownTimeoutMs: number; | ||
| workersDiscovered: number; | ||
@@ -12,0 +13,0 @@ workersReady: number; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEvG,sEAAsE;AACtE,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAE3F,oFAAoF;AACpF,MAAM,WAAW,uBAAuB;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,mBAAmB,CAAC;IACpC,uBAAuB,EAAE,MAAM,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,sFAAsF;AACtF,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,uBAAuB,CAAC;IACnC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAkFD;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,uBAAuB,GAAG,2BAA2B,CAkB7G"} | ||
| {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEvG,sEAAsE;AACtE,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAE3F,oFAAoF;AACpF,MAAM,WAAW,uBAAuB;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,mBAAmB,CAAC;IACpC,uBAAuB,EAAE,MAAM,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,uBAAuB,EAAE,MAAM,CAAC;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,sFAAsF;AACtF,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,uBAAuB,CAAC;IACnC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAkFD;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,uBAAuB,GAAG,2BAA2B,CAmB7G"} |
+1
-0
@@ -91,2 +91,3 @@ /** Lifecycle phases reported by the queue platform status adapter. */ | ||
| queuesReady: input.queuesReady, | ||
| workerShutdownTimeoutMs: input.workerShutdownTimeoutMs, | ||
| workersDiscovered: input.workersDiscovered, | ||
@@ -93,0 +94,0 @@ workersReady: input.workersReady |
+3
-0
@@ -41,2 +41,4 @@ import type { Token } from '@fluojs/core'; | ||
| defaultRateLimiter?: QueueRateLimiterOptions; | ||
| /** Maximum time shutdown waits for active worker processors before forcing worker close. Defaults to `30_000`. */ | ||
| workerShutdownTimeoutMs?: number; | ||
| } | ||
@@ -51,2 +53,3 @@ /** Normalized queue options resolved once during module registration. */ | ||
| defaultRateLimiter?: QueueRateLimiterOptions; | ||
| workerShutdownTimeoutMs: number; | ||
| } | ||
@@ -53,0 +56,0 @@ /** Metadata captured by {@link QueueWorker} during decorator evaluation. */ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,oFAAoF;AACpF,MAAM,WAAW,YAAY,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IACxD,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;CAC9B;AAED,sEAAsE;AACtE,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,aAAa,CAAC;AAEvD,4DAA4D;AAC5D,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED,qEAAqE;AACrE,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC;AAED,iFAAiF;AACjF,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2BAA2B,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC7C,kBAAkB,CAAC,EAAE,uBAAuB,CAAC;CAC9C;AAED,yEAAyE;AACzE,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,2BAA2B,EAAE,MAAM,GAAG,KAAK,CAAC;IAC5C,kBAAkB,CAAC,EAAE,uBAAuB,CAAC;CAC9C;AAED,4EAA4E;AAC5E,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,kBAAkB,CAAC;CAC7B;AAED,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,YAAY,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,yEAAyE;AACzE,MAAM,WAAW,KAAK;IACpB;;;;;OAKG;IACH,OAAO,CAAC,IAAI,SAAS,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1D"} | ||
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,oFAAoF;AACpF,MAAM,WAAW,YAAY,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IACxD,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;CAC9B;AAED,sEAAsE;AACtE,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,aAAa,CAAC;AAEvD,4DAA4D;AAC5D,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED,qEAAqE;AACrE,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC;AAED,iFAAiF;AACjF,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2BAA2B,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC7C,kBAAkB,CAAC,EAAE,uBAAuB,CAAC;IAC7C,kHAAkH;IAClH,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,yEAAyE;AACzE,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,2BAA2B,EAAE,MAAM,GAAG,KAAK,CAAC;IAC5C,kBAAkB,CAAC,EAAE,uBAAuB,CAAC;IAC7C,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED,4EAA4E;AAC5E,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,kBAAkB,CAAC;CAC7B;AAED,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,YAAY,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,yEAAyE;AACzE,MAAM,WAAW,KAAK;IACpB;;;;;OAKG;IACH,OAAO,CAAC,IAAI,SAAS,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1D"} |
+5
-5
@@ -13,3 +13,3 @@ { | ||
| ], | ||
| "version": "1.0.0-beta.5", | ||
| "version": "1.0.0", | ||
| "private": false, | ||
@@ -42,6 +42,6 @@ "license": "MIT", | ||
| "bullmq": "^5.58.0", | ||
| "@fluojs/core": "^1.0.0-beta.5", | ||
| "@fluojs/di": "^1.0.0-beta.7", | ||
| "@fluojs/redis": "^1.0.0-beta.4", | ||
| "@fluojs/runtime": "^1.0.0-beta.12" | ||
| "@fluojs/core": "^1.0.0", | ||
| "@fluojs/redis": "^1.0.0", | ||
| "@fluojs/runtime": "^1.0.0", | ||
| "@fluojs/di": "^1.0.0" | ||
| }, | ||
@@ -48,0 +48,0 @@ "devDependencies": { |
+14
-1
@@ -93,2 +93,8 @@ # @fluojs/queue | ||
| ### 부트스트랩 및 종료 수명 주기 | ||
| Queue는 애플리케이션 부트스트랩 중 worker를 탐색하고 Queue가 소유하는 BullMQ 리소스를 만들지만, BullMQ worker processor는 runtime이 전체 애플리케이션 bootstrap/readiness sequence 완료를 표시한 뒤에만 시작합니다. 다른 `onApplicationBootstrap()` hook에서 enqueue한 job은 Queue 서비스가 초기화된 뒤에는 받을 수 있으며, processor는 뒤에 실행되는 async bootstrap hook이나 애플리케이션 readiness보다 앞서 실행되지 않고 bootstrap-ready handoff 이후 실행됩니다. | ||
| 애플리케이션 종료가 시작되면 Queue는 상태를 `stopping`으로 바꾸고 새 enqueue를 거부한 다음 Queue 소유 worker/queue/connection을 닫고 pending dead-letter write를 drain합니다. Worker 종료는 `workerShutdownTimeoutMs`로 bounded wait를 적용하므로 끝나지 않는 active processor가 애플리케이션 종료를 무기한 막을 수 없습니다. Timeout이 지나면 Queue는 로그를 남기고 BullMQ worker에 force-close를 요청한 뒤 나머지 리소스 정리를 계속합니다. | ||
| ### 분산 재시도 (Distributed Retries) | ||
@@ -131,4 +137,11 @@ | ||
| `QueueModuleOptions`에는 `defaultDeadLetterMaxEntries` 같은 dead-letter retention 설정도 포함됩니다. | ||
| `QueueModuleOptions`에는 `workerShutdownTimeoutMs`, `defaultDeadLetterMaxEntries` 같은 lifecycle 및 dead-letter retention 설정도 포함됩니다. | ||
| `QueueModuleOptions` 수명 주기/status 설정: | ||
| - `workerShutdownTimeoutMs`: 종료 중 active worker processor를 기다리는 최대 시간입니다. 시간이 지나면 BullMQ worker를 force-close합니다. 기본값은 `30_000`입니다. | ||
| - `defaultDeadLetterMaxEntries`: job별로 유지할 dead-letter record의 최대 개수이며, trimming을 끄려면 `false`를 지정합니다. 기본값은 `1_000`입니다. | ||
| `createQueuePlatformStatusSnapshot(...)`은 Queue가 `started`에 도달한 뒤에만 readiness를 `ready`로 보고합니다. `starting`은 degraded readiness, `stopping`/`stopped`는 not-ready로 보고합니다. Snapshot details에는 Redis dependency id, lifecycle state, ready/discovered worker 수, pending dead-letter write 수, dead-letter drain timeout, `workerShutdownTimeoutMs`가 포함됩니다. | ||
| singleton `@QueueWorker()` provider/controller만 등록됩니다. request/transient worker는 discovery 중 건너뜁니다. | ||
@@ -135,0 +148,0 @@ |
+14
-1
@@ -93,2 +93,8 @@ # @fluojs/queue | ||
| ### Bootstrap and Shutdown Lifecycle | ||
| Queue discovers workers and creates queue-owned BullMQ resources during application bootstrap, but BullMQ worker processors are started only after the runtime marks the full application bootstrap/readiness sequence complete. Jobs enqueued by other `onApplicationBootstrap()` hooks can be accepted once the Queue service is initialized, and their processors run after the bootstrap-ready handoff instead of racing ahead of later async bootstrap hooks or application readiness. | ||
| Application shutdown marks Queue as `stopping`, rejects new enqueue attempts, closes queue-owned workers/queues/connections, and drains pending dead-letter writes. Worker shutdown is bounded by `workerShutdownTimeoutMs` so an active processor that never settles cannot block application shutdown indefinitely. When the timeout elapses, Queue logs the timeout and asks BullMQ to force-close the worker before continuing resource cleanup. | ||
| ### Distributed Retries | ||
@@ -131,4 +137,11 @@ | ||
| `QueueModuleOptions` also includes dead-letter retention controls such as `defaultDeadLetterMaxEntries`. | ||
| `QueueModuleOptions` also includes lifecycle and dead-letter retention controls such as `workerShutdownTimeoutMs` and `defaultDeadLetterMaxEntries`. | ||
| `QueueModuleOptions` lifecycle/status controls: | ||
| - `workerShutdownTimeoutMs`: maximum time to wait for active worker processors during shutdown before force-closing the BullMQ worker. Defaults to `30_000`. | ||
| - `defaultDeadLetterMaxEntries`: maximum retained dead-letter records per job, or `false` to disable trimming. Defaults to `1_000`. | ||
| `createQueuePlatformStatusSnapshot(...)` reports readiness as `ready` only after Queue reaches `started`; `starting` reports degraded readiness, and `stopping`/`stopped` report not-ready. Snapshot details include the Redis dependency id, lifecycle state, ready/discovered worker counts, pending dead-letter writes, the dead-letter drain timeout, and `workerShutdownTimeoutMs`. | ||
| Only singleton `@QueueWorker()` providers/controllers are registered. Request/transient workers are skipped during discovery. | ||
@@ -135,0 +148,0 @@ |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
79534
8.75%1351
4.4%1
-50%157
9.03%Updated
Updated
Updated
Updated