@lavoro/core 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Logger as Logger$1, LogObject, Levels } from '@julr/utils/logger';
2
- import { EventEmitter } from 'stream';
2
+ import { EventEmitter } from 'events';
3
3
  import { LockFactory } from '@verrou/core';
4
4
  import { SerializedLock, Duration } from '@verrou/core/types';
5
5
  import { Cron } from 'croner';
package/build/index.js CHANGED
@@ -242,7 +242,7 @@ __publicField(_Job, "defaultQueueServiceResolver");
242
242
  var Job = _Job;
243
243
 
244
244
  // src/queue/contracts/queue_driver_event_emitter.ts
245
- import { EventEmitter } from "stream";
245
+ import { EventEmitter } from "events";
246
246
  var QueueDriverEventEmitter = class extends EventEmitter {
247
247
  on(event, listener) {
248
248
  return super.on(event, listener);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/logger.ts","../src/queue/define_config.ts","../src/queue/pending_dispatch.ts","../src/queue/contracts/job.ts","../src/queue/contracts/queue_driver_event_emitter.ts","../src/queue/contracts/queue_driver.ts","../src/schedule/schedule_interval.ts","../src/schedule/schedule_registry.ts","../src/schedule/pending_schedule.ts","../src/schedule/pending_job_schedule.ts","../src/schedule/schedule.ts","../src/queue/queue_event_emitter.ts","../src/queue/queue.ts"],"sourcesContent":["import type {\n Logger as InternalLogger,\n Levels,\n LogObject,\n} from '@julr/utils/logger'\n\n/**\n * No-op logger implementation used as fallback when pino is not installed\n */\nclass NoOpLogger implements InternalLogger {\n level: Levels = 'trace'\n\n child(_obj: LogObject): InternalLogger {\n return this\n }\n\n trace(_msg: any, _obj?: any): void {}\n debug(_msg: any, _obj?: any): void {}\n info(_msg: any, _obj?: any): void {}\n warn(_msg: any, _obj?: any): void {}\n error(_msg: any, _obj?: any): void {}\n fatal(_msg: any, _obj?: any): void {}\n}\n\nexport class Logger {\n private internalLogger: InternalLogger\n\n constructor(internalLogger: InternalLogger) {\n this.internalLogger = internalLogger\n }\n\n child(obj: LogObject) {\n return new Logger(this.internalLogger.child(obj))\n }\n\n trace(msg: any, obj?: any) {\n this.internalLogger.trace(msg, obj)\n }\n\n debug(msg: any, obj?: any) {\n this.internalLogger.debug(msg, obj)\n }\n\n warn(msg: any, obj?: any) {\n this.internalLogger.warn(msg, obj)\n }\n\n error(msg: any, obj?: any) {\n this.internalLogger.error(msg, obj)\n }\n\n fatal(msg: any, obj?: any) {\n this.internalLogger.fatal(msg, obj)\n }\n\n info(msg: any, obj?: any) {\n this.internalLogger.info(msg, obj)\n }\n}\n\nexport function createDefaultLogger(\n name: string,\n level: Levels = 'info',\n): Logger {\n try {\n // Try to require pino synchronously\n const pino = require('pino')\n return new Logger(pino({ name, level }))\n } catch {\n // Fallback to no-op logger if pino is not installed\n return new Logger(new NoOpLogger())\n }\n}\n","import type { QueueConfig, QueueConnectionsList } from './types.js'\n\nimport { RuntimeException } from '@poppinss/utils'\n\ntype QueueConfigWithConnections<Connections, Connection> = QueueConfig & {\n connection: Connection\n connections: Connections\n}\n\n/**\n * Define config for queue service.\n *\n * @example\n * ```ts\n * // config/queue.ts\n * import { memory } from '@lavoro/memory'\n * import { postgres } from '@lavoro/postgres'\n *\n * const config = {\n * jobs: [...],\n * connection: 'main',\n * connections: {\n * main: {\n * driver: memory(),\n * queues: {\n * default: { concurrency: 1 },\n * emails: { concurrency: 3 },\n * },\n * },\n * background: {\n * driver: postgres({ ... }),\n * queues: {\n * 'heavy-tasks': { concurrency: 2 },\n * reports: { concurrency: 1 },\n * },\n * },\n * },\n * }\n *\n * const queueConfig = defineConfig(config)\n *\n * // Type augmentation to enable type-safe queue names\n * declare module '@lavoro/core' {\n * interface QueueList extends InferQueueNames<typeof config> {}\n * interface DefaultConnection {\n * name: InferDefaultConnection<typeof config>\n * }\n * interface QueueConnections extends InferConnections<typeof config> {}\n * interface ConnectionQueues extends InferConnectionQueues<typeof config> {}\n * }\n * ```\n *\n * After defining your queue names, you'll get autocomplete and type checking:\n * ```ts\n * await queue.listen('emails') // ✓ Valid\n * await queue.listen('heavy-tasks') // ✓ Valid\n * await queue.listen('invalid') // ✗ Type error\n *\n * await job.dispatch(payload).onQueue('emails') // ✓ Valid\n * await job.dispatch(payload).onQueue('typo') // ✗ Type error\n * ```\n */\nexport function defineConfig<\n const Connections extends QueueConnectionsList,\n const Connection extends keyof Connections = keyof Connections,\n>(\n config: QueueConfigWithConnections<Connections, Connection>,\n): QueueConfigWithConnections<Connections, Connection> {\n // Validate required fields\n if (!config.connection) {\n throw new RuntimeException(\n 'Missing \"connection\" property in queue config file',\n )\n }\n\n if (!config.connections) {\n throw new RuntimeException(\n 'Missing \"connections\" property in queue config file',\n )\n }\n\n // Validate default connection exists\n if (!config.connections[config.connection as string]) {\n throw new RuntimeException(\n `Missing \"connections.${String(config.connection)}\". It is referenced by the \"connection\" property`,\n )\n }\n\n // Validate each connection has queues\n Object.keys(config.connections).forEach((connectionName) => {\n const connection =\n config.connections[connectionName as keyof typeof config.connections]\n if (!connection.queues || Object.keys(connection.queues).length === 0) {\n throw new RuntimeException(\n `Connection \"${connectionName}\" must have at least one queue defined`,\n )\n }\n })\n\n return config\n}\n","import { Job, Payload } from './contracts/job.js'\nimport { QueueName, QueueNameForConnection } from './contracts/queue_driver.js'\nimport { DefaultConnection, QueueConnectionName } from './types.js'\n\nexport class PendingDispatch<\n T extends Job,\n P extends Payload<T>,\n C extends QueueConnectionName = DefaultConnection extends { name: infer N }\n ? N extends QueueConnectionName\n ? N\n : QueueConnectionName\n : QueueConnectionName,\n> {\n constructor(\n protected job: T,\n protected payload: P,\n ) {}\n\n public onConnection<NewC extends QueueConnectionName>(\n connection: NewC,\n ): PendingDispatch<T, P, NewC> {\n this.job.options.connection = connection\n\n return this as unknown as PendingDispatch<T, P, NewC>\n }\n\n public onQueue(queue: QueueNameForConnection<C>) {\n this.job.options.queue = queue as QueueName\n\n return this\n }\n\n // public withQueueServiceResolver(\n // queueServiceResolver: () => Promise<Queue>,\n // ): this {\n // this.job.setQueueServiceResolver(queueServiceResolver)\n\n // return this\n // }\n\n protected async execute(): Promise<void> {\n if (!this.job.getQueueServiceResolver) {\n throw new Error(\n 'Queue service resolver is not set.\\nDid you forget to call Job.setDefaultQueueServiceResolver()?',\n )\n }\n\n const queue = await this.job.getQueueServiceResolver()\n await queue.enqueue(this.job, this.payload)\n }\n\n /**\n * By defining the \"then\" method, PendingDispatch becomes \"thenable\",\n * allowing it to trigger automatically when await is called.\n */\n public async then<TResult1 = void, TResult2 = never>(\n onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n // When await is called, actually execte pending chain.\n return this.execute().then(onfulfilled, onrejected)\n }\n}\n","import { PendingDispatch } from '../pending_dispatch.js'\nimport { Queue } from '../queue.js'\nimport { QueueConnectionName } from '../types.js'\n\nimport { SerializedLock } from '@verrou/core/types'\nimport { randomUUID } from 'node:crypto'\n\nexport type Payload<T extends Job> = T extends Job<infer P> ? P : unknown\n\nexport type PayloadWithLock<T extends Job, P extends Payload<T>> = P & {\n _lock?: SerializedLock\n}\n\nexport type Options = {\n connection?: QueueConnectionName\n queue?: string\n retries: number\n delay: number\n}\n\nexport abstract class Job<P = unknown> {\n private _id: string = randomUUID()\n\n public options: Options = {\n retries: 3,\n delay: 0,\n }\n\n public static compileName(queue: string, name: string): string {\n return `${queue}_${name}`\n }\n\n public static parseName(name: string): { queue: string; name: string } {\n const [q, n] = name.split(/_(.+)/) // split on the first underscore only\n return { queue: q, name: n }\n }\n\n public get connection(): QueueConnectionName | undefined {\n return this.options.connection\n }\n\n public set connection(connection: QueueConnectionName | undefined) {\n this.options.connection = connection\n }\n\n public get queue(): string | undefined {\n return this.options.queue\n }\n\n public set queue(queue: string | undefined) {\n this.options.queue = queue\n }\n\n public get name(): string {\n return this.constructor.name\n }\n\n public get id(): string {\n return this._id\n }\n\n public set id(id: string) {\n this._id = id\n }\n\n public get fullyQualifiedName(): string {\n if (!this.options.queue) {\n throw new Error('Queue is not set.')\n }\n\n return Job.compileName(this.options.queue, this.name)\n }\n\n private static defaultQueueServiceResolver: () => Promise<Queue>\n\n public static setDefaultQueueServiceResolver(\n queueServiceResolver: () => Promise<Queue>,\n ): void {\n this.defaultQueueServiceResolver = queueServiceResolver\n }\n\n public setQueueServiceResolver(\n queueServiceResolver: () => Promise<Queue>,\n ): void {\n this.queueServiceResolver = queueServiceResolver\n }\n\n private queueServiceResolver?: () => Promise<Queue> = undefined\n\n public get getQueueServiceResolver(): () => Promise<Queue> {\n return this.queueServiceResolver || Job.defaultQueueServiceResolver\n }\n\n /**\n * Handle the job with the typed payload.\n */\n public abstract handle(payload: P): Promise<void>\n\n /**\n * Dispatch a job of type with a typed payload.\n */\n public static dispatch<T extends Job, P extends Payload<T>>(\n this: new () => T,\n payload: P,\n ): PendingDispatch<T, P> {\n const job = new this() as T\n return new PendingDispatch<T, P>(job, payload)\n }\n}\n","import { Job } from './job.js'\n\nimport { EventEmitter } from 'stream'\n\n/**\n * Type-safe queue driver events.\n */\nexport interface QueueDriverEvents {\n error: [error: Error]\n 'job:start': [job: Job, payload: unknown]\n 'job:progress': [job: Job, payload: unknown, elapsed: number]\n 'job:complete': [job: Job, payload: unknown, elapsed: number]\n 'job:error': [error: Error, job: Job, payload: unknown]\n 'job:finish': [job: Job, payload: unknown, elapsed: number]\n}\n\n/**\n * Type-safe event emitter for the queue driver.\n */\nexport abstract class QueueDriverEventEmitter extends EventEmitter {\n public override on<K extends keyof QueueDriverEvents>(\n event: K,\n listener: (...args: QueueDriverEvents[K]) => void,\n ): this {\n return super.on(event, listener)\n }\n\n public override off<K extends keyof QueueDriverEvents>(\n event: K,\n listener: (...args: QueueDriverEvents[K]) => void,\n ): this {\n return super.off(event, listener)\n }\n\n public override emit<K extends keyof QueueDriverEvents>(\n event: K,\n ...args: QueueDriverEvents[K]\n ): boolean {\n /**\n * Avoid throwing error even if there are no listeners\n * for the `error` event (special case, see:\n * https://nodejs.org/api/events.html#error-events).\n */\n if (this.listenerCount(event) === 0) {\n return false\n }\n\n return super.emit(event, ...args)\n }\n}\n","import { Logger, createDefaultLogger } from '../../logger.js'\nimport { QueueConfig, QueueConnectionName, WorkerOptions } from '../types.js'\nimport { Job, Payload } from './job.js'\nimport { QueueDriverEventEmitter } from './queue_driver_event_emitter.js'\n\nimport type { Lock, LockFactory } from '@verrou/core'\nimport type { SerializedLock } from '@verrou/core/types'\n\nexport type ProcessJobParams = {\n id: string\n fullyQualifiedName: string\n payload: unknown\n}\n\n/**\n * Interface to be augmented by users to define their queue names.\n * This enables type-safe queue names throughout the application.\n */\nexport interface QueueList {}\n\n/**\n * Interface to be augmented by users to map connections to their queue names.\n * This enables connection-specific type-safe queue names.\n */\nexport interface ConnectionQueues {}\n\n/**\n * Extract queue names from QueueList.\n * Defaults to string if no queues are defined.\n */\nexport type QueueName = keyof QueueList extends never ? string : keyof QueueList\n\n/**\n * Extract queue names for a specific connection from ConnectionQueues.\n */\nexport type QueueNameForConnection<C extends QueueConnectionName> =\n C extends keyof ConnectionQueues ? ConnectionQueues[C] : QueueName\n\nexport type QueueDriverStopOptions = {\n /**\n * Whether to wait for the jobs to finish processing before stopping.\n *\n * Default: true\n */\n graceful?: boolean\n\n /**\n * The timeout in milliseconds to wait for the jobs to finish processing.\n *\n * Default: 30000 (30 seconds)\n */\n timeout?: number\n}\n\nexport type QueueDriverConfig = {}\n\nexport abstract class QueueDriver<\n Config extends QueueDriverConfig = QueueDriverConfig,\n> extends QueueDriverEventEmitter {\n protected logger: Logger\n\n protected registeredQueues: Set<string> = new Set()\n\n protected registeredJobs: Map<string, new () => Job> = new Map()\n\n protected lockFactory?: LockFactory\n\n public connection: QueueConnectionName | undefined\n\n constructor(\n protected config: QueueConfig,\n protected options: Record<string, WorkerOptions>,\n protected driverConfig: Config = {} as Config,\n ) {\n super()\n this.logger = createDefaultLogger('queue')\n }\n\n public setLogger(logger: Logger): void {\n this.logger = logger\n }\n\n protected getMergedWorkerOptions(\n queue: QueueName,\n options?: WorkerOptions,\n ): WorkerOptions {\n const base = this.options[queue] || {}\n return { ...base, ...(options || {}) }\n }\n\n public async listen(\n queue: QueueName,\n options?: WorkerOptions,\n ): Promise<void> {\n if (this.registeredQueues.has(queue as string)) {\n throw new Error(`Queue '${queue as string}' already registered`)\n }\n\n this.registeredQueues.add(queue as string)\n\n const workerOptions = this.getMergedWorkerOptions(queue, options)\n\n this.logger.trace(\n { connection: this.connection, queue, options: workerOptions },\n 'Listening queue',\n )\n }\n\n public async register(job: new () => Job): Promise<void> {\n if (this.registeredJobs.has(job.name)) {\n return\n }\n\n this.registeredJobs.set(job.name, job)\n\n this.logger.trace(\n { connection: this.connection, job: job.name },\n 'Registered job',\n )\n }\n\n public async unregister(job: new () => Job): Promise<void> {\n if (!this.registeredJobs.has(job.name)) {\n return\n }\n\n this.registeredJobs.delete(job.name)\n\n this.logger.trace(\n { connection: this.connection, job: job.name },\n 'Unregistered job',\n )\n }\n\n public async start(): Promise<void> {\n for (const [queue, options] of Object.entries(this.options)) {\n await this.listen(queue as QueueName, options)\n }\n }\n\n public async stop(_options?: QueueDriverStopOptions): Promise<void> {\n this.registeredQueues.clear()\n this.registeredJobs.clear()\n }\n\n protected checkIfQueueIsRegistered(queue: string): void {\n if (!this.registeredQueues.has(queue)) {\n throw new Error(`Queue '${queue}' is not registered.`)\n }\n }\n\n protected checkIfJobIsRegistered(job: string): void {\n if (!this.registeredJobs.has(job)) {\n throw new Error(`Job '${job}' is not registered.`)\n }\n }\n\n public getDefaultQueue(): QueueName {\n if (this.registeredQueues.size === 0) {\n throw new Error(\n `No queues registered for connection: ${this.connection}.`,\n )\n }\n\n return this.registeredQueues.values().next().value as QueueName\n }\n\n /**\n * Parent method to be extended by the driver.\n * It implements checks for the job and queue being registered.\n */\n public async enqueue<T extends Job, P extends Payload<T>>(\n job: T,\n // @ts-ignore\n payload: P,\n ): Promise<void> {\n if (!job.options.queue) {\n job.options.queue = this.getDefaultQueue()\n }\n\n this.checkIfQueueIsRegistered(job.options.queue)\n this.checkIfJobIsRegistered(job.name)\n\n return Promise.resolve()\n }\n\n /**\n * Create a lock factory instance for this driver.\n *\n * Each driver implementation should return a\n * [Verrou LockFactory instance](https://verrou.dev/docs/quick-setup#lockfactory-api)\n * that matches the driver's backing store.\n *\n * @returns A LockFactory instance\n */\n public abstract createLockProvider(): LockFactory\n\n /**\n * Clean up resources associated with a lock factory created by this driver.\n * This is called when the queue is stopped to ensure proper resource cleanup.\n *\n * @param lockFactory - The lock factory instance to clean up\n */\n public async destroyLockProvider(_lockFactory: LockFactory): Promise<void> {\n // Default implementation does nothing\n // Drivers that need cleanup (e.g., Postgres with Knex) should override this\n }\n\n /**\n * Execute a job with the given parameters.\n * This method contains the common job processing logic shared by all drivers.\n */\n protected async process(params: ProcessJobParams): Promise<void> {\n const { id, fullyQualifiedName, payload } = params\n const { queue, name } = Job.parseName(fullyQualifiedName)\n\n if (!queue || !name) {\n const error = new Error(`Invalid job class name: ${fullyQualifiedName}`)\n this.logger.warn(error)\n throw error\n }\n\n this.logger.trace({ job: name }, 'Processing job')\n\n try {\n this.checkIfJobIsRegistered(name)\n } catch (error) {\n this.logger.warn(error)\n throw error\n }\n\n const jobClass = this.registeredJobs.get(name)!\n\n const jobInstance = new jobClass()\n\n jobInstance.connection = this.connection\n jobInstance.queue = queue\n jobInstance.id = id\n\n this.logger.debug(\n {\n connection: this.connection,\n queue,\n job: name,\n id,\n },\n 'Processing job',\n )\n\n /**\n * A job might have been scheduled by the scheduler,\n * in which case we need to restore the lock from the payload.\n *\n * This will prevent the job from being scheduled\n * while it is being processed.\n */\n const serializedLock = (payload as any)?._lock as SerializedLock | undefined\n const ttl = serializedLock?.ttl\n\n let lock: Lock | undefined\n\n if (serializedLock !== undefined) {\n if (this.lockFactory === undefined) {\n this.logger.warn(\n { job: name, id },\n 'Scheduled job has lock but lock factory is not available',\n )\n } else {\n try {\n lock = this.lockFactory.restoreLock(serializedLock)\n await lock.acquireImmediately()\n\n if (ttl) {\n await lock.extend(ttl)\n }\n\n this.logger.trace(\n {\n job: name,\n id,\n serializedLock,\n },\n 'Restored lock from scheduler',\n )\n } catch (error) {\n this.logger.warn({ job: name, id, error }, 'Failed to restore lock')\n }\n }\n }\n\n const startedAt = Date.now()\n\n this.emit('job:start', jobInstance, payload)\n\n let isExtending = false\n\n const onProgress = async () => {\n if (lock && ttl && !isExtending) {\n try {\n const remainingTime = lock.getRemainingTime()\n\n /**\n * Extend lock if remaining time drops below half the TTL.\n * This acts as a heartbeat to prevent the lock from expiring\n * while the job is still running, without unnecessary extensions\n * for short jobs.\n */\n if (remainingTime !== null && remainingTime <= ttl / 2) {\n isExtending = true\n this.logger.trace(\n { job: name, id, remainingTime, ttl },\n 'Extending lock',\n )\n await lock.extend(ttl)\n }\n } catch (error) {\n this.logger.warn({ job: name, id, error }, 'Failed to extend lock')\n } finally {\n isExtending = false\n }\n }\n\n this.emit('job:progress', jobInstance, payload, Date.now() - startedAt)\n }\n\n const intervalId = setInterval(onProgress, 1000)\n\n /**\n * Next, we process the actual job.\n */\n try {\n await jobInstance.handle(payload)\n\n this.emit('job:complete', jobInstance, payload, Date.now() - startedAt)\n\n this.logger.trace(\n {\n connection: this.connection,\n queue,\n job: name,\n id,\n },\n 'Job completed',\n )\n } catch (error) {\n this.emit('job:error', error, jobInstance, payload)\n } finally {\n this.emit('job:finish', jobInstance, payload, Date.now() - startedAt)\n /**\n * Once the job is done with any status,\n * we must clear the interval.\n */\n clearInterval(intervalId)\n\n /**\n * If we previously acquired a lock for\n * this job, we need to release it here.\n */\n if (lock) {\n try {\n await lock.forceRelease()\n\n this.logger.trace(\n { job: name, id, lock: lock.serialize() },\n 'Released lock for scheduled job',\n )\n } catch (error) {\n this.logger.warn({ job: name, id, error }, 'Failed to release lock')\n }\n }\n }\n }\n}\n","export type ScheduleInterval =\n | 'second'\n | 'two seconds'\n | 'three seconds'\n | 'four seconds'\n | 'five seconds'\n | 'ten seconds'\n | 'fifteen seconds'\n | 'twenty seconds'\n | 'thirty seconds'\n | 'minute'\n | 'two minutes'\n | 'three minutes'\n | 'four minutes'\n | 'five minutes'\n | 'ten minutes'\n | 'fifteen minutes'\n | 'twenty minutes'\n | 'thirty minutes'\n | 'hour'\n | 'two hours'\n | 'three hours'\n | 'four hours'\n | 'five hours'\n | 'six hours'\n | 'seven hours'\n | 'eight hours'\n | 'nine hours'\n | 'ten hours'\n | 'eleven hours'\n | 'twelve hours'\n | 'day'\n | 'week'\n | 'sunday'\n | 'monday'\n | 'tuesday'\n | 'wednesday'\n | 'thursday'\n | 'friday'\n | 'saturday'\n | 'month'\n | 'last day of month'\n// | 'quarter'\n// | 'year'\n\nexport type ScheduleIntervalDayOfWeek =\n | 'sunday'\n | 'monday'\n | 'tuesday'\n | 'wednesday'\n | 'thursday'\n | 'friday'\n | 'saturday'\n\ntype Hour = `${0 | 1 | 2}${0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`\ntype Minute = `${0 | 1 | 2 | 3 | 4 | 5}${0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`\n\nexport type ScheduleIntervalTime = `${Hour}:${Minute}`\n\nexport function parseTime(time: ScheduleIntervalTime): [number, number] {\n const [hour, minute] = time.split(':')\n\n if (!hour || !minute || hour.length !== 2 || minute.length !== 2) {\n throw new Error('Invalid time format')\n }\n\n return [Number(hour), Number(minute)]\n}\n\nexport interface IntervalCronOptions {\n /** Minute to run. Default: 0 */\n minute?: number\n /** Hour to run. Default: 0 */\n hour?: number\n /** Day of month to run. Default: 1 */\n dayOfMonth?: number\n /** Day of week to run. Default: 0 */\n dayOfWeek?: ScheduleIntervalDayOfWeek\n}\n\nexport function dayOfWeekToNumber(\n dayOfWeek: ScheduleIntervalDayOfWeek,\n): number {\n switch (dayOfWeek) {\n case 'sunday':\n return 0\n case 'monday':\n return 1\n case 'tuesday':\n return 2\n case 'wednesday':\n return 3\n case 'thursday':\n return 4\n case 'friday':\n return 5\n case 'saturday':\n return 6\n }\n}\n\n/**\n * Converts a ScheduleInterval to a cron pattern string.\n * For longer intervals (hour, day, week, etc.), you can customize when they run.\n *\n * @param interval - The schedule interval\n * @param options - Options to customize the cron pattern\n * @returns A cron pattern string\n *\n * @example\n * intervalToCron('minute') // '* * * * *' - every minute\n * intervalToCron('hour', { minute: 30 }) // '30 * * * *' - every hour at :30\n * intervalToCron('day', { hour: 14, minute: 30 }) // '30 14 * * *' - daily at 2:30 PM\n * intervalToCron('week', { dayOfWeek: 1, hour: 9 }) // '0 9 * * 1' - Mondays at 9 AM\n */\nexport function intervalToCron(\n interval: ScheduleInterval,\n options: IntervalCronOptions = {},\n): string {\n const { minute = 0, hour = 0, dayOfMonth = 1, dayOfWeek } = options\n\n const dayOfWeekNumber = dayOfWeekToNumber(dayOfWeek ?? 'sunday')\n\n const patterns: Record<ScheduleInterval, string> = {\n second: '* * * * * *',\n 'two seconds': '*/2 * * * * *',\n 'three seconds': '*/3 * * * * *',\n 'four seconds': '*/4 * * * * *',\n 'five seconds': '*/5 * * * * *',\n 'ten seconds': '*/10 * * * * *',\n 'fifteen seconds': '*/15 * * * * *',\n 'twenty seconds': '*/20 * * * * *',\n 'thirty seconds': '*/30 * * * * *',\n\n minute: '* * * * *',\n 'two minutes': '*/2 * * * *',\n 'three minutes': '*/3 * * * *',\n 'four minutes': '*/4 * * * *',\n 'five minutes': '*/5 * * * *',\n 'ten minutes': '*/10 * * * *',\n 'fifteen minutes': '*/15 * * * *',\n 'twenty minutes': '*/20 * * * *',\n 'thirty minutes': '*/30 * * * *',\n\n hour: `${minute} * * * *`,\n 'two hours': `${minute} */2 * * *`,\n 'three hours': `${minute} */3 * * *`,\n 'four hours': `${minute} */4 * * *`,\n 'five hours': `${minute} */5 * * *`,\n 'six hours': `${minute} */6 * * *`,\n 'seven hours': `${minute} */7 * * *`,\n 'eight hours': `${minute} */8 * * *`,\n 'nine hours': `${minute} */9 * * *`,\n 'ten hours': `${minute} */10 * * *`,\n 'eleven hours': `${minute} */11 * * *`,\n 'twelve hours': `${minute} */12 * * *`,\n\n day: `${minute} ${hour} * * *`,\n\n week: `${minute} ${hour} * * ${dayOfWeekNumber}`,\n sunday: `${minute} ${hour} * * 0`,\n monday: `${minute} ${hour} * * 1`,\n tuesday: `${minute} ${hour} * * 2`,\n wednesday: `${minute} ${hour} * * 3`,\n thursday: `${minute} ${hour} * * 4`,\n friday: `${minute} ${hour} * * 5`,\n saturday: `${minute} ${hour} * * 6`,\n\n month: `${minute} ${hour} ${dayOfWeek ? '*' : dayOfMonth} * ${dayOfWeek ? dayOfWeekNumber + '#1' : '*'}`,\n 'last day of month': `${minute} ${hour} L * *`,\n\n // quarter: `${minute} ${hour} ${dayOfWeek ? '*' : dayOfMonth} */3 ${dayOfWeek ? dayOfWeekNumber : '*'}`,\n // year: `${minute} ${hour} ${dayOfMonth} 1 ${dayOfWeek ? dayOfWeekNumber : '*'}`,\n }\n\n return patterns[interval]\n}\n","import { Cron } from 'croner'\n\n/**\n * Cron instance registry for internal use\n */\nexport class ScheduleRegistry {\n private static instances: Record<string, Cron> = {}\n\n public static add(name: string, cron: Cron): void {\n if (this.instances[name]) {\n throw new Error(`Cron instance with name '${name}' already exists`)\n }\n\n this.instances[name] = cron\n }\n\n public static all(): Record<string, Cron> {\n return this.instances\n }\n\n public static get(name: string): Cron | undefined {\n return this.instances[name]\n }\n\n public static clear(name?: string): void {\n if (name) {\n this.instances[name]?.stop()\n delete this.instances[name]\n } else {\n Object.values(this.instances).forEach((cron) => cron.stop())\n this.instances = {}\n }\n }\n}\n","import { MaybePromise } from '../types.js'\nimport {\n IntervalCronOptions,\n ScheduleInterval,\n ScheduleIntervalDayOfWeek,\n ScheduleIntervalTime,\n intervalToCron,\n parseTime,\n} from './schedule_interval.js'\nimport { ScheduleRegistry } from './schedule_registry.js'\n\nimport type { LockFactory } from '@verrou/core'\nimport type { SerializedLock } from '@verrou/core/types'\nimport { Duration } from '@verrou/core/types'\nimport { Cron } from 'croner'\nimport { createHash } from 'node:crypto'\n\nexport const getDistributedLockKey = (name: string) => {\n const hash = createHash('sha1').update(name).digest('hex').slice(0, 8)\n return `lavoro:schedule:${hash}`\n}\n\nexport class PendingSchedule {\n protected cronPattern?: string\n\n protected interval: ScheduleInterval = 'day'\n protected intervalOptions?: IntervalCronOptions\n\n protected distributedLockOptions: {\n /**\n * The lock key is based on the task name to ensure only one instance runs\n *\n * @param name - The task name\n * @returns The lock key\n */\n key: (name: string) => string\n /**\n * The lock TTL is the duration for which the lock is held\n */\n ttl: Duration\n /**\n * Whether to allow overlapping executions of the same task\n */\n overlap: boolean\n /**\n * Whether to hand off the lock to the queue worker\n */\n handOff: boolean\n } = {\n key: getDistributedLockKey,\n /**\n * Interval during which the lock is held for the job\n * and no other instances of it will not be scheduled\n */\n ttl: '15s',\n overlap: false,\n handOff: false,\n }\n\n constructor(\n protected name: string,\n protected cb: (lock?: SerializedLock) => MaybePromise<void>,\n protected lockProviderResolver: () => LockFactory,\n ) {}\n\n /**\n * Schedule using a cron pattern.\n * You can use https://crontab.guru to generate a cron pattern.\n *\n * @param pattern - Cron pattern string\n *\n * @example\n * Schedule.call('my-task', () => {}).cron('0 0 * * *') // Daily at midnight\n * Schedule.call('my-task', () => {}).cron('*\\/5 * * * *') // Every 5 minutes\n * Schedule.call('my-task', () => {}).cron('0 *\\/2 * * *') // Every 2 hours\n */\n public cron(pattern: string): this {\n this.cronPattern = pattern\n return this\n }\n\n /**\n * Schedule to run at a specific interval.\n * For longer intervals (hour, day, week, etc.), you can customize when they run.\n *\n * @param interval - The schedule interval\n * @param options - Options to customize the cron pattern\n *\n * @example\n * Schedule.call('my-task', () => {}).every('minute')\n * Schedule.call('my-task', () => {}).every('hour', { minute: 30 })\n * Schedule.call('my-task', () => {}).every('day', { hour: 14, minute: 30 })\n * Schedule.call('my-task', () => {}).every('week', { dayOfWeek: 1, hour: 9 })\n */\n public every(\n interval: ScheduleInterval,\n options?: IntervalCronOptions,\n ): this {\n this.interval = interval\n this.intervalOptions = options\n this.cronPattern = intervalToCron(interval, options)\n return this\n }\n\n public on(dayOfWeek: ScheduleIntervalDayOfWeek): this {\n // .on() only makes sense for intervals larger than 'day'\n const valid: ScheduleInterval[] = [\n //\n 'week',\n 'month',\n ]\n\n if (!valid.includes(this.interval)) {\n throw new Error(\n `.on() can only be used for weekly intervals or larger. Current interval: '${this.interval}'`,\n )\n }\n\n this.intervalOptions = { ...(this.intervalOptions ?? {}), dayOfWeek }\n this.cronPattern = intervalToCron(this.interval, this.intervalOptions)\n return this\n }\n\n public at(time: ScheduleIntervalTime): this {\n // .at() only makes sense for intervals larger than 'hour'\n const valid: ScheduleInterval[] = [\n 'day',\n 'week',\n 'sunday',\n 'monday',\n 'tuesday',\n 'wednesday',\n 'thursday',\n 'friday',\n 'saturday',\n 'month',\n 'last day of month',\n ]\n\n if (!valid.includes(this.interval)) {\n throw new Error(\n `.at() can only be used for daily intervals or larger. Current interval: '${this.interval}'`,\n )\n }\n\n const [hour, minute] = parseTime(time)\n this.intervalOptions = { ...(this.intervalOptions ?? {}), hour, minute }\n this.cronPattern = intervalToCron(this.interval, this.intervalOptions)\n return this\n }\n\n /**\n * Set the duration during which other instances\n * of the same task will be prevented from running.\n *\n * This should be roughly the duration of the task execution or longer\n * since the lock will be released automatically after the task execution.\n *\n * @param ttl - The lock duration\n *\n * @example\n * Schedule.call('my-task', () => {}).lockFor('10s')\n */\n public lockFor(ttl: Duration): this {\n this.distributedLockOptions.ttl = ttl\n return this\n }\n\n /**\n * Allow overlapping executions of the same task.\n *\n * @example\n * Schedule.call('my-task', () => {}).overlapping()\n */\n public overlapping(): this {\n this.distributedLockOptions.overlap = true\n return this\n }\n\n protected async execute(): Promise<void> {\n if (!this.cronPattern) {\n throw new Error(\n 'No schedule pattern defined. To schedule a task, set interval explicitly.',\n )\n }\n\n ScheduleRegistry.add(\n this.name,\n new Cron(this.cronPattern, async () => {\n // If overlapping is allowed, we can call the callback right away.\n if (this.distributedLockOptions.overlap) {\n await this.cb()\n return\n }\n\n // First, we create a distributed lock based on the task name,\n // which ensures that only one instance of the task runs at a time.\n const key = this.distributedLockOptions.key(this.name)\n\n // Resolve lock provider instance and create the lock.\n const lockProvider = this.lockProviderResolver()\n const lock = lockProvider.createLock(\n key,\n this.distributedLockOptions.ttl,\n )\n\n // If the lock is already locked, we skip the execution.\n // if (await lock.isLocked()) {\n // return\n // }\n\n const acquired = await lock.acquireImmediately()\n\n if (!acquired) {\n return\n }\n\n // If the lock was acquired, we run the task,\n // otherwise just skip it and do nothing.\n try {\n // If the lock is marked to be handed off to the queue\n // worker, we serialize and pass it to the callback.\n // Otherwise we just run the task and then release\n // the lock immediately.\n if (this.distributedLockOptions.handOff) {\n await this.cb(lock.serialize())\n } else {\n await this.cb()\n await lock.forceRelease()\n }\n } catch (error) {\n // If the task callback failed, we release\n // the lock and re-throw the error.\n await lock.forceRelease()\n throw error\n }\n }),\n )\n }\n\n /**\n * By defining the \"then\" method, PendingDispatch becomes \"thenable\",\n * allowing it to trigger automatically when await is called.\n */\n public async then<TResult1 = void, TResult2 = never>(\n onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n // When await is called, actually execte pending chain.\n return this.execute().then(onfulfilled, onrejected)\n }\n}\n","import { Job, Payload, PayloadWithLock } from '../queue/contracts/job.js'\nimport { QueueNameForConnection } from '../queue/contracts/queue_driver.js'\nimport { PendingDispatch } from '../queue/pending_dispatch.js'\nimport { DefaultConnection, QueueConnectionName } from '../queue/types.js'\nimport { PendingSchedule } from './pending_schedule.js'\n\nimport type { LockFactory } from '@verrou/core'\nimport type { SerializedLock } from '@verrou/core/types'\n\nexport class PendingJobSchedule<\n T extends Job,\n P extends Payload<T>,\n C extends QueueConnectionName = DefaultConnection extends { name: infer N }\n ? N extends QueueConnectionName\n ? N\n : QueueConnectionName\n : QueueConnectionName,\n> extends PendingSchedule {\n /**\n * Use composition pattern and store pending\n * job dispatch inside a pending schedule.\n */\n protected dispatch: PendingDispatch<T, PayloadWithLock<T, P>, C>\n\n private _connection?: string\n private _queue?: string\n\n private get jobName(): string {\n return `${this._connection}_${this._queue}_${this.job.name}`\n }\n\n constructor(\n protected job: T,\n protected payload: PayloadWithLock<T, P>,\n protected lockProviderResolver: () => LockFactory,\n ) {\n super(\n job.name,\n async (lock?: SerializedLock) => {\n if (lock) {\n this.payload._lock = lock\n }\n\n await this.dispatch.then(undefined, (error) => {\n throw error\n })\n },\n lockProviderResolver,\n )\n\n this.job = job\n this.payload = payload\n this.dispatch = new PendingDispatch(job, payload)\n\n this.distributedLockOptions.handOff = true\n }\n\n public onConnection<NewC extends QueueConnectionName>(\n connection: NewC,\n ): PendingJobSchedule<T, P, NewC> {\n this._connection = connection\n this.dispatch.onConnection(connection)\n // TypeScript can't track type parameter changes through `this`.\n // The instance is the same, but the type parameter C changes to NewC,\n // so we need to assert the type to the new type.\n return this as unknown as PendingJobSchedule<T, P, NewC>\n }\n\n public onQueue(queue: QueueNameForConnection<C>): this {\n this._queue = queue\n this.dispatch.onQueue(queue)\n\n return this\n }\n\n // public withQueueServiceResolver(queueServiceResolver: () => Promise<Queue>) {\n // this.dispatch.withQueueServiceResolver(queueServiceResolver)\n // return this\n // }\n\n protected async execute(): Promise<void> {\n // Before executing, update the lock provider resolver to use the one from the queue connection\n const queueServiceResolver = this.job.getQueueServiceResolver\n if (queueServiceResolver) {\n const queue = await queueServiceResolver()\n\n // Get the connection the job will use\n const connection =\n this.job.options.connection ?? queue.getDefaultConnection()\n\n // Override the lock service resolver to use the connection's lock provider\n const connectionLockService = queue.getLockProvider(connection)\n\n if (connectionLockService) {\n this.lockProviderResolver = () => connectionLockService\n }\n\n // Register this scheduled job with the queue service\n if (this.job.id) {\n queue.registerScheduledJob(this.job.id)\n }\n\n this._connection = this._connection ?? queue.getDefaultConnection()\n this._queue = this._queue ?? queue.getDefaultQueue()\n }\n\n this.name = this.jobName\n\n await super.execute()\n }\n}\n","import { Job, Payload, PayloadWithLock } from '../queue/contracts/job.js'\nimport { MaybePromise } from '../types.js'\nimport { PendingJobSchedule } from './pending_job_schedule.js'\nimport { PendingSchedule } from './pending_schedule.js'\nimport { ScheduleRegistry } from './schedule_registry.js'\n\nimport { LockFactory } from '@verrou/core'\nimport { memoryStore } from '@verrou/core/drivers/memory'\n\n/**\n * Default lock provider instance for distributed locking.\n * Uses memory store by default.\n */\nexport const defaultScheduleLockProvider = new LockFactory(\n memoryStore().factory(),\n)\n\nexport class Schedule {\n /**\n * Default lock provider resolver for distributed locking.\n * Returns the default memory-based instance if not overridden.\n */\n private static defaultLockProviderResolver: () => LockFactory = () =>\n defaultScheduleLockProvider\n\n /**\n * Set a custom lock provider resolver for distributed locking.\n *\n * This allows dynamic resolution of lock provider instances, useful when\n * integrating with Queue or other services that manage lock instances.\n *\n * @param resolver - Function that returns a LockFactory instance\n *\n * @example\n * import { LockFactory } from '@verrou/core'\n * import { redisStore } from '@verrou/core/drivers/redis'\n *\n * const customLockProvider = new LockFactory(\n * redisStore({ connection: redisClient })\n * )\n *\n * Schedule.setLockProviderResolver(() => customLockProvider)\n */\n public static setLockProviderResolver(resolver: () => LockFactory): void {\n this.defaultLockProviderResolver = resolver\n }\n\n /**\n * Get the current lock provider instance from the resolver.\n * @internal\n */\n public static getLockProvider(): LockFactory {\n return this.defaultLockProviderResolver()\n }\n\n /**\n * Clear all scheduled tasks (or specific one if name is specified).\n *\n * @param name - The name of the task to clear\n *\n * @example\n * Schedule.clear() // Clear all tasks\n * Schedule.clear('my-task') // Clear specific task\n */\n public static clear(name?: string): void {\n if (name) {\n ScheduleRegistry.clear(name)\n } else {\n Object.keys(ScheduleRegistry.all()).forEach((name) =>\n ScheduleRegistry.clear(name),\n )\n }\n }\n\n /**\n * Schedule a callback to run at specified intervals.\n *\n * @param name - Unique identifier for the task (required for distributed systems)\n * @param cb - The callback function to execute\n *\n * @example\n * // Using cron pattern\n * const cleanupUsers = async () => { ... }\n * Schedule.call('cleanup-users', cleanupUsers).cron('0 0 * * *')\n *\n * // Using convenience methods\n * Schedule.call('hourly-task', () => { ... }).hourly()\n * Schedule.call('daily-task', () => { ... }).daily()\n */\n public static call(name: string, cb: () => MaybePromise<void>) {\n return new PendingSchedule(name, cb, this.defaultLockProviderResolver)\n }\n\n /**\n * Schedule a job to run at specified intervals.\n *\n * You can specify the connection and queue to use for the job\n * the same way you would dispatch a job.\n *\n * @param job - The job class to schedule\n * @param payload - The payload to pass to the job\n *\n * @example\n * Schedule.job(TestJob, { arg1: 'hello', arg2: 1 }).every('minute')\n * Schedule.job(TestJob, { arg1: 'hello', arg2: 1 })\n * .onConnection('main')\n * .onQueue('default')\n * .every('minute')\n */\n public static job<T extends Job, P extends Payload<T>>(\n job: new () => T,\n payload: P,\n ): PendingJobSchedule<T, P> {\n return new PendingJobSchedule<T, P>(\n new job(),\n payload as PayloadWithLock<T, P>,\n this.defaultLockProviderResolver,\n )\n }\n}\n","import {\n QueueDriverEventEmitter,\n QueueDriverEvents,\n} from './contracts/queue_driver_event_emitter.js'\n\n/**\n * Queue service can emit any of the queue driver\n * events alongside its own events (currently none).\n */\nexport interface QueueEvents extends QueueDriverEvents {}\n\n/**\n * Type-safe event emitter for the queue service.\n */\nexport abstract class QueueEventEmitter extends QueueDriverEventEmitter {\n public override on<K extends keyof QueueEvents>(\n event: K,\n listener: (...args: QueueEvents[K]) => void,\n ): this {\n return super.on(event, listener)\n }\n\n public override emit<K extends keyof QueueEvents>(\n event: K,\n ...args: QueueEvents[K]\n ): boolean {\n return super.emit(event, ...args)\n }\n}\n","import { Logger, createDefaultLogger } from '../logger.js'\nimport { Schedule } from '../schedule/schedule.js'\nimport { Job, Payload } from './contracts/job.js'\nimport {\n QueueDriver,\n QueueDriverStopOptions,\n QueueName,\n} from './contracts/queue_driver.js'\nimport { QueueDriverEvents } from './contracts/queue_driver_event_emitter.js'\nimport { QueueEventEmitter } from './queue_event_emitter.js'\nimport type {\n QueueConfig,\n QueueConnectionConfig,\n QueueConnectionName,\n} from './types.js'\n\nimport type { LockFactory } from '@verrou/core'\n\nexport class Queue extends QueueEventEmitter {\n private drivers: Map<QueueConnectionName, QueueDriver> = new Map()\n private started: boolean = false\n private logger: Logger\n private scheduledJobs: Set<string> = new Set()\n private lockFactories: Map<QueueConnectionName, LockFactory> = new Map()\n\n constructor(private config: QueueConfig & { logger?: Logger }) {\n super()\n\n this.logger = config?.logger || createDefaultLogger('queue')\n\n for (const [connection, driverConfig] of Object.entries(\n this.config.connections,\n )) {\n this.logger.trace(\n { connection, driver: driverConfig.driver },\n 'Creating queue driver',\n )\n\n const driver = this.createDriver(driverConfig)\n driver.connection = connection as QueueConnectionName\n\n this.bindEvents(driver)\n\n this.drivers.set(driver.connection, driver)\n }\n }\n\n /**\n * Bind all queue driver events and\n * proxy them through the queue service.\n */\n private bindEvents(driver: QueueDriver) {\n const events = [\n 'error',\n 'job:start',\n 'job:progress',\n 'job:complete',\n 'job:error',\n 'job:finish',\n ] as const\n\n for (const event of events) {\n driver.on(event, (...args) => {\n this.emit(event, ...(args as QueueDriverEvents[typeof event]))\n })\n }\n }\n\n private createDriver(\n config: QueueConnectionConfig<QueueDriver>,\n ): QueueDriver {\n const { constructor: driverConstructor, config: driverConfig } =\n config.driver\n\n const driver = new driverConstructor(\n this.config,\n config.queues,\n driverConfig,\n )\n\n driver.setLogger(this.logger)\n\n return driver\n }\n\n async start() {\n if (this.started) {\n this.logger.warn('Queue service already started')\n return\n }\n\n /**\n * Create lock factories for each connection.\n * If no lock provider was explicitly configured,\n * create a driver-specific lock factory.\n */\n for (const [connection, driverConfig] of Object.entries(\n this.config.connections,\n )) {\n const driver = this.drivers.get(connection as QueueConnectionName)\n if (!driver) {\n throw new Error(`Driver not found for connection: ${connection}.`)\n }\n\n /**\n * Create driver-specific lock factory if\n * no lock provider was explicitly configured.\n */\n if (!driverConfig.lockProvider) {\n const lockFactory = driver.createLockProvider()\n if (lockFactory) {\n this.lockFactories.set(connection as QueueConnectionName, lockFactory)\n this.logger.trace(\n { connection, driver: driverConfig.driver },\n 'Created lock factory for driver',\n )\n }\n } else {\n this.lockFactories.set(\n connection as QueueConnectionName,\n driverConfig.lockProvider,\n )\n this.logger.trace(\n { connection, driver: driverConfig.driver },\n 'Using explicitly configured lock provider for driver',\n )\n }\n }\n\n for (const job of this.config.jobs) {\n await this.register(job)\n }\n\n this.started = true\n\n for (const [connection, driver] of this.drivers) {\n this.logger.trace({ connection }, 'Starting queue connection')\n await driver.start()\n }\n\n this.logger.trace(\n { connections: Array.from(this.drivers.keys()) },\n 'Queue service started',\n )\n }\n\n async stop(\n options: QueueDriverStopOptions = {\n graceful: true,\n timeout: 30000,\n },\n ) {\n if (!this.started) {\n this.logger.warn('Queue service not started')\n return\n }\n\n this.logger.trace(\n { count: this.scheduledJobs.size },\n 'Cleared scheduled jobs for the queue',\n )\n\n // Clear all scheduled jobs registered with this Queue instance\n for (const id of this.scheduledJobs) {\n Schedule.clear(id)\n }\n\n this.scheduledJobs.clear()\n\n for (const job of this.config.jobs) {\n await this.unregister(job)\n }\n\n for (const [connection, driver] of this.drivers) {\n this.logger.trace({ connection }, 'Stopping queue connection')\n await driver.stop(options)\n }\n\n /**\n * Destroy lock factories for each connection.\n */\n for (const [connection, lockFactory] of this.lockFactories) {\n const driver = this.drivers.get(connection as QueueConnectionName)\n if (!driver) {\n throw new Error(`Driver not found for connection: ${connection}.`)\n }\n\n await driver.destroyLockProvider(lockFactory)\n this.lockFactories.delete(connection as QueueConnectionName)\n }\n\n this.started = false\n\n this.logger.trace('Queue service stopped')\n }\n\n protected async register(job: new () => Job): Promise<void> {\n for (const [_, driver] of this.drivers) {\n await driver.register(job)\n }\n }\n\n protected async unregister(job: new () => Job): Promise<void> {\n for (const [_, driver] of this.drivers) {\n await driver.unregister(job)\n }\n }\n\n public async enqueue<T extends Job, P extends Payload<T>>(\n job: T,\n payload: P,\n ): Promise<void> {\n if (this.drivers.size === 0) {\n throw new Error('No queue drivers available.')\n }\n\n /**\n * Try to get driver from connection if specified\n * otherwise use the first available driver.\n */\n const driver: QueueDriver | undefined = job.options.connection\n ? this.drivers.get(job.options.connection)\n : this.drivers.values().next().value\n\n if (!driver) {\n throw new Error(\n `No driver found for connection: ${job.options.connection}.`,\n )\n }\n\n if (!job.options.queue) {\n job.options.queue = driver.getDefaultQueue()\n }\n\n await driver.enqueue(job, payload)\n }\n\n /**\n * Get the default connection name.\n *\n * Returns the name of the first available connection.\n * Throws an error if no connections are available.\n */\n public getDefaultConnection(): QueueConnectionName {\n if (this.drivers.size === 0) {\n throw new Error(`No queue drivers available.`)\n }\n\n return this.drivers.keys().next().value as QueueConnectionName\n }\n\n public getDefaultQueue(): QueueName {\n if (this.drivers.size === 0) {\n throw new Error(`No queue drivers available.`)\n }\n\n return this.drivers.values().next().value?.getDefaultQueue() as QueueName\n }\n\n /**\n * Get the lock factory instance for a specific connection.\n * Returns the explicitly configured lock provider or the auto-created lock factory.\n * Throws an error if no lock factory is available.\n *\n * @param connection - The connection name\n * @returns The lock factory instance\n */\n public getLockProvider(connection: QueueConnectionName): LockFactory {\n const connectionConfig = this.config.connections[connection]\n\n // Return explicitly configured lock provider if available\n if (connectionConfig?.lockProvider) {\n return connectionConfig.lockProvider\n }\n\n // Return auto-created lock factory\n const lockFactory = this.lockFactories.get(connection)\n\n if (!lockFactory) {\n throw new Error(`No lock provider found for connection: ${connection}.`)\n }\n\n return lockFactory\n }\n\n /**\n * Register a scheduled job ID with this Queue instance.\n * This allows the Queue to clean up scheduled jobs when it stops.\n */\n public registerScheduledJob(id: string): void {\n this.scheduledJobs.add(id)\n }\n}\n"],"mappings":"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","names":["name"]}
1
+ {"version":3,"sources":["../src/logger.ts","../src/queue/define_config.ts","../src/queue/pending_dispatch.ts","../src/queue/contracts/job.ts","../src/queue/contracts/queue_driver_event_emitter.ts","../src/queue/contracts/queue_driver.ts","../src/schedule/schedule_interval.ts","../src/schedule/schedule_registry.ts","../src/schedule/pending_schedule.ts","../src/schedule/pending_job_schedule.ts","../src/schedule/schedule.ts","../src/queue/queue_event_emitter.ts","../src/queue/queue.ts"],"sourcesContent":["import type {\n Logger as InternalLogger,\n Levels,\n LogObject,\n} from '@julr/utils/logger'\n\n/**\n * No-op logger implementation used as fallback when pino is not installed\n */\nclass NoOpLogger implements InternalLogger {\n level: Levels = 'trace'\n\n child(_obj: LogObject): InternalLogger {\n return this\n }\n\n trace(_msg: any, _obj?: any): void {}\n debug(_msg: any, _obj?: any): void {}\n info(_msg: any, _obj?: any): void {}\n warn(_msg: any, _obj?: any): void {}\n error(_msg: any, _obj?: any): void {}\n fatal(_msg: any, _obj?: any): void {}\n}\n\nexport class Logger {\n private internalLogger: InternalLogger\n\n constructor(internalLogger: InternalLogger) {\n this.internalLogger = internalLogger\n }\n\n child(obj: LogObject) {\n return new Logger(this.internalLogger.child(obj))\n }\n\n trace(msg: any, obj?: any) {\n this.internalLogger.trace(msg, obj)\n }\n\n debug(msg: any, obj?: any) {\n this.internalLogger.debug(msg, obj)\n }\n\n warn(msg: any, obj?: any) {\n this.internalLogger.warn(msg, obj)\n }\n\n error(msg: any, obj?: any) {\n this.internalLogger.error(msg, obj)\n }\n\n fatal(msg: any, obj?: any) {\n this.internalLogger.fatal(msg, obj)\n }\n\n info(msg: any, obj?: any) {\n this.internalLogger.info(msg, obj)\n }\n}\n\nexport function createDefaultLogger(\n name: string,\n level: Levels = 'info',\n): Logger {\n try {\n // Try to require pino synchronously\n const pino = require('pino')\n return new Logger(pino({ name, level }))\n } catch {\n // Fallback to no-op logger if pino is not installed\n return new Logger(new NoOpLogger())\n }\n}\n","import type { QueueConfig, QueueConnectionsList } from './types.js'\n\nimport { RuntimeException } from '@poppinss/utils'\n\ntype QueueConfigWithConnections<Connections, Connection> = QueueConfig & {\n connection: Connection\n connections: Connections\n}\n\n/**\n * Define config for queue service.\n *\n * @example\n * ```ts\n * // config/queue.ts\n * import { memory } from '@lavoro/memory'\n * import { postgres } from '@lavoro/postgres'\n *\n * const config = {\n * jobs: [...],\n * connection: 'main',\n * connections: {\n * main: {\n * driver: memory(),\n * queues: {\n * default: { concurrency: 1 },\n * emails: { concurrency: 3 },\n * },\n * },\n * background: {\n * driver: postgres({ ... }),\n * queues: {\n * 'heavy-tasks': { concurrency: 2 },\n * reports: { concurrency: 1 },\n * },\n * },\n * },\n * }\n *\n * const queueConfig = defineConfig(config)\n *\n * // Type augmentation to enable type-safe queue names\n * declare module '@lavoro/core' {\n * interface QueueList extends InferQueueNames<typeof config> {}\n * interface DefaultConnection {\n * name: InferDefaultConnection<typeof config>\n * }\n * interface QueueConnections extends InferConnections<typeof config> {}\n * interface ConnectionQueues extends InferConnectionQueues<typeof config> {}\n * }\n * ```\n *\n * After defining your queue names, you'll get autocomplete and type checking:\n * ```ts\n * await queue.listen('emails') // ✓ Valid\n * await queue.listen('heavy-tasks') // ✓ Valid\n * await queue.listen('invalid') // ✗ Type error\n *\n * await job.dispatch(payload).onQueue('emails') // ✓ Valid\n * await job.dispatch(payload).onQueue('typo') // ✗ Type error\n * ```\n */\nexport function defineConfig<\n const Connections extends QueueConnectionsList,\n const Connection extends keyof Connections = keyof Connections,\n>(\n config: QueueConfigWithConnections<Connections, Connection>,\n): QueueConfigWithConnections<Connections, Connection> {\n // Validate required fields\n if (!config.connection) {\n throw new RuntimeException(\n 'Missing \"connection\" property in queue config file',\n )\n }\n\n if (!config.connections) {\n throw new RuntimeException(\n 'Missing \"connections\" property in queue config file',\n )\n }\n\n // Validate default connection exists\n if (!config.connections[config.connection as string]) {\n throw new RuntimeException(\n `Missing \"connections.${String(config.connection)}\". It is referenced by the \"connection\" property`,\n )\n }\n\n // Validate each connection has queues\n Object.keys(config.connections).forEach((connectionName) => {\n const connection =\n config.connections[connectionName as keyof typeof config.connections]\n if (!connection.queues || Object.keys(connection.queues).length === 0) {\n throw new RuntimeException(\n `Connection \"${connectionName}\" must have at least one queue defined`,\n )\n }\n })\n\n return config\n}\n","import { Job, Payload } from './contracts/job.js'\nimport { QueueName, QueueNameForConnection } from './contracts/queue_driver.js'\nimport { DefaultConnection, QueueConnectionName } from './types.js'\n\nexport class PendingDispatch<\n T extends Job,\n P extends Payload<T>,\n C extends QueueConnectionName = DefaultConnection extends { name: infer N }\n ? N extends QueueConnectionName\n ? N\n : QueueConnectionName\n : QueueConnectionName,\n> {\n constructor(\n protected job: T,\n protected payload: P,\n ) {}\n\n public onConnection<NewC extends QueueConnectionName>(\n connection: NewC,\n ): PendingDispatch<T, P, NewC> {\n this.job.options.connection = connection\n\n return this as unknown as PendingDispatch<T, P, NewC>\n }\n\n public onQueue(queue: QueueNameForConnection<C>) {\n this.job.options.queue = queue as QueueName\n\n return this\n }\n\n // public withQueueServiceResolver(\n // queueServiceResolver: () => Promise<Queue>,\n // ): this {\n // this.job.setQueueServiceResolver(queueServiceResolver)\n\n // return this\n // }\n\n protected async execute(): Promise<void> {\n if (!this.job.getQueueServiceResolver) {\n throw new Error(\n 'Queue service resolver is not set.\\nDid you forget to call Job.setDefaultQueueServiceResolver()?',\n )\n }\n\n const queue = await this.job.getQueueServiceResolver()\n await queue.enqueue(this.job, this.payload)\n }\n\n /**\n * By defining the \"then\" method, PendingDispatch becomes \"thenable\",\n * allowing it to trigger automatically when await is called.\n */\n public async then<TResult1 = void, TResult2 = never>(\n onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n // When await is called, actually execte pending chain.\n return this.execute().then(onfulfilled, onrejected)\n }\n}\n","import { PendingDispatch } from '../pending_dispatch.js'\nimport { Queue } from '../queue.js'\nimport { QueueConnectionName } from '../types.js'\n\nimport { SerializedLock } from '@verrou/core/types'\nimport { randomUUID } from 'node:crypto'\n\nexport type Payload<T extends Job> = T extends Job<infer P> ? P : unknown\n\nexport type PayloadWithLock<T extends Job, P extends Payload<T>> = P & {\n _lock?: SerializedLock\n}\n\nexport type Options = {\n connection?: QueueConnectionName\n queue?: string\n retries: number\n delay: number\n}\n\nexport abstract class Job<P = unknown> {\n private _id: string = randomUUID()\n\n public options: Options = {\n retries: 3,\n delay: 0,\n }\n\n public static compileName(queue: string, name: string): string {\n return `${queue}_${name}`\n }\n\n public static parseName(name: string): { queue: string; name: string } {\n const [q, n] = name.split(/_(.+)/) // split on the first underscore only\n return { queue: q, name: n }\n }\n\n public get connection(): QueueConnectionName | undefined {\n return this.options.connection\n }\n\n public set connection(connection: QueueConnectionName | undefined) {\n this.options.connection = connection\n }\n\n public get queue(): string | undefined {\n return this.options.queue\n }\n\n public set queue(queue: string | undefined) {\n this.options.queue = queue\n }\n\n public get name(): string {\n return this.constructor.name\n }\n\n public get id(): string {\n return this._id\n }\n\n public set id(id: string) {\n this._id = id\n }\n\n public get fullyQualifiedName(): string {\n if (!this.options.queue) {\n throw new Error('Queue is not set.')\n }\n\n return Job.compileName(this.options.queue, this.name)\n }\n\n private static defaultQueueServiceResolver: () => Promise<Queue>\n\n public static setDefaultQueueServiceResolver(\n queueServiceResolver: () => Promise<Queue>,\n ): void {\n this.defaultQueueServiceResolver = queueServiceResolver\n }\n\n public setQueueServiceResolver(\n queueServiceResolver: () => Promise<Queue>,\n ): void {\n this.queueServiceResolver = queueServiceResolver\n }\n\n private queueServiceResolver?: () => Promise<Queue> = undefined\n\n public get getQueueServiceResolver(): () => Promise<Queue> {\n return this.queueServiceResolver || Job.defaultQueueServiceResolver\n }\n\n /**\n * Handle the job with the typed payload.\n */\n public abstract handle(payload: P): Promise<void>\n\n /**\n * Dispatch a job of type with a typed payload.\n */\n public static dispatch<T extends Job, P extends Payload<T>>(\n this: new () => T,\n payload: P,\n ): PendingDispatch<T, P> {\n const job = new this() as T\n return new PendingDispatch<T, P>(job, payload)\n }\n}\n","import { Job } from './job.js'\n\nimport { EventEmitter } from 'events'\n\n/**\n * Type-safe queue driver events.\n */\nexport interface QueueDriverEvents {\n error: [error: Error]\n 'job:start': [job: Job, payload: unknown]\n 'job:progress': [job: Job, payload: unknown, elapsed: number]\n 'job:complete': [job: Job, payload: unknown, elapsed: number]\n 'job:error': [error: Error, job: Job, payload: unknown]\n 'job:finish': [job: Job, payload: unknown, elapsed: number]\n}\n\n/**\n * Type-safe event emitter for the queue driver.\n */\nexport abstract class QueueDriverEventEmitter extends EventEmitter {\n public override on<K extends keyof QueueDriverEvents>(\n event: K,\n listener: (...args: QueueDriverEvents[K]) => void,\n ): this {\n return super.on(event, listener)\n }\n\n public override off<K extends keyof QueueDriverEvents>(\n event: K,\n listener: (...args: QueueDriverEvents[K]) => void,\n ): this {\n return super.off(event, listener)\n }\n\n public override emit<K extends keyof QueueDriverEvents>(\n event: K,\n ...args: QueueDriverEvents[K]\n ): boolean {\n /**\n * Avoid throwing error even if there are no listeners\n * for the `error` event (special case, see:\n * https://nodejs.org/api/events.html#error-events).\n */\n if (this.listenerCount(event) === 0) {\n return false\n }\n\n return super.emit(event, ...args)\n }\n}\n","import { Logger, createDefaultLogger } from '../../logger.js'\nimport { QueueConfig, QueueConnectionName, WorkerOptions } from '../types.js'\nimport { Job, Payload } from './job.js'\nimport { QueueDriverEventEmitter } from './queue_driver_event_emitter.js'\n\nimport type { Lock, LockFactory } from '@verrou/core'\nimport type { SerializedLock } from '@verrou/core/types'\n\nexport type ProcessJobParams = {\n id: string\n fullyQualifiedName: string\n payload: unknown\n}\n\n/**\n * Interface to be augmented by users to define their queue names.\n * This enables type-safe queue names throughout the application.\n */\nexport interface QueueList {}\n\n/**\n * Interface to be augmented by users to map connections to their queue names.\n * This enables connection-specific type-safe queue names.\n */\nexport interface ConnectionQueues {}\n\n/**\n * Extract queue names from QueueList.\n * Defaults to string if no queues are defined.\n */\nexport type QueueName = keyof QueueList extends never ? string : keyof QueueList\n\n/**\n * Extract queue names for a specific connection from ConnectionQueues.\n */\nexport type QueueNameForConnection<C extends QueueConnectionName> =\n C extends keyof ConnectionQueues ? ConnectionQueues[C] : QueueName\n\nexport type QueueDriverStopOptions = {\n /**\n * Whether to wait for the jobs to finish processing before stopping.\n *\n * Default: true\n */\n graceful?: boolean\n\n /**\n * The timeout in milliseconds to wait for the jobs to finish processing.\n *\n * Default: 30000 (30 seconds)\n */\n timeout?: number\n}\n\nexport type QueueDriverConfig = {}\n\nexport abstract class QueueDriver<\n Config extends QueueDriverConfig = QueueDriverConfig,\n> extends QueueDriverEventEmitter {\n protected logger: Logger\n\n protected registeredQueues: Set<string> = new Set()\n\n protected registeredJobs: Map<string, new () => Job> = new Map()\n\n protected lockFactory?: LockFactory\n\n public connection: QueueConnectionName | undefined\n\n constructor(\n protected config: QueueConfig,\n protected options: Record<string, WorkerOptions>,\n protected driverConfig: Config = {} as Config,\n ) {\n super()\n this.logger = createDefaultLogger('queue')\n }\n\n public setLogger(logger: Logger): void {\n this.logger = logger\n }\n\n protected getMergedWorkerOptions(\n queue: QueueName,\n options?: WorkerOptions,\n ): WorkerOptions {\n const base = this.options[queue] || {}\n return { ...base, ...(options || {}) }\n }\n\n public async listen(\n queue: QueueName,\n options?: WorkerOptions,\n ): Promise<void> {\n if (this.registeredQueues.has(queue as string)) {\n throw new Error(`Queue '${queue as string}' already registered`)\n }\n\n this.registeredQueues.add(queue as string)\n\n const workerOptions = this.getMergedWorkerOptions(queue, options)\n\n this.logger.trace(\n { connection: this.connection, queue, options: workerOptions },\n 'Listening queue',\n )\n }\n\n public async register(job: new () => Job): Promise<void> {\n if (this.registeredJobs.has(job.name)) {\n return\n }\n\n this.registeredJobs.set(job.name, job)\n\n this.logger.trace(\n { connection: this.connection, job: job.name },\n 'Registered job',\n )\n }\n\n public async unregister(job: new () => Job): Promise<void> {\n if (!this.registeredJobs.has(job.name)) {\n return\n }\n\n this.registeredJobs.delete(job.name)\n\n this.logger.trace(\n { connection: this.connection, job: job.name },\n 'Unregistered job',\n )\n }\n\n public async start(): Promise<void> {\n for (const [queue, options] of Object.entries(this.options)) {\n await this.listen(queue as QueueName, options)\n }\n }\n\n public async stop(_options?: QueueDriverStopOptions): Promise<void> {\n this.registeredQueues.clear()\n this.registeredJobs.clear()\n }\n\n protected checkIfQueueIsRegistered(queue: string): void {\n if (!this.registeredQueues.has(queue)) {\n throw new Error(`Queue '${queue}' is not registered.`)\n }\n }\n\n protected checkIfJobIsRegistered(job: string): void {\n if (!this.registeredJobs.has(job)) {\n throw new Error(`Job '${job}' is not registered.`)\n }\n }\n\n public getDefaultQueue(): QueueName {\n if (this.registeredQueues.size === 0) {\n throw new Error(\n `No queues registered for connection: ${this.connection}.`,\n )\n }\n\n return this.registeredQueues.values().next().value as QueueName\n }\n\n /**\n * Parent method to be extended by the driver.\n * It implements checks for the job and queue being registered.\n */\n public async enqueue<T extends Job, P extends Payload<T>>(\n job: T,\n // @ts-ignore\n payload: P,\n ): Promise<void> {\n if (!job.options.queue) {\n job.options.queue = this.getDefaultQueue()\n }\n\n this.checkIfQueueIsRegistered(job.options.queue)\n this.checkIfJobIsRegistered(job.name)\n\n return Promise.resolve()\n }\n\n /**\n * Create a lock factory instance for this driver.\n *\n * Each driver implementation should return a\n * [Verrou LockFactory instance](https://verrou.dev/docs/quick-setup#lockfactory-api)\n * that matches the driver's backing store.\n *\n * @returns A LockFactory instance\n */\n public abstract createLockProvider(): LockFactory\n\n /**\n * Clean up resources associated with a lock factory created by this driver.\n * This is called when the queue is stopped to ensure proper resource cleanup.\n *\n * @param lockFactory - The lock factory instance to clean up\n */\n public async destroyLockProvider(_lockFactory: LockFactory): Promise<void> {\n // Default implementation does nothing\n // Drivers that need cleanup (e.g., Postgres with Knex) should override this\n }\n\n /**\n * Execute a job with the given parameters.\n * This method contains the common job processing logic shared by all drivers.\n */\n protected async process(params: ProcessJobParams): Promise<void> {\n const { id, fullyQualifiedName, payload } = params\n const { queue, name } = Job.parseName(fullyQualifiedName)\n\n if (!queue || !name) {\n const error = new Error(`Invalid job class name: ${fullyQualifiedName}`)\n this.logger.warn(error)\n throw error\n }\n\n this.logger.trace({ job: name }, 'Processing job')\n\n try {\n this.checkIfJobIsRegistered(name)\n } catch (error) {\n this.logger.warn(error)\n throw error\n }\n\n const jobClass = this.registeredJobs.get(name)!\n\n const jobInstance = new jobClass()\n\n jobInstance.connection = this.connection\n jobInstance.queue = queue\n jobInstance.id = id\n\n this.logger.debug(\n {\n connection: this.connection,\n queue,\n job: name,\n id,\n },\n 'Processing job',\n )\n\n /**\n * A job might have been scheduled by the scheduler,\n * in which case we need to restore the lock from the payload.\n *\n * This will prevent the job from being scheduled\n * while it is being processed.\n */\n const serializedLock = (payload as any)?._lock as SerializedLock | undefined\n const ttl = serializedLock?.ttl\n\n let lock: Lock | undefined\n\n if (serializedLock !== undefined) {\n if (this.lockFactory === undefined) {\n this.logger.warn(\n { job: name, id },\n 'Scheduled job has lock but lock factory is not available',\n )\n } else {\n try {\n lock = this.lockFactory.restoreLock(serializedLock)\n await lock.acquireImmediately()\n\n if (ttl) {\n await lock.extend(ttl)\n }\n\n this.logger.trace(\n {\n job: name,\n id,\n serializedLock,\n },\n 'Restored lock from scheduler',\n )\n } catch (error) {\n this.logger.warn({ job: name, id, error }, 'Failed to restore lock')\n }\n }\n }\n\n const startedAt = Date.now()\n\n this.emit('job:start', jobInstance, payload)\n\n let isExtending = false\n\n const onProgress = async () => {\n if (lock && ttl && !isExtending) {\n try {\n const remainingTime = lock.getRemainingTime()\n\n /**\n * Extend lock if remaining time drops below half the TTL.\n * This acts as a heartbeat to prevent the lock from expiring\n * while the job is still running, without unnecessary extensions\n * for short jobs.\n */\n if (remainingTime !== null && remainingTime <= ttl / 2) {\n isExtending = true\n this.logger.trace(\n { job: name, id, remainingTime, ttl },\n 'Extending lock',\n )\n await lock.extend(ttl)\n }\n } catch (error) {\n this.logger.warn({ job: name, id, error }, 'Failed to extend lock')\n } finally {\n isExtending = false\n }\n }\n\n this.emit('job:progress', jobInstance, payload, Date.now() - startedAt)\n }\n\n const intervalId = setInterval(onProgress, 1000)\n\n /**\n * Next, we process the actual job.\n */\n try {\n await jobInstance.handle(payload)\n\n this.emit('job:complete', jobInstance, payload, Date.now() - startedAt)\n\n this.logger.trace(\n {\n connection: this.connection,\n queue,\n job: name,\n id,\n },\n 'Job completed',\n )\n } catch (error) {\n this.emit('job:error', error, jobInstance, payload)\n } finally {\n this.emit('job:finish', jobInstance, payload, Date.now() - startedAt)\n /**\n * Once the job is done with any status,\n * we must clear the interval.\n */\n clearInterval(intervalId)\n\n /**\n * If we previously acquired a lock for\n * this job, we need to release it here.\n */\n if (lock) {\n try {\n await lock.forceRelease()\n\n this.logger.trace(\n { job: name, id, lock: lock.serialize() },\n 'Released lock for scheduled job',\n )\n } catch (error) {\n this.logger.warn({ job: name, id, error }, 'Failed to release lock')\n }\n }\n }\n }\n}\n","export type ScheduleInterval =\n | 'second'\n | 'two seconds'\n | 'three seconds'\n | 'four seconds'\n | 'five seconds'\n | 'ten seconds'\n | 'fifteen seconds'\n | 'twenty seconds'\n | 'thirty seconds'\n | 'minute'\n | 'two minutes'\n | 'three minutes'\n | 'four minutes'\n | 'five minutes'\n | 'ten minutes'\n | 'fifteen minutes'\n | 'twenty minutes'\n | 'thirty minutes'\n | 'hour'\n | 'two hours'\n | 'three hours'\n | 'four hours'\n | 'five hours'\n | 'six hours'\n | 'seven hours'\n | 'eight hours'\n | 'nine hours'\n | 'ten hours'\n | 'eleven hours'\n | 'twelve hours'\n | 'day'\n | 'week'\n | 'sunday'\n | 'monday'\n | 'tuesday'\n | 'wednesday'\n | 'thursday'\n | 'friday'\n | 'saturday'\n | 'month'\n | 'last day of month'\n// | 'quarter'\n// | 'year'\n\nexport type ScheduleIntervalDayOfWeek =\n | 'sunday'\n | 'monday'\n | 'tuesday'\n | 'wednesday'\n | 'thursday'\n | 'friday'\n | 'saturday'\n\ntype Hour = `${0 | 1 | 2}${0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`\ntype Minute = `${0 | 1 | 2 | 3 | 4 | 5}${0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`\n\nexport type ScheduleIntervalTime = `${Hour}:${Minute}`\n\nexport function parseTime(time: ScheduleIntervalTime): [number, number] {\n const [hour, minute] = time.split(':')\n\n if (!hour || !minute || hour.length !== 2 || minute.length !== 2) {\n throw new Error('Invalid time format')\n }\n\n return [Number(hour), Number(minute)]\n}\n\nexport interface IntervalCronOptions {\n /** Minute to run. Default: 0 */\n minute?: number\n /** Hour to run. Default: 0 */\n hour?: number\n /** Day of month to run. Default: 1 */\n dayOfMonth?: number\n /** Day of week to run. Default: 0 */\n dayOfWeek?: ScheduleIntervalDayOfWeek\n}\n\nexport function dayOfWeekToNumber(\n dayOfWeek: ScheduleIntervalDayOfWeek,\n): number {\n switch (dayOfWeek) {\n case 'sunday':\n return 0\n case 'monday':\n return 1\n case 'tuesday':\n return 2\n case 'wednesday':\n return 3\n case 'thursday':\n return 4\n case 'friday':\n return 5\n case 'saturday':\n return 6\n }\n}\n\n/**\n * Converts a ScheduleInterval to a cron pattern string.\n * For longer intervals (hour, day, week, etc.), you can customize when they run.\n *\n * @param interval - The schedule interval\n * @param options - Options to customize the cron pattern\n * @returns A cron pattern string\n *\n * @example\n * intervalToCron('minute') // '* * * * *' - every minute\n * intervalToCron('hour', { minute: 30 }) // '30 * * * *' - every hour at :30\n * intervalToCron('day', { hour: 14, minute: 30 }) // '30 14 * * *' - daily at 2:30 PM\n * intervalToCron('week', { dayOfWeek: 1, hour: 9 }) // '0 9 * * 1' - Mondays at 9 AM\n */\nexport function intervalToCron(\n interval: ScheduleInterval,\n options: IntervalCronOptions = {},\n): string {\n const { minute = 0, hour = 0, dayOfMonth = 1, dayOfWeek } = options\n\n const dayOfWeekNumber = dayOfWeekToNumber(dayOfWeek ?? 'sunday')\n\n const patterns: Record<ScheduleInterval, string> = {\n second: '* * * * * *',\n 'two seconds': '*/2 * * * * *',\n 'three seconds': '*/3 * * * * *',\n 'four seconds': '*/4 * * * * *',\n 'five seconds': '*/5 * * * * *',\n 'ten seconds': '*/10 * * * * *',\n 'fifteen seconds': '*/15 * * * * *',\n 'twenty seconds': '*/20 * * * * *',\n 'thirty seconds': '*/30 * * * * *',\n\n minute: '* * * * *',\n 'two minutes': '*/2 * * * *',\n 'three minutes': '*/3 * * * *',\n 'four minutes': '*/4 * * * *',\n 'five minutes': '*/5 * * * *',\n 'ten minutes': '*/10 * * * *',\n 'fifteen minutes': '*/15 * * * *',\n 'twenty minutes': '*/20 * * * *',\n 'thirty minutes': '*/30 * * * *',\n\n hour: `${minute} * * * *`,\n 'two hours': `${minute} */2 * * *`,\n 'three hours': `${minute} */3 * * *`,\n 'four hours': `${minute} */4 * * *`,\n 'five hours': `${minute} */5 * * *`,\n 'six hours': `${minute} */6 * * *`,\n 'seven hours': `${minute} */7 * * *`,\n 'eight hours': `${minute} */8 * * *`,\n 'nine hours': `${minute} */9 * * *`,\n 'ten hours': `${minute} */10 * * *`,\n 'eleven hours': `${minute} */11 * * *`,\n 'twelve hours': `${minute} */12 * * *`,\n\n day: `${minute} ${hour} * * *`,\n\n week: `${minute} ${hour} * * ${dayOfWeekNumber}`,\n sunday: `${minute} ${hour} * * 0`,\n monday: `${minute} ${hour} * * 1`,\n tuesday: `${minute} ${hour} * * 2`,\n wednesday: `${minute} ${hour} * * 3`,\n thursday: `${minute} ${hour} * * 4`,\n friday: `${minute} ${hour} * * 5`,\n saturday: `${minute} ${hour} * * 6`,\n\n month: `${minute} ${hour} ${dayOfWeek ? '*' : dayOfMonth} * ${dayOfWeek ? dayOfWeekNumber + '#1' : '*'}`,\n 'last day of month': `${minute} ${hour} L * *`,\n\n // quarter: `${minute} ${hour} ${dayOfWeek ? '*' : dayOfMonth} */3 ${dayOfWeek ? dayOfWeekNumber : '*'}`,\n // year: `${minute} ${hour} ${dayOfMonth} 1 ${dayOfWeek ? dayOfWeekNumber : '*'}`,\n }\n\n return patterns[interval]\n}\n","import { Cron } from 'croner'\n\n/**\n * Cron instance registry for internal use\n */\nexport class ScheduleRegistry {\n private static instances: Record<string, Cron> = {}\n\n public static add(name: string, cron: Cron): void {\n if (this.instances[name]) {\n throw new Error(`Cron instance with name '${name}' already exists`)\n }\n\n this.instances[name] = cron\n }\n\n public static all(): Record<string, Cron> {\n return this.instances\n }\n\n public static get(name: string): Cron | undefined {\n return this.instances[name]\n }\n\n public static clear(name?: string): void {\n if (name) {\n this.instances[name]?.stop()\n delete this.instances[name]\n } else {\n Object.values(this.instances).forEach((cron) => cron.stop())\n this.instances = {}\n }\n }\n}\n","import { MaybePromise } from '../types.js'\nimport {\n IntervalCronOptions,\n ScheduleInterval,\n ScheduleIntervalDayOfWeek,\n ScheduleIntervalTime,\n intervalToCron,\n parseTime,\n} from './schedule_interval.js'\nimport { ScheduleRegistry } from './schedule_registry.js'\n\nimport type { LockFactory } from '@verrou/core'\nimport type { SerializedLock } from '@verrou/core/types'\nimport { Duration } from '@verrou/core/types'\nimport { Cron } from 'croner'\nimport { createHash } from 'node:crypto'\n\nexport const getDistributedLockKey = (name: string) => {\n const hash = createHash('sha1').update(name).digest('hex').slice(0, 8)\n return `lavoro:schedule:${hash}`\n}\n\nexport class PendingSchedule {\n protected cronPattern?: string\n\n protected interval: ScheduleInterval = 'day'\n protected intervalOptions?: IntervalCronOptions\n\n protected distributedLockOptions: {\n /**\n * The lock key is based on the task name to ensure only one instance runs\n *\n * @param name - The task name\n * @returns The lock key\n */\n key: (name: string) => string\n /**\n * The lock TTL is the duration for which the lock is held\n */\n ttl: Duration\n /**\n * Whether to allow overlapping executions of the same task\n */\n overlap: boolean\n /**\n * Whether to hand off the lock to the queue worker\n */\n handOff: boolean\n } = {\n key: getDistributedLockKey,\n /**\n * Interval during which the lock is held for the job\n * and no other instances of it will not be scheduled\n */\n ttl: '15s',\n overlap: false,\n handOff: false,\n }\n\n constructor(\n protected name: string,\n protected cb: (lock?: SerializedLock) => MaybePromise<void>,\n protected lockProviderResolver: () => LockFactory,\n ) {}\n\n /**\n * Schedule using a cron pattern.\n * You can use https://crontab.guru to generate a cron pattern.\n *\n * @param pattern - Cron pattern string\n *\n * @example\n * Schedule.call('my-task', () => {}).cron('0 0 * * *') // Daily at midnight\n * Schedule.call('my-task', () => {}).cron('*\\/5 * * * *') // Every 5 minutes\n * Schedule.call('my-task', () => {}).cron('0 *\\/2 * * *') // Every 2 hours\n */\n public cron(pattern: string): this {\n this.cronPattern = pattern\n return this\n }\n\n /**\n * Schedule to run at a specific interval.\n * For longer intervals (hour, day, week, etc.), you can customize when they run.\n *\n * @param interval - The schedule interval\n * @param options - Options to customize the cron pattern\n *\n * @example\n * Schedule.call('my-task', () => {}).every('minute')\n * Schedule.call('my-task', () => {}).every('hour', { minute: 30 })\n * Schedule.call('my-task', () => {}).every('day', { hour: 14, minute: 30 })\n * Schedule.call('my-task', () => {}).every('week', { dayOfWeek: 1, hour: 9 })\n */\n public every(\n interval: ScheduleInterval,\n options?: IntervalCronOptions,\n ): this {\n this.interval = interval\n this.intervalOptions = options\n this.cronPattern = intervalToCron(interval, options)\n return this\n }\n\n public on(dayOfWeek: ScheduleIntervalDayOfWeek): this {\n // .on() only makes sense for intervals larger than 'day'\n const valid: ScheduleInterval[] = [\n //\n 'week',\n 'month',\n ]\n\n if (!valid.includes(this.interval)) {\n throw new Error(\n `.on() can only be used for weekly intervals or larger. Current interval: '${this.interval}'`,\n )\n }\n\n this.intervalOptions = { ...(this.intervalOptions ?? {}), dayOfWeek }\n this.cronPattern = intervalToCron(this.interval, this.intervalOptions)\n return this\n }\n\n public at(time: ScheduleIntervalTime): this {\n // .at() only makes sense for intervals larger than 'hour'\n const valid: ScheduleInterval[] = [\n 'day',\n 'week',\n 'sunday',\n 'monday',\n 'tuesday',\n 'wednesday',\n 'thursday',\n 'friday',\n 'saturday',\n 'month',\n 'last day of month',\n ]\n\n if (!valid.includes(this.interval)) {\n throw new Error(\n `.at() can only be used for daily intervals or larger. Current interval: '${this.interval}'`,\n )\n }\n\n const [hour, minute] = parseTime(time)\n this.intervalOptions = { ...(this.intervalOptions ?? {}), hour, minute }\n this.cronPattern = intervalToCron(this.interval, this.intervalOptions)\n return this\n }\n\n /**\n * Set the duration during which other instances\n * of the same task will be prevented from running.\n *\n * This should be roughly the duration of the task execution or longer\n * since the lock will be released automatically after the task execution.\n *\n * @param ttl - The lock duration\n *\n * @example\n * Schedule.call('my-task', () => {}).lockFor('10s')\n */\n public lockFor(ttl: Duration): this {\n this.distributedLockOptions.ttl = ttl\n return this\n }\n\n /**\n * Allow overlapping executions of the same task.\n *\n * @example\n * Schedule.call('my-task', () => {}).overlapping()\n */\n public overlapping(): this {\n this.distributedLockOptions.overlap = true\n return this\n }\n\n protected async execute(): Promise<void> {\n if (!this.cronPattern) {\n throw new Error(\n 'No schedule pattern defined. To schedule a task, set interval explicitly.',\n )\n }\n\n ScheduleRegistry.add(\n this.name,\n new Cron(this.cronPattern, async () => {\n // If overlapping is allowed, we can call the callback right away.\n if (this.distributedLockOptions.overlap) {\n await this.cb()\n return\n }\n\n // First, we create a distributed lock based on the task name,\n // which ensures that only one instance of the task runs at a time.\n const key = this.distributedLockOptions.key(this.name)\n\n // Resolve lock provider instance and create the lock.\n const lockProvider = this.lockProviderResolver()\n const lock = lockProvider.createLock(\n key,\n this.distributedLockOptions.ttl,\n )\n\n // If the lock is already locked, we skip the execution.\n // if (await lock.isLocked()) {\n // return\n // }\n\n const acquired = await lock.acquireImmediately()\n\n if (!acquired) {\n return\n }\n\n // If the lock was acquired, we run the task,\n // otherwise just skip it and do nothing.\n try {\n // If the lock is marked to be handed off to the queue\n // worker, we serialize and pass it to the callback.\n // Otherwise we just run the task and then release\n // the lock immediately.\n if (this.distributedLockOptions.handOff) {\n await this.cb(lock.serialize())\n } else {\n await this.cb()\n await lock.forceRelease()\n }\n } catch (error) {\n // If the task callback failed, we release\n // the lock and re-throw the error.\n await lock.forceRelease()\n throw error\n }\n }),\n )\n }\n\n /**\n * By defining the \"then\" method, PendingDispatch becomes \"thenable\",\n * allowing it to trigger automatically when await is called.\n */\n public async then<TResult1 = void, TResult2 = never>(\n onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,\n ): Promise<TResult1 | TResult2> {\n // When await is called, actually execte pending chain.\n return this.execute().then(onfulfilled, onrejected)\n }\n}\n","import { Job, Payload, PayloadWithLock } from '../queue/contracts/job.js'\nimport { QueueNameForConnection } from '../queue/contracts/queue_driver.js'\nimport { PendingDispatch } from '../queue/pending_dispatch.js'\nimport { DefaultConnection, QueueConnectionName } from '../queue/types.js'\nimport { PendingSchedule } from './pending_schedule.js'\n\nimport type { LockFactory } from '@verrou/core'\nimport type { SerializedLock } from '@verrou/core/types'\n\nexport class PendingJobSchedule<\n T extends Job,\n P extends Payload<T>,\n C extends QueueConnectionName = DefaultConnection extends { name: infer N }\n ? N extends QueueConnectionName\n ? N\n : QueueConnectionName\n : QueueConnectionName,\n> extends PendingSchedule {\n /**\n * Use composition pattern and store pending\n * job dispatch inside a pending schedule.\n */\n protected dispatch: PendingDispatch<T, PayloadWithLock<T, P>, C>\n\n private _connection?: string\n private _queue?: string\n\n private get jobName(): string {\n return `${this._connection}_${this._queue}_${this.job.name}`\n }\n\n constructor(\n protected job: T,\n protected payload: PayloadWithLock<T, P>,\n protected lockProviderResolver: () => LockFactory,\n ) {\n super(\n job.name,\n async (lock?: SerializedLock) => {\n if (lock) {\n this.payload._lock = lock\n }\n\n await this.dispatch.then(undefined, (error) => {\n throw error\n })\n },\n lockProviderResolver,\n )\n\n this.job = job\n this.payload = payload\n this.dispatch = new PendingDispatch(job, payload)\n\n this.distributedLockOptions.handOff = true\n }\n\n public onConnection<NewC extends QueueConnectionName>(\n connection: NewC,\n ): PendingJobSchedule<T, P, NewC> {\n this._connection = connection\n this.dispatch.onConnection(connection)\n // TypeScript can't track type parameter changes through `this`.\n // The instance is the same, but the type parameter C changes to NewC,\n // so we need to assert the type to the new type.\n return this as unknown as PendingJobSchedule<T, P, NewC>\n }\n\n public onQueue(queue: QueueNameForConnection<C>): this {\n this._queue = queue\n this.dispatch.onQueue(queue)\n\n return this\n }\n\n // public withQueueServiceResolver(queueServiceResolver: () => Promise<Queue>) {\n // this.dispatch.withQueueServiceResolver(queueServiceResolver)\n // return this\n // }\n\n protected async execute(): Promise<void> {\n // Before executing, update the lock provider resolver to use the one from the queue connection\n const queueServiceResolver = this.job.getQueueServiceResolver\n if (queueServiceResolver) {\n const queue = await queueServiceResolver()\n\n // Get the connection the job will use\n const connection =\n this.job.options.connection ?? queue.getDefaultConnection()\n\n // Override the lock service resolver to use the connection's lock provider\n const connectionLockService = queue.getLockProvider(connection)\n\n if (connectionLockService) {\n this.lockProviderResolver = () => connectionLockService\n }\n\n // Register this scheduled job with the queue service\n if (this.job.id) {\n queue.registerScheduledJob(this.job.id)\n }\n\n this._connection = this._connection ?? queue.getDefaultConnection()\n this._queue = this._queue ?? queue.getDefaultQueue()\n }\n\n this.name = this.jobName\n\n await super.execute()\n }\n}\n","import { Job, Payload, PayloadWithLock } from '../queue/contracts/job.js'\nimport { MaybePromise } from '../types.js'\nimport { PendingJobSchedule } from './pending_job_schedule.js'\nimport { PendingSchedule } from './pending_schedule.js'\nimport { ScheduleRegistry } from './schedule_registry.js'\n\nimport { LockFactory } from '@verrou/core'\nimport { memoryStore } from '@verrou/core/drivers/memory'\n\n/**\n * Default lock provider instance for distributed locking.\n * Uses memory store by default.\n */\nexport const defaultScheduleLockProvider = new LockFactory(\n memoryStore().factory(),\n)\n\nexport class Schedule {\n /**\n * Default lock provider resolver for distributed locking.\n * Returns the default memory-based instance if not overridden.\n */\n private static defaultLockProviderResolver: () => LockFactory = () =>\n defaultScheduleLockProvider\n\n /**\n * Set a custom lock provider resolver for distributed locking.\n *\n * This allows dynamic resolution of lock provider instances, useful when\n * integrating with Queue or other services that manage lock instances.\n *\n * @param resolver - Function that returns a LockFactory instance\n *\n * @example\n * import { LockFactory } from '@verrou/core'\n * import { redisStore } from '@verrou/core/drivers/redis'\n *\n * const customLockProvider = new LockFactory(\n * redisStore({ connection: redisClient })\n * )\n *\n * Schedule.setLockProviderResolver(() => customLockProvider)\n */\n public static setLockProviderResolver(resolver: () => LockFactory): void {\n this.defaultLockProviderResolver = resolver\n }\n\n /**\n * Get the current lock provider instance from the resolver.\n * @internal\n */\n public static getLockProvider(): LockFactory {\n return this.defaultLockProviderResolver()\n }\n\n /**\n * Clear all scheduled tasks (or specific one if name is specified).\n *\n * @param name - The name of the task to clear\n *\n * @example\n * Schedule.clear() // Clear all tasks\n * Schedule.clear('my-task') // Clear specific task\n */\n public static clear(name?: string): void {\n if (name) {\n ScheduleRegistry.clear(name)\n } else {\n Object.keys(ScheduleRegistry.all()).forEach((name) =>\n ScheduleRegistry.clear(name),\n )\n }\n }\n\n /**\n * Schedule a callback to run at specified intervals.\n *\n * @param name - Unique identifier for the task (required for distributed systems)\n * @param cb - The callback function to execute\n *\n * @example\n * // Using cron pattern\n * const cleanupUsers = async () => { ... }\n * Schedule.call('cleanup-users', cleanupUsers).cron('0 0 * * *')\n *\n * // Using convenience methods\n * Schedule.call('hourly-task', () => { ... }).hourly()\n * Schedule.call('daily-task', () => { ... }).daily()\n */\n public static call(name: string, cb: () => MaybePromise<void>) {\n return new PendingSchedule(name, cb, this.defaultLockProviderResolver)\n }\n\n /**\n * Schedule a job to run at specified intervals.\n *\n * You can specify the connection and queue to use for the job\n * the same way you would dispatch a job.\n *\n * @param job - The job class to schedule\n * @param payload - The payload to pass to the job\n *\n * @example\n * Schedule.job(TestJob, { arg1: 'hello', arg2: 1 }).every('minute')\n * Schedule.job(TestJob, { arg1: 'hello', arg2: 1 })\n * .onConnection('main')\n * .onQueue('default')\n * .every('minute')\n */\n public static job<T extends Job, P extends Payload<T>>(\n job: new () => T,\n payload: P,\n ): PendingJobSchedule<T, P> {\n return new PendingJobSchedule<T, P>(\n new job(),\n payload as PayloadWithLock<T, P>,\n this.defaultLockProviderResolver,\n )\n }\n}\n","import {\n QueueDriverEventEmitter,\n QueueDriverEvents,\n} from './contracts/queue_driver_event_emitter.js'\n\n/**\n * Queue service can emit any of the queue driver\n * events alongside its own events (currently none).\n */\nexport interface QueueEvents extends QueueDriverEvents {}\n\n/**\n * Type-safe event emitter for the queue service.\n */\nexport abstract class QueueEventEmitter extends QueueDriverEventEmitter {\n public override on<K extends keyof QueueEvents>(\n event: K,\n listener: (...args: QueueEvents[K]) => void,\n ): this {\n return super.on(event, listener)\n }\n\n public override emit<K extends keyof QueueEvents>(\n event: K,\n ...args: QueueEvents[K]\n ): boolean {\n return super.emit(event, ...args)\n }\n}\n","import { Logger, createDefaultLogger } from '../logger.js'\nimport { Schedule } from '../schedule/schedule.js'\nimport { Job, Payload } from './contracts/job.js'\nimport {\n QueueDriver,\n QueueDriverStopOptions,\n QueueName,\n} from './contracts/queue_driver.js'\nimport { QueueDriverEvents } from './contracts/queue_driver_event_emitter.js'\nimport { QueueEventEmitter } from './queue_event_emitter.js'\nimport type {\n QueueConfig,\n QueueConnectionConfig,\n QueueConnectionName,\n} from './types.js'\n\nimport type { LockFactory } from '@verrou/core'\n\nexport class Queue extends QueueEventEmitter {\n private drivers: Map<QueueConnectionName, QueueDriver> = new Map()\n private started: boolean = false\n private logger: Logger\n private scheduledJobs: Set<string> = new Set()\n private lockFactories: Map<QueueConnectionName, LockFactory> = new Map()\n\n constructor(private config: QueueConfig & { logger?: Logger }) {\n super()\n\n this.logger = config?.logger || createDefaultLogger('queue')\n\n for (const [connection, driverConfig] of Object.entries(\n this.config.connections,\n )) {\n this.logger.trace(\n { connection, driver: driverConfig.driver },\n 'Creating queue driver',\n )\n\n const driver = this.createDriver(driverConfig)\n driver.connection = connection as QueueConnectionName\n\n this.bindEvents(driver)\n\n this.drivers.set(driver.connection, driver)\n }\n }\n\n /**\n * Bind all queue driver events and\n * proxy them through the queue service.\n */\n private bindEvents(driver: QueueDriver) {\n const events = [\n 'error',\n 'job:start',\n 'job:progress',\n 'job:complete',\n 'job:error',\n 'job:finish',\n ] as const\n\n for (const event of events) {\n driver.on(event, (...args) => {\n this.emit(event, ...(args as QueueDriverEvents[typeof event]))\n })\n }\n }\n\n private createDriver(\n config: QueueConnectionConfig<QueueDriver>,\n ): QueueDriver {\n const { constructor: driverConstructor, config: driverConfig } =\n config.driver\n\n const driver = new driverConstructor(\n this.config,\n config.queues,\n driverConfig,\n )\n\n driver.setLogger(this.logger)\n\n return driver\n }\n\n async start() {\n if (this.started) {\n this.logger.warn('Queue service already started')\n return\n }\n\n /**\n * Create lock factories for each connection.\n * If no lock provider was explicitly configured,\n * create a driver-specific lock factory.\n */\n for (const [connection, driverConfig] of Object.entries(\n this.config.connections,\n )) {\n const driver = this.drivers.get(connection as QueueConnectionName)\n if (!driver) {\n throw new Error(`Driver not found for connection: ${connection}.`)\n }\n\n /**\n * Create driver-specific lock factory if\n * no lock provider was explicitly configured.\n */\n if (!driverConfig.lockProvider) {\n const lockFactory = driver.createLockProvider()\n if (lockFactory) {\n this.lockFactories.set(connection as QueueConnectionName, lockFactory)\n this.logger.trace(\n { connection, driver: driverConfig.driver },\n 'Created lock factory for driver',\n )\n }\n } else {\n this.lockFactories.set(\n connection as QueueConnectionName,\n driverConfig.lockProvider,\n )\n this.logger.trace(\n { connection, driver: driverConfig.driver },\n 'Using explicitly configured lock provider for driver',\n )\n }\n }\n\n for (const job of this.config.jobs) {\n await this.register(job)\n }\n\n this.started = true\n\n for (const [connection, driver] of this.drivers) {\n this.logger.trace({ connection }, 'Starting queue connection')\n await driver.start()\n }\n\n this.logger.trace(\n { connections: Array.from(this.drivers.keys()) },\n 'Queue service started',\n )\n }\n\n async stop(\n options: QueueDriverStopOptions = {\n graceful: true,\n timeout: 30000,\n },\n ) {\n if (!this.started) {\n this.logger.warn('Queue service not started')\n return\n }\n\n this.logger.trace(\n { count: this.scheduledJobs.size },\n 'Cleared scheduled jobs for the queue',\n )\n\n // Clear all scheduled jobs registered with this Queue instance\n for (const id of this.scheduledJobs) {\n Schedule.clear(id)\n }\n\n this.scheduledJobs.clear()\n\n for (const job of this.config.jobs) {\n await this.unregister(job)\n }\n\n for (const [connection, driver] of this.drivers) {\n this.logger.trace({ connection }, 'Stopping queue connection')\n await driver.stop(options)\n }\n\n /**\n * Destroy lock factories for each connection.\n */\n for (const [connection, lockFactory] of this.lockFactories) {\n const driver = this.drivers.get(connection as QueueConnectionName)\n if (!driver) {\n throw new Error(`Driver not found for connection: ${connection}.`)\n }\n\n await driver.destroyLockProvider(lockFactory)\n this.lockFactories.delete(connection as QueueConnectionName)\n }\n\n this.started = false\n\n this.logger.trace('Queue service stopped')\n }\n\n protected async register(job: new () => Job): Promise<void> {\n for (const [_, driver] of this.drivers) {\n await driver.register(job)\n }\n }\n\n protected async unregister(job: new () => Job): Promise<void> {\n for (const [_, driver] of this.drivers) {\n await driver.unregister(job)\n }\n }\n\n public async enqueue<T extends Job, P extends Payload<T>>(\n job: T,\n payload: P,\n ): Promise<void> {\n if (this.drivers.size === 0) {\n throw new Error('No queue drivers available.')\n }\n\n /**\n * Try to get driver from connection if specified\n * otherwise use the first available driver.\n */\n const driver: QueueDriver | undefined = job.options.connection\n ? this.drivers.get(job.options.connection)\n : this.drivers.values().next().value\n\n if (!driver) {\n throw new Error(\n `No driver found for connection: ${job.options.connection}.`,\n )\n }\n\n if (!job.options.queue) {\n job.options.queue = driver.getDefaultQueue()\n }\n\n await driver.enqueue(job, payload)\n }\n\n /**\n * Get the default connection name.\n *\n * Returns the name of the first available connection.\n * Throws an error if no connections are available.\n */\n public getDefaultConnection(): QueueConnectionName {\n if (this.drivers.size === 0) {\n throw new Error(`No queue drivers available.`)\n }\n\n return this.drivers.keys().next().value as QueueConnectionName\n }\n\n public getDefaultQueue(): QueueName {\n if (this.drivers.size === 0) {\n throw new Error(`No queue drivers available.`)\n }\n\n return this.drivers.values().next().value?.getDefaultQueue() as QueueName\n }\n\n /**\n * Get the lock factory instance for a specific connection.\n * Returns the explicitly configured lock provider or the auto-created lock factory.\n * Throws an error if no lock factory is available.\n *\n * @param connection - The connection name\n * @returns The lock factory instance\n */\n public getLockProvider(connection: QueueConnectionName): LockFactory {\n const connectionConfig = this.config.connections[connection]\n\n // Return explicitly configured lock provider if available\n if (connectionConfig?.lockProvider) {\n return connectionConfig.lockProvider\n }\n\n // Return auto-created lock factory\n const lockFactory = this.lockFactories.get(connection)\n\n if (!lockFactory) {\n throw new Error(`No lock provider found for connection: ${connection}.`)\n }\n\n return lockFactory\n }\n\n /**\n * Register a scheduled job ID with this Queue instance.\n * This allows the Queue to clean up scheduled jobs when it stops.\n */\n public registerScheduledJob(id: string): void {\n this.scheduledJobs.add(id)\n }\n}\n"],"mappings":"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","names":["name"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lavoro/core",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "type": "module",
5
5
  "description": "A type-safe, flexible queue library for Node.js with support for multiple drivers",
6
6
  "author": "Aleksei Ivanov <contact@aleksei.dev>",