@orion-js/dogs 4.6.1 → 4.6.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/dist/index.cjs +174 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +174 -24
- package/dist/index.js.map +1 -1
- package/dist/repos/JobsRepo.d.ts +16 -1
- package/dist/services/WorkerService.d.ts +16 -0
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/services/EventsService.ts","../src/repos/JobsRepo.ts","../src/types/JobRecord.ts","../src/types/StartConfig.ts","../src/services/getNextRunDate.ts","../src/services/WorkerService.ts","../src/services/Executor.ts","../src/repos/JobsHistoryRepo.ts","../../../node_modules/.bun/rambdax@11.3.1/node_modules/rambdax/src/_internals/isInteger.js","../../../node_modules/.bun/rambdax@11.3.1/node_modules/rambdax/src/_internals/createPath.js","../../../node_modules/.bun/rambdax@11.3.1/node_modules/rambdax/src/_internals/compare.js","../../../node_modules/.bun/rambdax@11.3.1/node_modules/rambdax/src/_internals/includes.js","../../../node_modules/.bun/rambdax@11.3.1/node_modules/rambdax/src/omit.js","../src/types/HistoryRecord.ts","../src/service/index.ts","../src/defineJob/index.ts"],"sourcesContent":["import {getInstance} from '@orion-js/services'\nimport {EventsService} from './services/EventsService'\nimport {WorkerService} from './services/WorkerService'\nimport {StartWorkersConfig} from './types/StartConfig'\nimport {ScheduleJobOptions, ScheduleJobsOptions, ScheduleJobsResult} from './types/Events'\nimport {JobsHistoryRepo} from './repos/JobsHistoryRepo'\nimport {JobsRepo} from './repos/JobsRepo'\nimport {SchemaInAnyOrionForm} from '@orion-js/schema'\n\nexport * from './types'\nexport * from './service'\nexport * from './defineJob'\n\nconst workerService = getInstance(WorkerService)\nconst eventsService = getInstance(EventsService)\nconst jobsHistoryRepo = getInstance(JobsHistoryRepo)\nconst jobsRepo = getInstance(JobsRepo)\n\nconst startWorkers = (config: StartWorkersConfig) => {\n return workerService.startWorkers(config)\n}\n\n/**\n * @deprecated Use the event job definition.schedule method instead.\n */\nconst scheduleJob = <TParamsSchema extends SchemaInAnyOrionForm = any>(\n options: ScheduleJobOptions<TParamsSchema>,\n) => {\n return eventsService.scheduleJob(options)\n}\n\n/**\n * Schedule multiple jobs at once for better performance.\n * @deprecated Use the event job definition.scheduleJobs method instead.\n */\nconst scheduleJobs = <TParamsSchema extends SchemaInAnyOrionForm = any>(\n jobs: ScheduleJobsOptions<TParamsSchema>,\n): Promise<ScheduleJobsResult> => {\n return eventsService.scheduleJobs(jobs)\n}\n\nexport {startWorkers, scheduleJob, scheduleJobs, jobsHistoryRepo, jobsRepo}\n","import {logger} from '@orion-js/logger'\nimport {Inject, Service} from '@orion-js/services'\nimport {JobsRepo} from '../repos/JobsRepo'\nimport {ScheduleJobOptions, ScheduleJobsOptions, ScheduleJobsResult} from '../types/Events'\nimport {getNextRunDate} from './getNextRunDate'\n\n@Service()\nexport class EventsService {\n @Inject(() => JobsRepo)\n private jobsRepo: JobsRepo\n\n async scheduleJob(options: ScheduleJobOptions) {\n logger.debug('Scheduling job...', options)\n\n await this.jobsRepo.scheduleJob({\n name: options.name,\n priority: options.priority || 100,\n nextRunAt: getNextRunDate(options),\n params: options.params || null,\n uniqueIdentifier: options.uniqueIdentifier,\n })\n }\n\n async scheduleJobs(jobs: ScheduleJobsOptions): Promise<ScheduleJobsResult> {\n logger.debug(`Scheduling ${jobs.length} jobs...`)\n\n const jobRecords = jobs.map(options => ({\n name: options.name,\n priority: options.priority || 100,\n nextRunAt: getNextRunDate(options),\n params: options.params || null,\n uniqueIdentifier: options.uniqueIdentifier,\n }))\n\n return await this.jobsRepo.scheduleJobs(jobRecords)\n }\n}\n","import {generateId} from '@orion-js/helpers'\nimport {logger} from '@orion-js/logger'\nimport {Collection, MongoCollection, MongoDB, Repository} from '@orion-js/mongodb'\nimport {ScheduleJobRecordOptions, ScheduleJobsResult} from '../types/Events'\nimport {JobRecord, JobRecordSchema} from '../types/JobRecord'\nimport {JobDefinitionWithName, RecurrentJobDefinition} from '../types/JobsDefinition'\nimport {DEFAULT_MAX_TRIES_REACHED_RETENTION_MS} from '../types/StartConfig'\nimport {JobToRun} from '../types/Worker'\n\n@Repository()\nexport class JobsRepo {\n @MongoCollection({\n idGeneration: 'uuid',\n name: 'orionjs.jobs_dogs_records',\n schema: JobRecordSchema,\n indexes: [\n {\n keys: {\n jobName: 1,\n priority: -1,\n nextRunAt: 1,\n },\n },\n {\n keys: {\n jobName: 1,\n },\n options: {\n unique: true,\n partialFilterExpression: {type: 'recurrent'},\n },\n },\n {\n keys: {\n uniqueIdentifier: 1,\n },\n options: {\n unique: true,\n sparse: true,\n },\n },\n {\n keys: {\n expiresAt: 1,\n },\n name: 'jobs_dogs_records_expires_at_ttl',\n expireAfterSeconds: 0,\n },\n ],\n })\n jobs: Collection<JobRecord>\n\n async getJobAndLock(jobNames: string[], lockTime: number): Promise<JobToRun> {\n const executionId = generateId()\n const lockedUntil = new Date(Date.now() + lockTime)\n\n const job = await this.jobs.findOneAndUpdate(\n {\n jobName: {$in: jobNames},\n nextRunAt: {$lte: new Date()},\n $and: [\n {$or: [{lockedUntil: {$exists: false}}, {lockedUntil: {$lte: new Date()}}]},\n // Exclude event jobs that have reached max tries. Recurrent jobs keep running even\n // if old records still have this status from previous versions.\n {$or: [{type: {$ne: 'event'}}, {status: {$ne: 'maxTriesReached'}}]},\n ],\n },\n {\n $set: {lockId: executionId, lockedUntil, lastRunAt: new Date()},\n $inc: {tries: 1},\n },\n {\n mongoOptions: {\n sort: {\n priority: -1,\n nextRunAt: 1,\n },\n returnDocument: 'before',\n },\n },\n )\n\n if (!job) return\n\n const tries = (job.tries || 0) + 1\n const wasStale = Boolean(job.lockedUntil)\n\n if (wasStale) {\n logger.info(`Running job \"${job.jobName}\" that was staled`)\n }\n\n return {\n jobId: job._id,\n executionId,\n lockId: executionId,\n name: job.jobName,\n params: job.params,\n type: job.type,\n tries,\n lockTime,\n priority: job.priority,\n uniqueIdentifier: job.uniqueIdentifier,\n wasStale,\n }\n }\n\n async setJobRecordPriority(jobId: string, priority: number, lockId?: string) {\n const result = await this.jobs.updateOne(lockId ? {_id: jobId, lockId} : jobId, {\n $set: {priority},\n })\n return result.matchedCount > 0\n }\n\n async scheduleNextRun(options: {\n jobId: string\n nextRunAt: Date\n resetTries: boolean\n priority: number\n lockId?: string\n }) {\n const updator: MongoDB.UpdateFilter<JobRecord> = {\n $set: {\n nextRunAt: options.nextRunAt,\n priority: options.priority,\n ...(options.resetTries ? {tries: 0} : {}),\n },\n $unset: {lockId: '', lockedUntil: ''},\n }\n\n const result = await this.jobs.updateOne(\n options.lockId ? {_id: options.jobId, lockId: options.lockId} : options.jobId,\n updator,\n )\n return result.matchedCount > 0\n }\n\n async deleteEventJob(jobId: string, lockId?: string) {\n const result = await this.jobs.deleteOne({\n _id: jobId,\n type: 'event',\n ...(lockId ? {lockId} : {}),\n })\n return result.deletedCount > 0\n }\n\n /**\n * Marks an event job as having reached its maximum tries limit.\n * The job won't be picked up for execution and MongoDB will delete it after\n * the configured retention period.\n */\n async markJobAsMaxTriesReached(\n jobId: string,\n retentionMs: number | null = DEFAULT_MAX_TRIES_REACHED_RETENTION_MS,\n lockId?: string,\n ) {\n const maxTriesReachedAt = new Date()\n const result = await this.jobs.updateOne(\n {_id: jobId, type: 'event', ...(lockId ? {lockId} : {})},\n {\n $set: {\n status: 'maxTriesReached',\n maxTriesReachedAt,\n ...(retentionMs === null\n ? {}\n : {expiresAt: new Date(maxTriesReachedAt.getTime() + retentionMs)}),\n },\n $unset: {\n lockId: '',\n lockedUntil: '',\n ...(retentionMs === null ? {expiresAt: ''} : {}),\n },\n },\n )\n return result.matchedCount > 0\n }\n\n /**\n * Applies the current retention configuration to existing maxTriesReached\n * event jobs. The collection definition ensures the TTL index. Legacy records\n * use lastRunAt as their retention anchor when available.\n */\n async ensureMaxTriesReachedRetention(retentionMs: number | null) {\n const selector = {\n type: 'event' as const,\n status: 'maxTriesReached' as const,\n }\n\n if (retentionMs === null) {\n await this.jobs.updateMany(selector, {$unset: {expiresAt: ''}})\n return\n }\n\n const now = new Date()\n const retentionAnchor = {\n $ifNull: ['$maxTriesReachedAt', {$ifNull: ['$lastRunAt', now]}],\n }\n\n await this.jobs.rawCollection.updateMany(selector, [\n {\n $set: {\n maxTriesReachedAt: retentionAnchor,\n expiresAt: {$add: [retentionAnchor, retentionMs]},\n },\n },\n ])\n }\n\n async extendLockTime(jobId: string, extraTime: number, lockId?: string) {\n return this.updateLockTime(jobId, extraTime, lockId)\n }\n\n /**\n * Updates the lock time for a job to the specified duration from now.\n * Can be used to both extend or shorten the lock time.\n */\n async updateLockTime(jobId: string, lockDuration: number, lockId?: string) {\n const lockedUntil = new Date(Date.now() + lockDuration)\n const result = await this.jobs.updateOne(\n {_id: jobId, ...(lockId ? {lockId} : {})},\n {\n $set: {lockedUntil},\n },\n )\n return result.matchedCount > 0\n }\n\n async unlockAllJobs(): Promise<number> {\n const result = await this.jobs.updateMany(\n {\n lockedUntil: {$exists: true},\n },\n {\n $unset: {lockId: '', lockedUntil: ''},\n },\n )\n\n return result.modifiedCount\n }\n\n async ensureJobRecord(job: JobDefinitionWithName) {\n const result = await this.jobs.upsert(\n {\n jobName: job.name,\n },\n {\n $set: {\n type: job.type,\n priority: (job as RecurrentJobDefinition).priority,\n },\n $unset: {\n status: '',\n },\n $setOnInsert: {\n nextRunAt: new Date(),\n },\n },\n )\n\n if (result.upsertedId) {\n logger.debug(`Created job record for \"${job.name}\"`)\n } else {\n logger.debug(`Record for job \"${job.name}\" already exists`)\n }\n }\n\n async scheduleJob(options: ScheduleJobRecordOptions) {\n try {\n await this.jobs.insertOne({\n jobName: options.name,\n uniqueIdentifier: options.uniqueIdentifier,\n params: options.params,\n nextRunAt: options.nextRunAt,\n priority: options.priority,\n type: 'event',\n })\n } catch (error) {\n if (\n error.isValidationError &&\n Object.values(error.validationErrors).includes('notUnique') &&\n options.uniqueIdentifier\n ) {\n logger.info(\n `Job \"${options.name}\" with identifier \"${options.uniqueIdentifier}\" already exists`,\n )\n } else {\n throw error\n }\n }\n }\n\n async scheduleJobs(jobs: ScheduleJobRecordOptions[]): Promise<ScheduleJobsResult> {\n if (jobs.length === 0) {\n return {scheduledCount: 0, skippedCount: 0, errors: []}\n }\n\n // Process each job individually to handle errors properly\n let scheduledCount = 0\n let skippedCount = 0\n const errors: Array<{index: number; error: Error; job: ScheduleJobRecordOptions}> = []\n\n for (let i = 0; i < jobs.length; i++) {\n const job = jobs[i]\n try {\n // Insert directly to get better error handling than the single scheduleJob method\n await this.jobs.insertOne({\n jobName: job.name,\n uniqueIdentifier: job.uniqueIdentifier,\n params: job.params,\n nextRunAt: job.nextRunAt,\n priority: job.priority,\n type: 'event',\n })\n scheduledCount++\n } catch (error) {\n // Check if it's a validation error with uniqueIdentifier constraint\n if (\n error.isValidationError &&\n Object.values(error.validationErrors).includes('notUnique') &&\n job.uniqueIdentifier\n ) {\n logger.info(`Job \"${job.name}\" with identifier \"${job.uniqueIdentifier}\" already exists`)\n skippedCount++\n } else {\n errors.push({\n index: i,\n error: error instanceof Error ? error : new Error(String(error)),\n job,\n })\n }\n }\n }\n\n logger.debug(\n `Scheduled ${scheduledCount} jobs successfully, skipped ${skippedCount}, errors: ${errors.length}`,\n )\n\n return {\n scheduledCount,\n skippedCount,\n errors,\n }\n }\n}\n","import {createEnum, InferSchemaType, schemaWithName} from '@orion-js/schema'\n\n/**\n * Enum representing the status of a job record.\n * - 'pending': Job is active and can be executed (default for existing records)\n * - 'maxTriesReached': Event job has exhausted all retry attempts and won't be executed\n */\nexport const JobStatusEnum = createEnum('JobStatus', ['pending', 'maxTriesReached'])\n\nexport const JobRecordSchema = schemaWithName('JobRecord', {\n _id: {type: 'string'},\n jobName: {type: 'string'},\n type: {type: createEnum('JobType', ['recurrent', 'event'])},\n priority: {type: 'number'},\n uniqueIdentifier: {type: 'string', optional: true},\n nextRunAt: {type: 'date'},\n lastRunAt: {type: 'date', optional: true},\n lockedUntil: {type: 'date', optional: true},\n /**\n * Identifies the execution that currently owns the lock. Mutations from an execution must match\n * this value so a stale execution cannot modify a newer claim.\n */\n lockId: {type: 'string', optional: true},\n tries: {type: 'number', optional: true},\n params: {type: 'blackbox', optional: true},\n /**\n * Status of the job. Optional for backwards compatibility with existing records.\n * Records without this field are treated as 'pending'.\n */\n status: {type: JobStatusEnum, optional: true},\n /**\n * Date when the job reached its maximum tries. Used as the stable anchor when\n * maxTriesReachedRetentionMs changes between worker restarts.\n */\n maxTriesReachedAt: {type: 'date', optional: true},\n /**\n * Date when MongoDB should remove a terminal event job through the TTL index.\n */\n expiresAt: {type: 'date', optional: true},\n})\n\nexport type JobRecord = InferSchemaType<typeof JobRecordSchema>\n","import {JobsDefinition} from './JobsDefinition'\nimport {JobToRun} from './Worker'\n\nexport type LogLevels = 'debug' | 'info' | 'warn' | 'error' | 'none'\n\nexport const DEFAULT_MAX_TRIES_REACHED_RETENTION_MS = 1000 * 60 * 60 * 24 * 7\n\nexport interface StartWorkersConfig {\n /**\n * Object map of the jobs that this scheduler will execute.\n */\n jobs: JobsDefinition\n /**\n * Maximum number of tries for an event job before it is marked as 'maxTriesReached'.\n * This is a global default that can be overridden per event job definition.\n */\n maxTries?: number\n /**\n * Time in milliseconds to keep event jobs after they reach their maximum tries.\n * Defaults to one week. Set to null to keep them indefinitely.\n */\n maxTriesReachedRetentionMs?: number | null\n /**\n * Callback invoked when an event job reaches its maximum tries limit.\n * Use this to notify administrators (e.g., send an email alert).\n * The job will remain in the database with status 'maxTriesReached' until its\n * configured retention period expires.\n */\n onMaxTriesReached?: (job: JobToRun) => Promise<void>\n /**\n * Time in milliseconds to wait between each look without results for a job\n * to run at the database. Default is 3000.\n */\n pollInterval?: number\n /**\n * @deprecated The centralized scheduler no longer waits after successful job acquisition or\n * execution. This option is accepted for backwards compatibility and ignored.\n */\n cooldownPeriod?: number\n /**\n * Maximum number of concurrent job executions for this scheduler. Default is 4.\n */\n workersCount?: number\n /**\n * Default time in milliseconds to lock a job for execution. Default is 30000 (30 seconds).\n * If a job is locked for longer than this time, it will be considered as failed.\n * This is to prevent a job from being executed multiple times at the same time.\n * You can extend this time inside a job by calling extendLockTime from context.\n * Individual jobs can override this value by setting their own lockTime.\n */\n defaultLockTime?: number\n}\n","import {CronExpressionParser} from 'cron-parser'\n\nexport type Options = {\n getNextRun?: () => Date\n runIn?: number\n runEvery?: number\n runAt?: Date\n cron?: string\n timezone?: string\n currentDate?: Date | string | number\n} & {[key: string]: any}\n\nexport const getNextRunDate = (options: Options) => {\n if (options.runIn) {\n return new Date(Date.now() + options.runIn)\n }\n\n if (options.runEvery) {\n return new Date(Date.now() + options.runEvery)\n }\n\n if (options.cron) {\n if (!options.timezone) {\n throw new Error('Cron recurrent jobs require a timezone')\n }\n\n return CronExpressionParser.parse(options.cron, {\n currentDate: options.currentDate ?? new Date(),\n tz: options.timezone,\n })\n .next()\n .toDate()\n }\n\n if (options.runAt) {\n return options.runAt\n }\n\n if (options.getNextRun) {\n return options.getNextRun()\n }\n\n return new Date()\n}\n","import {sleep} from '@orion-js/helpers'\nimport {logger} from '@orion-js/logger'\nimport {Inject, Service} from '@orion-js/services'\nimport {JobsRepo} from '../repos/JobsRepo'\nimport {JobDefinitionWithName, JobsDefinition} from '../types/JobsDefinition'\nimport {DEFAULT_MAX_TRIES_REACHED_RETENTION_MS, StartWorkersConfig} from '../types/StartConfig'\nimport {JobToRun, WorkersInstance} from '../types/Worker'\nimport {ExecuteJobConfig, Executor} from './Executor'\n\ninterface TrackedExecution {\n job: JobToRun\n promise: Promise<void>\n capacityPromise: Promise<void>\n releaseCapacity: () => void\n status: 'running' | 'stale' | 'finished'\n}\n\ninterface InternalWorkersInstance extends WorkersInstance {\n activeExecutions: Map<string, TrackedExecution>\n staleExecutions: Map<string, TrackedExecution>\n runningJobsByName: Map<string, number>\n schedulerPromise: Promise<void>\n stopSignal: Promise<void>\n signalStop: () => void\n stopPromise?: Promise<void>\n}\n\n@Service()\nexport class WorkerService {\n @Inject(() => JobsRepo)\n private jobsRepo: JobsRepo\n\n @Inject(() => Executor)\n private executor: Executor\n\n getJobNames(jobs: JobsDefinition) {\n return Object.keys(jobs)\n }\n\n getJobs(jobs: JobsDefinition): JobDefinitionWithName[] {\n return Object.keys(jobs).map(name => {\n return {\n name,\n ...jobs[name],\n }\n })\n }\n\n getAvailableJobNames(\n config: StartWorkersConfig,\n workersInstance: InternalWorkersInstance,\n jobNames: string[],\n ) {\n return jobNames.filter(jobName => {\n const currentExecutions = workersInstance.runningJobsByName.get(jobName) || 0\n const job = config.jobs[jobName]\n const maxParallelExecutions =\n job.type === 'event'\n ? (job.maxParallelExecutionsPerServer ?? Number.POSITIVE_INFINITY)\n : Number.POSITIVE_INFINITY\n\n return currentExecutions < maxParallelExecutions\n })\n }\n\n reserveJobExecution(workersInstance: InternalWorkersInstance, jobName: string) {\n const currentExecutions = workersInstance.runningJobsByName.get(jobName) || 0\n workersInstance.runningJobsByName.set(jobName, currentExecutions + 1)\n }\n\n releaseJobExecution(workersInstance: InternalWorkersInstance, jobName: string) {\n const currentExecutions = workersInstance.runningJobsByName.get(jobName) || 0\n if (currentExecutions <= 1) {\n workersInstance.runningJobsByName.delete(jobName)\n return\n }\n\n workersInstance.runningJobsByName.set(jobName, currentExecutions - 1)\n }\n\n releaseExecutionCapacity(\n workersInstance: InternalWorkersInstance,\n execution: TrackedExecution,\n nextStatus: 'stale' | 'finished',\n ) {\n if (execution.status !== 'running') return\n\n execution.status = nextStatus\n workersInstance.activeExecutions.delete(execution.job.executionId)\n this.releaseJobExecution(workersInstance, execution.job.name)\n execution.releaseCapacity()\n\n if (nextStatus === 'stale') {\n workersInstance.staleExecutions.set(execution.job.executionId, execution)\n }\n }\n\n startExecution(\n config: ExecuteJobConfig,\n workersInstance: InternalWorkersInstance,\n jobToRun: JobToRun,\n ) {\n let releaseCapacity!: () => void\n const capacityPromise = new Promise<void>(resolve => {\n releaseCapacity = resolve\n })\n\n const execution: TrackedExecution = {\n job: jobToRun,\n promise: Promise.resolve(),\n capacityPromise,\n releaseCapacity,\n status: 'running',\n }\n\n this.reserveJobExecution(workersInstance, jobToRun.name)\n workersInstance.activeExecutions.set(jobToRun.executionId, execution)\n\n logger.debug(`Starting job execution \"${jobToRun.executionId}\"`, jobToRun)\n\n const executionPromise = this.executor.executeJob(config, jobToRun, () => {\n this.releaseExecutionCapacity(workersInstance, execution, 'stale')\n })\n execution.promise = executionPromise\n\n void executionPromise\n .catch(error => {\n logger.error(`Unhandled error executing job \"${jobToRun.name}\"`, {error})\n })\n .finally(() => {\n if (execution.status === 'running') {\n this.releaseExecutionCapacity(workersInstance, execution, 'finished')\n } else if (execution.status === 'stale') {\n workersInstance.staleExecutions.delete(jobToRun.executionId)\n }\n })\n }\n\n async waitForPollOrStop(config: StartWorkersConfig, workersInstance: InternalWorkersInstance) {\n await Promise.race([sleep(config.pollInterval), workersInstance.stopSignal])\n }\n\n async waitForCapacityOrStop(workersInstance: InternalWorkersInstance) {\n const capacityPromises = Array.from(\n workersInstance.activeExecutions.values(),\n execution => execution.capacityPromise,\n )\n\n if (capacityPromises.length === 0) return\n await Promise.race([...capacityPromises, workersInstance.stopSignal])\n }\n\n async runSchedulerLoop(config: StartWorkersConfig, workersInstance: InternalWorkersInstance) {\n const jobNames = this.getJobNames(config.jobs)\n const executeConfig: ExecuteJobConfig = {\n jobs: config.jobs,\n maxTries: config.maxTries,\n maxTriesReachedRetentionMs: config.maxTriesReachedRetentionMs,\n onMaxTriesReached: config.onMaxTriesReached,\n }\n\n logger.debug(`Running scheduler loop for jobs \"${jobNames.join(', ')}\"...`)\n\n while (workersInstance.running) {\n let didMiss = false\n let allJobNamesAtCapacity = false\n\n try {\n while (workersInstance.activeExecutions.size < config.workersCount) {\n const availableJobNames = this.getAvailableJobNames(config, workersInstance, jobNames)\n\n if (availableJobNames.length === 0) {\n allJobNamesAtCapacity = workersInstance.activeExecutions.size > 0\n break\n }\n\n const jobToRun = await this.jobsRepo.getJobAndLock(\n availableJobNames,\n config.defaultLockTime,\n )\n\n if (!jobToRun) {\n logger.debug('No job to run')\n didMiss = true\n break\n }\n\n // An acquisition already in flight when stop() is called is considered committed.\n this.startExecution(executeConfig, workersInstance, jobToRun)\n if (!workersInstance.running) break\n }\n } catch (error) {\n logger.error('Error in job scheduler.', {error})\n didMiss = true\n }\n\n if (!workersInstance.running) return\n\n const concurrencyIsFull =\n workersInstance.activeExecutions.size >= config.workersCount &&\n workersInstance.activeExecutions.size > 0\n\n if (concurrencyIsFull || allJobNamesAtCapacity) {\n await this.waitForCapacityOrStop(workersInstance)\n } else if (didMiss || workersInstance.activeExecutions.size === 0) {\n await this.waitForPollOrStop(config, workersInstance)\n }\n }\n }\n\n createWorkersInstanceDefinition(config: StartWorkersConfig): InternalWorkersInstance {\n let signalStop!: () => void\n const stopSignal = new Promise<void>(resolve => {\n signalStop = resolve\n })\n\n const workersInstance: InternalWorkersInstance = {\n running: true,\n workersCount: config.workersCount,\n activeExecutions: new Map(),\n staleExecutions: new Map(),\n runningJobsByName: new Map(),\n schedulerPromise: Promise.resolve(),\n stopSignal,\n signalStop,\n get runningExecutions() {\n return this.activeExecutions.size\n },\n stop: async () => {\n if (workersInstance.stopPromise) return workersInstance.stopPromise\n\n workersInstance.stopPromise = (async () => {\n logger.info('Stopping job scheduler...')\n workersInstance.running = false\n workersInstance.signalStop()\n\n await workersInstance.schedulerPromise\n\n const activeCapacity = Array.from(\n workersInstance.activeExecutions.values(),\n execution => execution.capacityPromise,\n )\n await Promise.all(activeCapacity)\n })()\n\n return workersInstance.stopPromise\n },\n }\n\n return workersInstance\n }\n\n async ensureRecords(config: StartWorkersConfig) {\n const jobs = this.getJobs(config.jobs)\n\n await Promise.all(\n jobs\n .filter(job => job.type === 'recurrent')\n .map(async job => {\n logger.debug(`Ensuring records for job \"${job.name}\"...`)\n await this.jobsRepo.ensureJobRecord(job)\n }),\n )\n }\n\n async runScheduler(config: StartWorkersConfig, workersInstance: InternalWorkersInstance) {\n logger.debug('Will ensure maxTriesReached retention and TTL index')\n void this.jobsRepo\n .ensureMaxTriesReachedRetention(config.maxTriesReachedRetentionMs)\n .catch(error => logger.error('Error ensuring maxTriesReached retention', {error}))\n\n logger.debug('Will ensure records for recurrent jobs')\n await this.ensureRecords(config)\n\n logger.info(`Starting job scheduler with concurrency ${config.workersCount}`)\n await this.runSchedulerLoop(config, workersInstance)\n }\n\n /**\n * Starts one job scheduler with the provided concurrency configuration.\n * @param userConfig - Configuration for the scheduler. Required field: jobs\n */\n startWorkers(userConfig: StartWorkersConfig): WorkersInstance {\n const maxTriesReachedRetentionMs =\n userConfig.maxTriesReachedRetentionMs === undefined\n ? DEFAULT_MAX_TRIES_REACHED_RETENTION_MS\n : userConfig.maxTriesReachedRetentionMs\n\n if (\n maxTriesReachedRetentionMs !== null &&\n (!Number.isFinite(maxTriesReachedRetentionMs) || maxTriesReachedRetentionMs < 0)\n ) {\n throw new Error('maxTriesReachedRetentionMs must be null, zero, or a positive number')\n }\n\n const config: StartWorkersConfig = {\n pollInterval: 3000,\n workersCount: 4,\n defaultLockTime: 30 * 1000,\n ...userConfig,\n maxTriesReachedRetentionMs,\n }\n\n setNameToJobs(config.jobs)\n\n const workersInstance = this.createWorkersInstanceDefinition(config)\n logger.debug('Starting job scheduler', config)\n\n workersInstance.schedulerPromise = this.runScheduler(config, workersInstance).catch(error => {\n workersInstance.running = false\n logger.error('Job scheduler stopped after an unexpected error.', {error})\n })\n\n return workersInstance\n }\n}\n\nfunction setNameToJobs(jobs: JobsDefinition) {\n for (const name of Object.keys(jobs)) {\n jobs[name].jobName = name\n }\n}\n","import {SpanStatusCode, trace} from '@opentelemetry/api'\nimport {logger, runWithOrionAsyncContext, updateOrionAsyncContext} from '@orion-js/logger'\nimport {Blackbox} from '@orion-js/schema'\nimport {Inject, Service} from '@orion-js/services'\nimport {JobsHistoryRepo} from '../repos/JobsHistoryRepo'\nimport {JobsRepo} from '../repos/JobsRepo'\nimport {EventJobDefinition, JobDefinition, JobsDefinition} from '../types/JobsDefinition'\nimport {ExecutionContext, JobToRun} from '../types/Worker'\nimport {getNextRunDate} from './getNextRunDate'\n\n/**\n * Configuration for job execution including max tries settings.\n */\nexport interface ExecuteJobConfig {\n jobs: JobsDefinition\n maxTries?: number\n maxTriesReachedRetentionMs?: number | null\n onMaxTriesReached?: (job: JobToRun) => Promise<void>\n}\n\n@Service()\nexport class Executor {\n @Inject(() => JobsRepo)\n private readonly jobsRepo: JobsRepo\n\n @Inject(() => JobsHistoryRepo)\n private readonly jobsHistoryRepo: JobsHistoryRepo\n\n /**\n * Determines the effective lock time for a job execution.\n * Job-specific lockTime takes precedence over the default lockTime from config.\n */\n getEffectiveLockTime(job: JobDefinition, jobToRun: JobToRun): number {\n return job.lockTime ?? jobToRun.lockTime\n }\n\n getContext(\n job: JobDefinition,\n jobToRun: JobToRun,\n onStale: () => void,\n isExecutionActive: () => boolean,\n ): ExecutionContext {\n const effectiveLockTime = this.getEffectiveLockTime(job, jobToRun)\n let staleTimeout = setTimeout(() => onStale(), effectiveLockTime)\n staleTimeout.unref?.()\n const contextLogger = logger.addMetadata({\n jobName: jobToRun.name,\n jobId: jobToRun.jobId,\n })\n\n return {\n definition: job,\n record: jobToRun,\n tries: jobToRun.tries || 0,\n clearStaleTimeout: () => clearTimeout(staleTimeout),\n extendLockTime: async (extraTime: number) => {\n if (!isExecutionActive()) {\n contextLogger.warn(`Will not extend lock for stale execution \"${jobToRun.executionId}\"`)\n return\n }\n\n clearTimeout(staleTimeout)\n let didExtend = false\n try {\n didExtend = await this.jobsRepo.extendLockTime(jobToRun.jobId, extraTime, jobToRun.lockId)\n } catch (error) {\n onStale()\n throw error\n }\n if (!didExtend) {\n onStale()\n return\n }\n staleTimeout = setTimeout(() => onStale(), extraTime)\n staleTimeout.unref?.()\n },\n logger: contextLogger,\n }\n }\n\n getJobDefinition(jobToRun: JobToRun, jobs: JobsDefinition) {\n const job = jobs[jobToRun.name]\n\n if (jobToRun.type !== job.type) {\n logger.warn(\n `Job record \"${jobToRun.name}\" is \"${jobToRun.type}\" but definition is \"${job.type}\"`,\n )\n return\n }\n\n return job\n }\n\n /**\n * Determines the effective max tries for an event job.\n * Job-specific maxTries takes precedence over the global maxTries from config.\n */\n getEffectiveMaxTries(job: EventJobDefinition, globalMaxTries?: number): number | undefined {\n return job.maxTries ?? globalMaxTries\n }\n\n /**\n * Handles when a job has reached its maximum retry attempts.\n * Marks the job in the database and invokes the onMaxTriesReached callback when provided.\n */\n async handleMaxTriesReached(\n jobToRun: JobToRun,\n retentionMs?: number | null,\n onMaxTriesReached?: (job: JobToRun) => Promise<void>,\n ) {\n const jobLogger = logger.addMetadata({\n jobName: jobToRun.name,\n jobId: jobToRun.jobId,\n })\n\n jobLogger.warn(\n `Job \"${jobToRun.name}\" has exceeded max tries (${jobToRun.tries}). Marking as maxTriesReached.`,\n )\n const didMark = await this.jobsRepo.markJobAsMaxTriesReached(\n jobToRun.jobId,\n retentionMs,\n jobToRun.lockId,\n )\n\n if (!didMark) {\n jobLogger.warn(`Could not mark job \"${jobToRun.name}\" because its lock is no longer owned`)\n return false\n }\n\n if (!onMaxTriesReached) return true\n\n // Invoke the callback to notify administrators\n try {\n await onMaxTriesReached(jobToRun)\n } catch (callbackError) {\n jobLogger.error(`Error in onMaxTriesReached callback for job \"${jobToRun.name}\"`, {\n error: callbackError,\n })\n }\n\n return true\n }\n\n async onError(error: unknown, job: JobDefinition, jobToRun: JobToRun, context: ExecutionContext) {\n // Helper to schedule next run for recurrent jobs (used when dismissing)\n const scheduleRecurrent = async () => {\n if (job.type === 'recurrent') {\n return this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt: getNextRunDate(job),\n resetTries: true,\n priority: job.priority,\n lockId: jobToRun.lockId,\n })\n }\n return true\n }\n\n const handleRetry = async (nextRunAt: Date) => {\n return this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt,\n resetTries: false,\n priority: job.type === 'recurrent' ? job.priority : jobToRun.priority,\n lockId: jobToRun.lockId,\n })\n }\n\n if (!job.onError) {\n context.logger.error(`Error executing job \"${jobToRun.name}\"`, {error})\n\n return scheduleRecurrent()\n }\n\n context.logger.info(`Error executing job \"${jobToRun.name}\"`, {error})\n const result = await job.onError(\n error instanceof Error ? error : new Error(String(error)),\n jobToRun.params,\n context,\n )\n\n if (result.action === 'dismiss') {\n return scheduleRecurrent()\n }\n\n if (result.action === 'retry') {\n return handleRetry(getNextRunDate(result))\n }\n\n return true\n }\n\n async saveExecution(options: {\n startedAt: Date\n status: 'stale' | 'error' | 'success'\n errorMessage?: string\n result?: Blackbox\n job: JobDefinition\n jobToRun: JobToRun\n }) {\n const {startedAt, status, errorMessage, result, job, jobToRun} = options\n const endedAt = new Date()\n\n if (job.saveExecutionsFor !== 0) {\n const oneWeek = 1000 * 60 * 60 * 24 * 7\n const saveExecutionsFor = job.saveExecutionsFor || oneWeek\n await this.jobsHistoryRepo.saveExecution({\n jobId: jobToRun.jobId,\n executionId: jobToRun.executionId,\n jobName: jobToRun.name,\n type: jobToRun.type,\n priority: jobToRun.priority,\n tries: jobToRun.tries,\n uniqueIdentifier: jobToRun.uniqueIdentifier,\n startedAt,\n endedAt,\n duration: endedAt.getTime() - startedAt.getTime(),\n expiresAt: new Date(Date.now() + saveExecutionsFor),\n status,\n errorMessage,\n params: jobToRun.params,\n result,\n })\n }\n }\n\n async afterExecutionSuccess(job: JobDefinition, jobToRun: JobToRun, context: ExecutionContext) {\n if (job.type === 'recurrent') {\n context.logger.debug(`Scheduling next run for recurrent job \"${jobToRun.name}\"`)\n return this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt: getNextRunDate(job),\n resetTries: true,\n priority: job.priority,\n lockId: jobToRun.lockId,\n })\n }\n if (job.type === 'event') {\n context.logger.debug(`Removing event job after success \"${jobToRun.name}\"`)\n return this.jobsRepo.deleteEventJob(jobToRun.jobId, jobToRun.lockId)\n }\n return false\n }\n\n async executeJob(config: ExecuteJobConfig, jobToRun: JobToRun, onExecutionStale: () => void) {\n const job = this.getJobDefinition(jobToRun, config.jobs)\n if (!job) return\n\n if (job.type === 'event') {\n const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries)\n if (typeof effectiveMaxTries === 'number' && jobToRun.tries > effectiveMaxTries) {\n await this.handleMaxTriesReached(\n jobToRun,\n config.maxTriesReachedRetentionMs,\n config.onMaxTriesReached,\n )\n return\n }\n }\n\n // If job has a custom lockTime different from the default, update the database lock\n const effectiveLockTime = this.getEffectiveLockTime(job, jobToRun)\n if (effectiveLockTime !== jobToRun.lockTime) {\n const didUpdateLock = await this.jobsRepo.updateLockTime(\n jobToRun.jobId,\n effectiveLockTime,\n jobToRun.lockId,\n )\n if (!didUpdateLock) {\n logger.warn(`Will not execute job \"${jobToRun.name}\" because its lock is no longer owned`)\n return\n }\n }\n\n const tracer = trace.getTracer('orionjs.dogs', '1.0')\n\n await tracer.startActiveSpan(`job.${jobToRun.name}.${jobToRun.executionId}`, async span => {\n try {\n const startedAt = new Date()\n let executionStatus: 'running' | 'stale' = 'running'\n let staleHandlingPromise: Promise<void> | undefined\n let context: ExecutionContext\n\n const markAsStale = () => {\n if (executionStatus === 'stale') return staleHandlingPromise\n\n executionStatus = 'stale'\n context.clearStaleTimeout()\n\n staleHandlingPromise = (async () => {\n context.logger.warn(`Job \"${jobToRun.name}\" is stale`)\n\n if (job.onStale) {\n void Promise.resolve(job.onStale(jobToRun.params, context)).catch(error => {\n context.logger.error(`Error in onStale callback for job \"${jobToRun.name}\"`, {\n error,\n })\n })\n }\n\n try {\n await this.jobsRepo.setJobRecordPriority(jobToRun.jobId, 0, jobToRun.lockId)\n } catch (error) {\n context.logger.error(`Error lowering priority for stale job \"${jobToRun.name}\"`, {\n error,\n })\n } finally {\n // Preserve the current ordering guarantee: a stale retry only becomes eligible for\n // local capacity after its priority has been lowered.\n onExecutionStale()\n }\n\n await this.saveExecution({\n startedAt,\n status: 'stale',\n result: null,\n errorMessage: null,\n job,\n jobToRun,\n })\n })().catch(error => {\n context.logger.error('Error handling stale execution', {error})\n })\n\n return staleHandlingPromise\n }\n\n context = this.getContext(\n job,\n jobToRun,\n () => void markAsStale(),\n () => executionStatus === 'running',\n )\n\n const extraContext = {\n controllerType: 'job' as const,\n jobName: jobToRun.name,\n jobId: jobToRun.jobId,\n params: jobToRun.params,\n }\n\n await runWithOrionAsyncContext(extraContext, async () => {\n try {\n // Inject async context update\n updateOrionAsyncContext({\n jobName: jobToRun.name,\n jobId: jobToRun.jobId,\n params: jobToRun.params,\n })\n const result = await job.resolve(jobToRun.params, context)\n context.clearStaleTimeout()\n\n if (executionStatus === 'stale') {\n await staleHandlingPromise\n context.logger.warn(\n `Ignoring late success from stale execution \"${jobToRun.executionId}\"`,\n )\n return\n }\n\n const stillOwnsJob = await this.afterExecutionSuccess(job, jobToRun, context)\n if (!stillOwnsJob) {\n await markAsStale()\n return\n }\n\n void this.saveExecution({\n startedAt,\n status: 'success',\n result: result || null,\n errorMessage: null,\n job,\n jobToRun,\n }).catch(error => {\n context.logger.error('Error saving successful execution history', {error})\n })\n } catch (error) {\n context.clearStaleTimeout()\n\n if (executionStatus === 'stale') {\n await staleHandlingPromise\n context.logger.warn(\n `Ignoring late error from stale execution \"${jobToRun.executionId}\"`,\n {error},\n )\n return\n }\n\n const stillOwnsJob = await this.onError(error, job, jobToRun, context)\n if (!stillOwnsJob) {\n await markAsStale()\n return\n }\n\n void this.saveExecution({\n startedAt,\n status: 'error',\n result: null,\n errorMessage: (error as Error).message,\n job,\n jobToRun,\n }).catch(saveError => {\n context.logger.error('Error saving failed execution history', {error: saveError})\n })\n }\n })\n } catch (error) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: (error as Error).message,\n })\n throw error\n } finally {\n span.end()\n }\n })\n }\n}\n","import {Collection, MongoCollection, Repository, MongoDB} from '@orion-js/mongodb'\nimport {omit} from 'rambdax'\nimport {HistoryRecord, HistoryRecordSchema} from '../types/HistoryRecord'\n\n@Repository()\nexport class JobsHistoryRepo {\n @MongoCollection({\n name: 'orionjs.jobs_dogs_history',\n idGeneration: 'uuid',\n schema: HistoryRecordSchema,\n indexes: [\n {\n keys: {\n jobName: 1,\n startedAt: 1,\n },\n },\n {\n keys: {\n executionId: 1,\n },\n },\n {\n keys: {\n expiresAt: 1,\n },\n options: {\n expireAfterSeconds: 0,\n },\n },\n ],\n })\n history: Collection<HistoryRecord>\n\n async saveExecution(record: MongoDB.WithoutId<HistoryRecord>) {\n await this.history.upsert(\n {executionId: record.executionId},\n {\n $setOnInsert: {\n status: record.status,\n },\n $set: {\n ...omit(['status'], record),\n },\n },\n )\n }\n\n async getExecutions(jobName: string, limit?: number, skip?: number): Promise<HistoryRecord[]> {\n const cursor = this.history.find({jobName}).sort({startedAt: -1})\n\n if (skip) {\n cursor.skip(skip)\n }\n\n if (limit) {\n cursor.limit(limit)\n }\n\n return await cursor.toArray()\n }\n}\n","function _isInteger(n){\n return n << 0 === n\n}\n\nexport const isInteger = Number.isInteger || _isInteger\n\n/**\n * Check if `index` is integer even if it is a string.\n */\nexport const isIndexInteger = index => Number.isInteger(Number(index))\n","import { isInteger } from './isInteger.js'\n\nexport function createPath(path, delimiter = '.'){\n return typeof path === 'string' ?\n path.split(delimiter).map(x => isInteger(x) ? Number(x) : x) :\n path\n}\n","export function compare(a, b){\n return String(a) === String(b)\n}\n","import { compare } from './compare.js'\n\nexport function includes(a, list){\n let index = -1\n const { length } = list\n\n while (++index < length)\n if (compare(list[ index ], a))\n return true\n\n return false\n}\n","import { createPath } from './_internals/createPath.js'\nimport { includes } from './_internals/includes.js'\n\nexport function omit(propsToOmit, obj){\n if (arguments.length === 1) return _obj => omit(propsToOmit, _obj)\n\n if (obj === null || obj === undefined)\n return undefined\n\n const propsToOmitValue = createPath(propsToOmit, ',')\n const willReturn = {}\n\n for (const key in obj)\n if (!includes(key, propsToOmitValue))\n willReturn[ key ] = obj[ key ]\n\n return willReturn\n}\n","import {InferSchemaType, schemaWithName} from '@orion-js/schema'\n\nexport const HistoryRecordSchema = schemaWithName('HistoryRecord', {\n _id: {type: 'string'},\n jobId: {type: 'string'},\n executionId: {type: 'string'},\n jobName: {type: 'string'},\n type: {type: 'string'},\n priority: {type: 'number'},\n tries: {type: 'number'},\n uniqueIdentifier: {type: 'string', optional: true},\n startedAt: {type: 'date'},\n endedAt: {type: 'date'},\n duration: {type: 'number'},\n expiresAt: {type: 'date', optional: true},\n status: {type: 'string', enum: ['success', 'error', 'stale']},\n errorMessage: {type: 'string', optional: true},\n params: {type: 'blackbox', optional: true},\n result: {type: 'any', optional: true},\n})\n\nexport type HistoryRecord = InferSchemaType<typeof HistoryRecordSchema>\n","import {getInstance, Service} from '@orion-js/services'\nimport {createEventJob, defineJob} from '../defineJob'\nimport type {CreateEventJobOptions, JobDefinition, RecurrentJobDefinition} from '../types'\n\n// Define metadata storage using WeakMaps\nconst serviceMetadata = new WeakMap<any, {_serviceType: string}>()\nconst jobsMetadata = new Map<any, Record<string, any>>()\nconst jobEntriesByClass = new Map<Function, Record<string, (instance: any) => any>>()\nlet pendingJobEntries: Record<string, (instance: any) => any> = {}\n\nexport function Jobs() {\n return (target: any, context: ClassDecoratorContext<any>) => {\n Service()(target, context)\n serviceMetadata.set(target, {_serviceType: 'jobs'})\n\n if (Object.keys(pendingJobEntries).length > 0) {\n jobEntriesByClass.set(target, pendingJobEntries)\n pendingJobEntries = {}\n }\n }\n}\n\nexport function RecurrentJob(): (\n method: any,\n context: ClassFieldDecoratorContext | ClassMethodDecoratorContext,\n) => any\nexport function RecurrentJob(\n options: Omit<RecurrentJobDefinition, 'resolve' | 'type'>,\n): (method: any, context: ClassMethodDecoratorContext) => any\nexport function RecurrentJob(options = {}) {\n return (method: any, context: ClassFieldDecoratorContext | ClassMethodDecoratorContext) => {\n const propertyKey = String(context.name)\n\n if (context.kind === 'method') {\n pendingJobEntries[propertyKey] = (instance: any) =>\n defineJob({\n ...options,\n type: 'recurrent',\n resolve: instance[propertyKey].bind(instance),\n })\n }\n\n if (context.kind === 'field') {\n pendingJobEntries[propertyKey] = (instance: any) => instance[propertyKey]\n }\n\n return method\n }\n}\n\nexport function EventJob(): (\n method: any,\n context: ClassFieldDecoratorContext | ClassMethodDecoratorContext,\n) => any\nexport function EventJob(\n options: Omit<CreateEventJobOptions<any>, 'resolve'>,\n): (method: any, context: ClassMethodDecoratorContext) => any\nexport function EventJob(options = {}) {\n return (method: any, context: ClassFieldDecoratorContext | ClassMethodDecoratorContext) => {\n const propertyKey = String(context.name)\n\n if (context.kind === 'method') {\n pendingJobEntries[propertyKey] = (instance: any) =>\n createEventJob({\n ...options,\n resolve: instance[propertyKey].bind(instance),\n })\n }\n\n if (context.kind === 'field') {\n pendingJobEntries[propertyKey] = (instance: any) => instance[propertyKey]\n }\n\n return method\n }\n}\n\nfunction initializeJobsIfNeeded(instance: any) {\n if (jobsMetadata.has(instance)) return\n const entries = jobEntriesByClass.get(instance.constructor) || {}\n const jobs: Record<string, any> = {}\n for (const [key, setup] of Object.entries(entries)) {\n jobs[key] = setup(instance)\n }\n jobsMetadata.set(instance, jobs)\n}\n\nexport function getServiceJobs(target: any): {\n [key: string]: JobDefinition\n} {\n const instance = getInstance(target)\n\n if (!serviceMetadata.has(instance.constructor)) {\n throw new Error('You must pass a class decorated with @Jobs to getServiceJobs')\n }\n\n const instanceMetadata = serviceMetadata.get(instance.constructor)\n if (instanceMetadata._serviceType !== 'jobs') {\n throw new Error('You must pass a class decorated with @Jobs to getServiceJobs')\n }\n\n initializeJobsIfNeeded(instance)\n\n const jobsMap = jobsMetadata.get(instance) || {}\n\n return jobsMap\n}\n","import {cleanAndValidate, SchemaInAnyOrionForm} from '@orion-js/schema'\nimport {CronExpressionParser} from 'cron-parser'\nimport parse from 'parse-duration'\nimport {ScheduleJobsResult, scheduleJob, scheduleJobs} from '..'\nimport {ScheduleJobOptionsWithoutName} from '../types/Events'\nimport {\n CreateEventJobOptions,\n CreateJobOptions,\n CreateRecurrentJobOptions,\n EventJobDefinition,\n JobDefinition,\n RecurrentJobDefinition,\n} from '../types/JobsDefinition'\n\nexport function createEventJob<TParamsSchema extends SchemaInAnyOrionForm>(\n options: CreateEventJobOptions<TParamsSchema>,\n): EventJobDefinition<TParamsSchema> {\n const jobDefinition: EventJobDefinition<TParamsSchema> = {\n ...options,\n type: 'event',\n schedule: null,\n scheduleJobs: null,\n }\n\n jobDefinition.schedule = async (\n scheduleOptions: ScheduleJobOptionsWithoutName<TParamsSchema>,\n ) => {\n if (!jobDefinition.jobName) {\n throw new Error('This job has not been registered in the workers')\n }\n\n const params = jobDefinition.params\n ? await cleanAndValidate(jobDefinition.params, scheduleOptions.params)\n : scheduleOptions.params\n\n return await scheduleJob({\n ...scheduleOptions,\n name: jobDefinition.jobName,\n params,\n })\n }\n\n jobDefinition.scheduleJobs = async (\n jobs: Array<ScheduleJobOptionsWithoutName<TParamsSchema>>,\n ): Promise<ScheduleJobsResult> => {\n if (!jobDefinition.jobName) {\n throw new Error('This job has not been registered in the workers')\n }\n\n // Process all job parameters if schema validation is needed\n const processedJobs = await Promise.all(\n jobs.map(async scheduleOptions => {\n const params = jobDefinition.params\n ? await cleanAndValidate(jobDefinition.params, scheduleOptions.params)\n : scheduleOptions.params\n\n return {\n ...scheduleOptions,\n name: jobDefinition.jobName,\n params,\n }\n }),\n )\n\n return await scheduleJobs(processedJobs)\n }\n\n return jobDefinition\n}\n\nexport function createRecurrentJob(options: CreateRecurrentJobOptions): RecurrentJobDefinition {\n const recurrentOptions = {\n ...options,\n } as CreateRecurrentJobOptions & {maxTries?: number}\n\n delete recurrentOptions.maxTries\n\n if ('cron' in recurrentOptions && recurrentOptions.cron && !recurrentOptions.timezone) {\n throw new Error('Cron recurrent jobs require a timezone')\n }\n\n if ('cron' in recurrentOptions && recurrentOptions.cron) {\n CronExpressionParser.parse(recurrentOptions.cron, {tz: recurrentOptions.timezone}).next()\n }\n\n const runEvery =\n 'runEvery' in recurrentOptions\n ? typeof recurrentOptions.runEvery === 'string'\n ? parse(recurrentOptions.runEvery)\n : recurrentOptions.runEvery\n : undefined\n\n const jobDefinition: RecurrentJobDefinition = {\n ...recurrentOptions,\n priority: recurrentOptions.priority ?? 100,\n type: 'recurrent',\n runEvery,\n }\n\n return jobDefinition\n}\n\n/**\n * @deprecated Use `createEventJob` or `createRecurrentJob` instead.\n */\nexport const defineJob = (\n options: CreateJobOptions & {type: 'event' | 'recurrent'},\n): JobDefinition => {\n return options.type === 'event'\n ? createEventJob(options as any)\n : createRecurrentJob(options as any)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAQ,eAAAA,oBAAkB;;;ACA1B,SAAQ,UAAAC,eAAa;AACrB,SAAQ,QAAQ,eAAc;;;ACD9B,SAAQ,kBAAiB;AACzB,SAAQ,cAAa;AACrB,SAAoB,iBAA0B,kBAAiB;;;ACF/D,SAAQ,YAA6B,sBAAqB;AAOnD,IAAM,gBAAgB,WAAW,aAAa,CAAC,WAAW,iBAAiB,CAAC;AAE5E,IAAM,kBAAkB,eAAe,aAAa;AAAA,EACzD,KAAK,EAAC,MAAM,SAAQ;AAAA,EACpB,SAAS,EAAC,MAAM,SAAQ;AAAA,EACxB,MAAM,EAAC,MAAM,WAAW,WAAW,CAAC,aAAa,OAAO,CAAC,EAAC;AAAA,EAC1D,UAAU,EAAC,MAAM,SAAQ;AAAA,EACzB,kBAAkB,EAAC,MAAM,UAAU,UAAU,KAAI;AAAA,EACjD,WAAW,EAAC,MAAM,OAAM;AAAA,EACxB,WAAW,EAAC,MAAM,QAAQ,UAAU,KAAI;AAAA,EACxC,aAAa,EAAC,MAAM,QAAQ,UAAU,KAAI;AAAA;AAAA;AAAA;AAAA;AAAA,EAK1C,QAAQ,EAAC,MAAM,UAAU,UAAU,KAAI;AAAA,EACvC,OAAO,EAAC,MAAM,UAAU,UAAU,KAAI;AAAA,EACtC,QAAQ,EAAC,MAAM,YAAY,UAAU,KAAI;AAAA;AAAA;AAAA;AAAA;AAAA,EAKzC,QAAQ,EAAC,MAAM,eAAe,UAAU,KAAI;AAAA;AAAA;AAAA;AAAA;AAAA,EAK5C,mBAAmB,EAAC,MAAM,QAAQ,UAAU,KAAI;AAAA;AAAA;AAAA;AAAA,EAIhD,WAAW,EAAC,MAAM,QAAQ,UAAU,KAAI;AAC1C,CAAC;;;AClCM,IAAM,yCAAyC,MAAO,KAAK,KAAK,KAAK;;;AFL5E;AASA,wBAAC,WAAW,IAEV,aAAC,gBAAgB;AAAA,EACf,cAAc;AAAA,EACd,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,SAAS;AAAA,IACP;AAAA,MACE,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,UAAU;AAAA,QACV,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,QACJ,SAAS;AAAA,MACX;AAAA,MACA,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,yBAAyB,EAAC,MAAM,YAAW;AAAA,MAC7C;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,QACJ,kBAAkB;AAAA,MACpB;AAAA,MACA,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,QACJ,WAAW;AAAA,MACb;AAAA,MACA,MAAM;AAAA,MACN,oBAAoB;AAAA,IACtB;AAAA,EACF;AACF,CAAC;AAvCI,IAAM,WAAN,MAAe;AAAA,EAAf;AAwCL;AAAA;AAAA,EAEA,MAAM,cAAc,UAAoB,UAAqC;AAC3E,UAAM,cAAc,WAAW;AAC/B,UAAM,cAAc,IAAI,KAAK,KAAK,IAAI,IAAI,QAAQ;AAElD,UAAM,MAAM,MAAM,KAAK,KAAK;AAAA,MAC1B;AAAA,QACE,SAAS,EAAC,KAAK,SAAQ;AAAA,QACvB,WAAW,EAAC,MAAM,oBAAI,KAAK,EAAC;AAAA,QAC5B,MAAM;AAAA,UACJ,EAAC,KAAK,CAAC,EAAC,aAAa,EAAC,SAAS,MAAK,EAAC,GAAG,EAAC,aAAa,EAAC,MAAM,oBAAI,KAAK,EAAC,EAAC,CAAC,EAAC;AAAA;AAAA;AAAA,UAG1E,EAAC,KAAK,CAAC,EAAC,MAAM,EAAC,KAAK,QAAO,EAAC,GAAG,EAAC,QAAQ,EAAC,KAAK,kBAAiB,EAAC,CAAC,EAAC;AAAA,QACpE;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,EAAC,QAAQ,aAAa,aAAa,WAAW,oBAAI,KAAK,EAAC;AAAA,QAC9D,MAAM,EAAC,OAAO,EAAC;AAAA,MACjB;AAAA,MACA;AAAA,QACE,cAAc;AAAA,UACZ,MAAM;AAAA,YACJ,UAAU;AAAA,YACV,WAAW;AAAA,UACb;AAAA,UACA,gBAAgB;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,IAAK;AAEV,UAAM,SAAS,IAAI,SAAS,KAAK;AACjC,UAAM,WAAW,QAAQ,IAAI,WAAW;AAExC,QAAI,UAAU;AACZ,aAAO,KAAK,gBAAgB,IAAI,OAAO,mBAAmB;AAAA,IAC5D;AAEA,WAAO;AAAA,MACL,OAAO,IAAI;AAAA,MACX;AAAA,MACA,QAAQ;AAAA,MACR,MAAM,IAAI;AAAA,MACV,QAAQ,IAAI;AAAA,MACZ,MAAM,IAAI;AAAA,MACV;AAAA,MACA;AAAA,MACA,UAAU,IAAI;AAAA,MACd,kBAAkB,IAAI;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,qBAAqB,OAAe,UAAkB,QAAiB;AAC3E,UAAM,SAAS,MAAM,KAAK,KAAK,UAAU,SAAS,EAAC,KAAK,OAAO,OAAM,IAAI,OAAO;AAAA,MAC9E,MAAM,EAAC,SAAQ;AAAA,IACjB,CAAC;AACD,WAAO,OAAO,eAAe;AAAA,EAC/B;AAAA,EAEA,MAAM,gBAAgB,SAMnB;AACD,UAAM,UAA2C;AAAA,MAC/C,MAAM;AAAA,QACJ,WAAW,QAAQ;AAAA,QACnB,UAAU,QAAQ;AAAA,QAClB,GAAI,QAAQ,aAAa,EAAC,OAAO,EAAC,IAAI,CAAC;AAAA,MACzC;AAAA,MACA,QAAQ,EAAC,QAAQ,IAAI,aAAa,GAAE;AAAA,IACtC;AAEA,UAAM,SAAS,MAAM,KAAK,KAAK;AAAA,MAC7B,QAAQ,SAAS,EAAC,KAAK,QAAQ,OAAO,QAAQ,QAAQ,OAAM,IAAI,QAAQ;AAAA,MACxE;AAAA,IACF;AACA,WAAO,OAAO,eAAe;AAAA,EAC/B;AAAA,EAEA,MAAM,eAAe,OAAe,QAAiB;AACnD,UAAM,SAAS,MAAM,KAAK,KAAK,UAAU;AAAA,MACvC,KAAK;AAAA,MACL,MAAM;AAAA,MACN,GAAI,SAAS,EAAC,OAAM,IAAI,CAAC;AAAA,IAC3B,CAAC;AACD,WAAO,OAAO,eAAe;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,yBACJ,OACA,cAA6B,wCAC7B,QACA;AACA,UAAM,oBAAoB,oBAAI,KAAK;AACnC,UAAM,SAAS,MAAM,KAAK,KAAK;AAAA,MAC7B,EAAC,KAAK,OAAO,MAAM,SAAS,GAAI,SAAS,EAAC,OAAM,IAAI,CAAC,EAAE;AAAA,MACvD;AAAA,QACE,MAAM;AAAA,UACJ,QAAQ;AAAA,UACR;AAAA,UACA,GAAI,gBAAgB,OAChB,CAAC,IACD,EAAC,WAAW,IAAI,KAAK,kBAAkB,QAAQ,IAAI,WAAW,EAAC;AAAA,QACrE;AAAA,QACA,QAAQ;AAAA,UACN,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,GAAI,gBAAgB,OAAO,EAAC,WAAW,GAAE,IAAI,CAAC;AAAA,QAChD;AAAA,MACF;AAAA,IACF;AACA,WAAO,OAAO,eAAe;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,+BAA+B,aAA4B;AAC/D,UAAM,WAAW;AAAA,MACf,MAAM;AAAA,MACN,QAAQ;AAAA,IACV;AAEA,QAAI,gBAAgB,MAAM;AACxB,YAAM,KAAK,KAAK,WAAW,UAAU,EAAC,QAAQ,EAAC,WAAW,GAAE,EAAC,CAAC;AAC9D;AAAA,IACF;AAEA,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,kBAAkB;AAAA,MACtB,SAAS,CAAC,sBAAsB,EAAC,SAAS,CAAC,cAAc,GAAG,EAAC,CAAC;AAAA,IAChE;AAEA,UAAM,KAAK,KAAK,cAAc,WAAW,UAAU;AAAA,MACjD;AAAA,QACE,MAAM;AAAA,UACJ,mBAAmB;AAAA,UACnB,WAAW,EAAC,MAAM,CAAC,iBAAiB,WAAW,EAAC;AAAA,QAClD;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,eAAe,OAAe,WAAmB,QAAiB;AACtE,WAAO,KAAK,eAAe,OAAO,WAAW,MAAM;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,eAAe,OAAe,cAAsB,QAAiB;AACzE,UAAM,cAAc,IAAI,KAAK,KAAK,IAAI,IAAI,YAAY;AACtD,UAAM,SAAS,MAAM,KAAK,KAAK;AAAA,MAC7B,EAAC,KAAK,OAAO,GAAI,SAAS,EAAC,OAAM,IAAI,CAAC,EAAE;AAAA,MACxC;AAAA,QACE,MAAM,EAAC,YAAW;AAAA,MACpB;AAAA,IACF;AACA,WAAO,OAAO,eAAe;AAAA,EAC/B;AAAA,EAEA,MAAM,gBAAiC;AACrC,UAAM,SAAS,MAAM,KAAK,KAAK;AAAA,MAC7B;AAAA,QACE,aAAa,EAAC,SAAS,KAAI;AAAA,MAC7B;AAAA,MACA;AAAA,QACE,QAAQ,EAAC,QAAQ,IAAI,aAAa,GAAE;AAAA,MACtC;AAAA,IACF;AAEA,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,MAAM,gBAAgB,KAA4B;AAChD,UAAM,SAAS,MAAM,KAAK,KAAK;AAAA,MAC7B;AAAA,QACE,SAAS,IAAI;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,UACJ,MAAM,IAAI;AAAA,UACV,UAAW,IAA+B;AAAA,QAC5C;AAAA,QACA,QAAQ;AAAA,UACN,QAAQ;AAAA,QACV;AAAA,QACA,cAAc;AAAA,UACZ,WAAW,oBAAI,KAAK;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAEA,QAAI,OAAO,YAAY;AACrB,aAAO,MAAM,2BAA2B,IAAI,IAAI,GAAG;AAAA,IACrD,OAAO;AACL,aAAO,MAAM,mBAAmB,IAAI,IAAI,kBAAkB;AAAA,IAC5D;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,SAAmC;AACnD,QAAI;AACF,YAAM,KAAK,KAAK,UAAU;AAAA,QACxB,SAAS,QAAQ;AAAA,QACjB,kBAAkB,QAAQ;AAAA,QAC1B,QAAQ,QAAQ;AAAA,QAChB,WAAW,QAAQ;AAAA,QACnB,UAAU,QAAQ;AAAA,QAClB,MAAM;AAAA,MACR,CAAC;AAAA,IACH,SAAS,OAAO;AACd,UACE,MAAM,qBACN,OAAO,OAAO,MAAM,gBAAgB,EAAE,SAAS,WAAW,KAC1D,QAAQ,kBACR;AACA,eAAO;AAAA,UACL,QAAQ,QAAQ,IAAI,sBAAsB,QAAQ,gBAAgB;AAAA,QACpE;AAAA,MACF,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,MAA+D;AAChF,QAAI,KAAK,WAAW,GAAG;AACrB,aAAO,EAAC,gBAAgB,GAAG,cAAc,GAAG,QAAQ,CAAC,EAAC;AAAA,IACxD;AAGA,QAAI,iBAAiB;AACrB,QAAI,eAAe;AACnB,UAAM,SAA8E,CAAC;AAErF,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,MAAM,KAAK,CAAC;AAClB,UAAI;AAEF,cAAM,KAAK,KAAK,UAAU;AAAA,UACxB,SAAS,IAAI;AAAA,UACb,kBAAkB,IAAI;AAAA,UACtB,QAAQ,IAAI;AAAA,UACZ,WAAW,IAAI;AAAA,UACf,UAAU,IAAI;AAAA,UACd,MAAM;AAAA,QACR,CAAC;AACD;AAAA,MACF,SAAS,OAAO;AAEd,YACE,MAAM,qBACN,OAAO,OAAO,MAAM,gBAAgB,EAAE,SAAS,WAAW,KAC1D,IAAI,kBACJ;AACA,iBAAO,KAAK,QAAQ,IAAI,IAAI,sBAAsB,IAAI,gBAAgB,kBAAkB;AACxF;AAAA,QACF,OAAO;AACL,iBAAO,KAAK;AAAA,YACV,OAAO;AAAA,YACP,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,YAC/D;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,aAAa,cAAc,+BAA+B,YAAY,aAAa,OAAO,MAAM;AAAA,IAClG;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AA5UO;AAwCL,oCAvCA,WADW;AAAA,WAAN,wCADP,sBACa;AAAN,4BAAM;;;AGVb,SAAQ,4BAA2B;AAY5B,IAAM,iBAAiB,CAAC,YAAqB;AAClD,MAAI,QAAQ,OAAO;AACjB,WAAO,IAAI,KAAK,KAAK,IAAI,IAAI,QAAQ,KAAK;AAAA,EAC5C;AAEA,MAAI,QAAQ,UAAU;AACpB,WAAO,IAAI,KAAK,KAAK,IAAI,IAAI,QAAQ,QAAQ;AAAA,EAC/C;AAEA,MAAI,QAAQ,MAAM;AAChB,QAAI,CAAC,QAAQ,UAAU;AACrB,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC1D;AAEA,WAAO,qBAAqB,MAAM,QAAQ,MAAM;AAAA,MAC9C,aAAa,QAAQ,eAAe,oBAAI,KAAK;AAAA,MAC7C,IAAI,QAAQ;AAAA,IACd,CAAC,EACE,KAAK,EACL,OAAO;AAAA,EACZ;AAEA,MAAI,QAAQ,OAAO;AACjB,WAAO,QAAQ;AAAA,EACjB;AAEA,MAAI,QAAQ,YAAY;AACtB,WAAO,QAAQ,WAAW;AAAA,EAC5B;AAEA,SAAO,oBAAI,KAAK;AAClB;;;AJ3CA,8CAAAC;AAMA,6BAAC,QAAQ,IAEP,iBAAC,OAAO,MAAM,QAAQ;AADjB,IAAM,gBAAN,MAAoB;AAAA,EAApB;AAEL,wBAAQ,YAAR,kBAAAA,QAAA,6BAAAA,QAAA;AAAA;AAAA,EAEA,MAAM,YAAY,SAA6B;AAC7C,IAAAC,QAAO,MAAM,qBAAqB,OAAO;AAEzC,UAAM,KAAK,SAAS,YAAY;AAAA,MAC9B,MAAM,QAAQ;AAAA,MACd,UAAU,QAAQ,YAAY;AAAA,MAC9B,WAAW,eAAe,OAAO;AAAA,MACjC,QAAQ,QAAQ,UAAU;AAAA,MAC1B,kBAAkB,QAAQ;AAAA,IAC5B,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,aAAa,MAAwD;AACzE,IAAAA,QAAO,MAAM,cAAc,KAAK,MAAM,UAAU;AAEhD,UAAM,aAAa,KAAK,IAAI,cAAY;AAAA,MACtC,MAAM,QAAQ;AAAA,MACd,UAAU,QAAQ,YAAY;AAAA,MAC9B,WAAW,eAAe,OAAO;AAAA,MACjC,QAAQ,QAAQ,UAAU;AAAA,MAC1B,kBAAkB,QAAQ;AAAA,IAC5B,EAAE;AAEF,WAAO,MAAM,KAAK,SAAS,aAAa,UAAU;AAAA,EACpD;AACF;AA7BOD,SAAA;AAEL,kBAAAA,QAAA,GAAQ,YADR,eADW;AAAA,gBAAN,kBAAAA,QAAA,oBADP,2BACa;AAAN,kBAAAA,QAAA,GAAM;;;AKPb,SAAQ,aAAY;AACpB,SAAQ,UAAAE,eAAa;AACrB,SAAQ,UAAAC,SAAQ,WAAAC,gBAAc;;;ACF9B,SAAQ,gBAAgB,aAAY;AACpC,SAAQ,UAAAC,SAAQ,0BAA0B,+BAA8B;AAExE,SAAQ,UAAAC,SAAQ,WAAAC,gBAAc;;;ACH9B,SAAoB,mBAAAC,kBAAiB,cAAAC,mBAA0B;;;ACA/D,SAAS,WAAW,GAAE;AACpB,SAAO,KAAK,MAAM;AACpB;AAEO,IAAM,YAAY,OAAO,aAAa;;;ACFtC,SAAS,WAAW,MAAM,YAAY,KAAI;AAC/C,SAAO,OAAO,SAAS,WACrB,KAAK,MAAM,SAAS,EAAE,IAAI,OAAK,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,IAC3D;AACJ;;;ACNO,SAAS,QAAQ,GAAG,GAAE;AAC3B,SAAO,OAAO,CAAC,MAAM,OAAO,CAAC;AAC/B;;;ACAO,SAAS,SAAS,GAAG,MAAK;AAC/B,MAAI,QAAQ;AACZ,QAAM,EAAE,OAAO,IAAI;AAEnB,SAAO,EAAE,QAAQ;AACf,QAAI,QAAQ,KAAM,KAAM,GAAG,CAAC;AAC1B,aAAO;AAEX,SAAO;AACT;;;ACRO,SAAS,KAAK,aAAa,KAAI;AACpC,MAAI,UAAU,WAAW,EAAG,QAAO,UAAQ,KAAK,aAAa,IAAI;AAEjE,MAAI,QAAQ,QAAQ,QAAQ;AAC1B,WAAO;AAET,QAAM,mBAAmB,WAAW,aAAa,GAAG;AACpD,QAAM,aAAa,CAAC;AAEpB,aAAW,OAAO;AAChB,QAAI,CAAC,SAAS,KAAK,gBAAgB;AACjC,iBAAY,GAAI,IAAI,IAAK,GAAI;AAEjC,SAAO;AACT;;;ACjBA,SAAyB,kBAAAC,uBAAqB;AAEvC,IAAM,sBAAsBA,gBAAe,iBAAiB;AAAA,EACjE,KAAK,EAAC,MAAM,SAAQ;AAAA,EACpB,OAAO,EAAC,MAAM,SAAQ;AAAA,EACtB,aAAa,EAAC,MAAM,SAAQ;AAAA,EAC5B,SAAS,EAAC,MAAM,SAAQ;AAAA,EACxB,MAAM,EAAC,MAAM,SAAQ;AAAA,EACrB,UAAU,EAAC,MAAM,SAAQ;AAAA,EACzB,OAAO,EAAC,MAAM,SAAQ;AAAA,EACtB,kBAAkB,EAAC,MAAM,UAAU,UAAU,KAAI;AAAA,EACjD,WAAW,EAAC,MAAM,OAAM;AAAA,EACxB,SAAS,EAAC,MAAM,OAAM;AAAA,EACtB,UAAU,EAAC,MAAM,SAAQ;AAAA,EACzB,WAAW,EAAC,MAAM,QAAQ,UAAU,KAAI;AAAA,EACxC,QAAQ,EAAC,MAAM,UAAU,MAAM,CAAC,WAAW,SAAS,OAAO,EAAC;AAAA,EAC5D,cAAc,EAAC,MAAM,UAAU,UAAU,KAAI;AAAA,EAC7C,QAAQ,EAAC,MAAM,YAAY,UAAU,KAAI;AAAA,EACzC,QAAQ,EAAC,MAAM,OAAO,UAAU,KAAI;AACtC,CAAC;;;ANnBD,+CAAAC;AAIA,+BAACC,YAAW,IAEV,gBAACC,iBAAgB;AAAA,EACf,MAAM;AAAA,EACN,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,SAAS;AAAA,IACP;AAAA,MACE,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,QACJ,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,QACJ,WAAW;AAAA,MACb;AAAA,MACA,SAAS;AAAA,QACP,oBAAoB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AACF,CAAC;AA1BI,IAAM,kBAAN,MAAsB;AAAA,EAAtB;AA2BL,qDAAAF,QAAA,6BAAAA,QAAA;AAAA;AAAA,EAEA,MAAM,cAAc,QAA0C;AAC5D,UAAM,KAAK,QAAQ;AAAA,MACjB,EAAC,aAAa,OAAO,YAAW;AAAA,MAChC;AAAA,QACE,cAAc;AAAA,UACZ,QAAQ,OAAO;AAAA,QACjB;AAAA,QACA,MAAM;AAAA,UACJ,GAAG,KAAK,CAAC,QAAQ,GAAG,MAAM;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,SAAiB,OAAgB,MAAyC;AAC5F,UAAM,SAAS,KAAK,QAAQ,KAAK,EAAC,QAAO,CAAC,EAAE,KAAK,EAAC,WAAW,GAAE,CAAC;AAEhE,QAAI,MAAM;AACR,aAAO,KAAK,IAAI;AAAA,IAClB;AAEA,QAAI,OAAO;AACT,aAAO,MAAM,KAAK;AAAA,IACpB;AAEA,WAAO,MAAM,OAAO,QAAQ;AAAA,EAC9B;AACF;AAxDOA,SAAA;AA2BL,kBAAAA,QAAA,cA1BA,cADW;AAAA,kBAAN,kBAAAA,QAAA,sBADP,6BACa;AAAN,kBAAAA,QAAA,GAAM;;;ADLb,0BAAAG,gBAAA,sBAAAC;AAoBA,wBAACC,SAAQ,IAEPF,iBAAA,CAACG,QAAO,MAAM,QAAQ,IAGtB,wBAACA,QAAO,MAAM,eAAe;AAJxB,IAAM,WAAN,MAAe;AAAA,EAAf;AAEL,wBAAiB,YAAjB,kBAAAF,QAAA,6BAAAA,QAAA;AAGA,wBAAiB,mBAAjB,kBAAAA,QAAA,8BAAAA,QAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAqB,KAAoB,UAA4B;AACnE,WAAO,IAAI,YAAY,SAAS;AAAA,EAClC;AAAA,EAEA,WACE,KACA,UACA,SACA,mBACkB;AAzCtB;AA0CI,UAAM,oBAAoB,KAAK,qBAAqB,KAAK,QAAQ;AACjE,QAAI,eAAe,WAAW,MAAM,QAAQ,GAAG,iBAAiB;AAChE,uBAAa,UAAb;AACA,UAAM,gBAAgBG,QAAO,YAAY;AAAA,MACvC,SAAS,SAAS;AAAA,MAClB,OAAO,SAAS;AAAA,IAClB,CAAC;AAED,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,OAAO,SAAS,SAAS;AAAA,MACzB,mBAAmB,MAAM,aAAa,YAAY;AAAA,MAClD,gBAAgB,OAAO,cAAsB;AAvDnD,YAAAC;AAwDQ,YAAI,CAAC,kBAAkB,GAAG;AACxB,wBAAc,KAAK,6CAA6C,SAAS,WAAW,GAAG;AACvF;AAAA,QACF;AAEA,qBAAa,YAAY;AACzB,YAAI,YAAY;AAChB,YAAI;AACF,sBAAY,MAAM,KAAK,SAAS,eAAe,SAAS,OAAO,WAAW,SAAS,MAAM;AAAA,QAC3F,SAAS,OAAO;AACd,kBAAQ;AACR,gBAAM;AAAA,QACR;AACA,YAAI,CAAC,WAAW;AACd,kBAAQ;AACR;AAAA,QACF;AACA,uBAAe,WAAW,MAAM,QAAQ,GAAG,SAAS;AACpD,SAAAA,MAAA,aAAa,UAAb,gBAAAA,IAAA;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AAAA,EAEA,iBAAiB,UAAoB,MAAsB;AACzD,UAAM,MAAM,KAAK,SAAS,IAAI;AAE9B,QAAI,SAAS,SAAS,IAAI,MAAM;AAC9B,MAAAD,QAAO;AAAA,QACL,eAAe,SAAS,IAAI,SAAS,SAAS,IAAI,wBAAwB,IAAI,IAAI;AAAA,MACpF;AACA;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAqB,KAAyB,gBAA6C;AACzF,WAAO,IAAI,YAAY;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,sBACJ,UACA,aACA,mBACA;AACA,UAAM,YAAYA,QAAO,YAAY;AAAA,MACnC,SAAS,SAAS;AAAA,MAClB,OAAO,SAAS;AAAA,IAClB,CAAC;AAED,cAAU;AAAA,MACR,QAAQ,SAAS,IAAI,6BAA6B,SAAS,KAAK;AAAA,IAClE;AACA,UAAM,UAAU,MAAM,KAAK,SAAS;AAAA,MAClC,SAAS;AAAA,MACT;AAAA,MACA,SAAS;AAAA,IACX;AAEA,QAAI,CAAC,SAAS;AACZ,gBAAU,KAAK,uBAAuB,SAAS,IAAI,uCAAuC;AAC1F,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,kBAAmB,QAAO;AAG/B,QAAI;AACF,YAAM,kBAAkB,QAAQ;AAAA,IAClC,SAAS,eAAe;AACtB,gBAAU,MAAM,gDAAgD,SAAS,IAAI,KAAK;AAAA,QAChF,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,OAAgB,KAAoB,UAAoB,SAA2B;AAE/F,UAAM,oBAAoB,YAAY;AACpC,UAAI,IAAI,SAAS,aAAa;AAC5B,eAAO,KAAK,SAAS,gBAAgB;AAAA,UACnC,OAAO,SAAS;AAAA,UAChB,WAAW,eAAe,GAAG;AAAA,UAC7B,YAAY;AAAA,UACZ,UAAU,IAAI;AAAA,UACd,QAAQ,SAAS;AAAA,QACnB,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,OAAO,cAAoB;AAC7C,aAAO,KAAK,SAAS,gBAAgB;AAAA,QACnC,OAAO,SAAS;AAAA,QAChB;AAAA,QACA,YAAY;AAAA,QACZ,UAAU,IAAI,SAAS,cAAc,IAAI,WAAW,SAAS;AAAA,QAC7D,QAAQ,SAAS;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,IAAI,SAAS;AAChB,cAAQ,OAAO,MAAM,wBAAwB,SAAS,IAAI,KAAK,EAAC,MAAK,CAAC;AAEtE,aAAO,kBAAkB;AAAA,IAC3B;AAEA,YAAQ,OAAO,KAAK,wBAAwB,SAAS,IAAI,KAAK,EAAC,MAAK,CAAC;AACrE,UAAM,SAAS,MAAM,IAAI;AAAA,MACvB,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MACxD,SAAS;AAAA,MACT;AAAA,IACF;AAEA,QAAI,OAAO,WAAW,WAAW;AAC/B,aAAO,kBAAkB;AAAA,IAC3B;AAEA,QAAI,OAAO,WAAW,SAAS;AAC7B,aAAO,YAAY,eAAe,MAAM,CAAC;AAAA,IAC3C;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,SAOjB;AACD,UAAM,EAAC,WAAW,QAAQ,cAAc,QAAQ,KAAK,SAAQ,IAAI;AACjE,UAAM,UAAU,oBAAI,KAAK;AAEzB,QAAI,IAAI,sBAAsB,GAAG;AAC/B,YAAM,UAAU,MAAO,KAAK,KAAK,KAAK;AACtC,YAAM,oBAAoB,IAAI,qBAAqB;AACnD,YAAM,KAAK,gBAAgB,cAAc;AAAA,QACvC,OAAO,SAAS;AAAA,QAChB,aAAa,SAAS;AAAA,QACtB,SAAS,SAAS;AAAA,QAClB,MAAM,SAAS;AAAA,QACf,UAAU,SAAS;AAAA,QACnB,OAAO,SAAS;AAAA,QAChB,kBAAkB,SAAS;AAAA,QAC3B;AAAA,QACA;AAAA,QACA,UAAU,QAAQ,QAAQ,IAAI,UAAU,QAAQ;AAAA,QAChD,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,iBAAiB;AAAA,QAClD;AAAA,QACA;AAAA,QACA,QAAQ,SAAS;AAAA,QACjB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,sBAAsB,KAAoB,UAAoB,SAA2B;AAC7F,QAAI,IAAI,SAAS,aAAa;AAC5B,cAAQ,OAAO,MAAM,0CAA0C,SAAS,IAAI,GAAG;AAC/E,aAAO,KAAK,SAAS,gBAAgB;AAAA,QACnC,OAAO,SAAS;AAAA,QAChB,WAAW,eAAe,GAAG;AAAA,QAC7B,YAAY;AAAA,QACZ,UAAU,IAAI;AAAA,QACd,QAAQ,SAAS;AAAA,MACnB,CAAC;AAAA,IACH;AACA,QAAI,IAAI,SAAS,SAAS;AACxB,cAAQ,OAAO,MAAM,qCAAqC,SAAS,IAAI,GAAG;AAC1E,aAAO,KAAK,SAAS,eAAe,SAAS,OAAO,SAAS,MAAM;AAAA,IACrE;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WAAW,QAA0B,UAAoB,kBAA8B;AAC3F,UAAM,MAAM,KAAK,iBAAiB,UAAU,OAAO,IAAI;AACvD,QAAI,CAAC,IAAK;AAEV,QAAI,IAAI,SAAS,SAAS;AACxB,YAAM,oBAAoB,KAAK,qBAAqB,KAAK,OAAO,QAAQ;AACxE,UAAI,OAAO,sBAAsB,YAAY,SAAS,QAAQ,mBAAmB;AAC/E,cAAM,KAAK;AAAA,UACT;AAAA,UACA,OAAO;AAAA,UACP,OAAO;AAAA,QACT;AACA;AAAA,MACF;AAAA,IACF;AAGA,UAAM,oBAAoB,KAAK,qBAAqB,KAAK,QAAQ;AACjE,QAAI,sBAAsB,SAAS,UAAU;AAC3C,YAAM,gBAAgB,MAAM,KAAK,SAAS;AAAA,QACxC,SAAS;AAAA,QACT;AAAA,QACA,SAAS;AAAA,MACX;AACA,UAAI,CAAC,eAAe;AAClB,QAAAA,QAAO,KAAK,yBAAyB,SAAS,IAAI,uCAAuC;AACzF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU,gBAAgB,KAAK;AAEpD,UAAM,OAAO,gBAAgB,OAAO,SAAS,IAAI,IAAI,SAAS,WAAW,IAAI,OAAM,SAAQ;AACzF,UAAI;AACF,cAAM,YAAY,oBAAI,KAAK;AAC3B,YAAI,kBAAuC;AAC3C,YAAI;AACJ,YAAI;AAEJ,cAAM,cAAc,MAAM;AACxB,cAAI,oBAAoB,QAAS,QAAO;AAExC,4BAAkB;AAClB,kBAAQ,kBAAkB;AAE1B,kCAAwB,YAAY;AAClC,oBAAQ,OAAO,KAAK,QAAQ,SAAS,IAAI,YAAY;AAErD,gBAAI,IAAI,SAAS;AACf,mBAAK,QAAQ,QAAQ,IAAI,QAAQ,SAAS,QAAQ,OAAO,CAAC,EAAE,MAAM,WAAS;AACzE,wBAAQ,OAAO,MAAM,sCAAsC,SAAS,IAAI,KAAK;AAAA,kBAC3E;AAAA,gBACF,CAAC;AAAA,cACH,CAAC;AAAA,YACH;AAEA,gBAAI;AACF,oBAAM,KAAK,SAAS,qBAAqB,SAAS,OAAO,GAAG,SAAS,MAAM;AAAA,YAC7E,SAAS,OAAO;AACd,sBAAQ,OAAO,MAAM,0CAA0C,SAAS,IAAI,KAAK;AAAA,gBAC/E;AAAA,cACF,CAAC;AAAA,YACH,UAAE;AAGA,+BAAiB;AAAA,YACnB;AAEA,kBAAM,KAAK,cAAc;AAAA,cACvB;AAAA,cACA,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,cAAc;AAAA,cACd;AAAA,cACA;AAAA,YACF,CAAC;AAAA,UACH,GAAG,EAAE,MAAM,WAAS;AAClB,oBAAQ,OAAO,MAAM,kCAAkC,EAAC,MAAK,CAAC;AAAA,UAChE,CAAC;AAED,iBAAO;AAAA,QACT;AAEA,kBAAU,KAAK;AAAA,UACb;AAAA,UACA;AAAA,UACA,MAAM,KAAK,YAAY;AAAA,UACvB,MAAM,oBAAoB;AAAA,QAC5B;AAEA,cAAM,eAAe;AAAA,UACnB,gBAAgB;AAAA,UAChB,SAAS,SAAS;AAAA,UAClB,OAAO,SAAS;AAAA,UAChB,QAAQ,SAAS;AAAA,QACnB;AAEA,cAAM,yBAAyB,cAAc,YAAY;AACvD,cAAI;AAEF,oCAAwB;AAAA,cACtB,SAAS,SAAS;AAAA,cAClB,OAAO,SAAS;AAAA,cAChB,QAAQ,SAAS;AAAA,YACnB,CAAC;AACD,kBAAM,SAAS,MAAM,IAAI,QAAQ,SAAS,QAAQ,OAAO;AACzD,oBAAQ,kBAAkB;AAE1B,gBAAI,oBAAoB,SAAS;AAC/B,oBAAM;AACN,sBAAQ,OAAO;AAAA,gBACb,+CAA+C,SAAS,WAAW;AAAA,cACrE;AACA;AAAA,YACF;AAEA,kBAAM,eAAe,MAAM,KAAK,sBAAsB,KAAK,UAAU,OAAO;AAC5E,gBAAI,CAAC,cAAc;AACjB,oBAAM,YAAY;AAClB;AAAA,YACF;AAEA,iBAAK,KAAK,cAAc;AAAA,cACtB;AAAA,cACA,QAAQ;AAAA,cACR,QAAQ,UAAU;AAAA,cAClB,cAAc;AAAA,cACd;AAAA,cACA;AAAA,YACF,CAAC,EAAE,MAAM,WAAS;AAChB,sBAAQ,OAAO,MAAM,6CAA6C,EAAC,MAAK,CAAC;AAAA,YAC3E,CAAC;AAAA,UACH,SAAS,OAAO;AACd,oBAAQ,kBAAkB;AAE1B,gBAAI,oBAAoB,SAAS;AAC/B,oBAAM;AACN,sBAAQ,OAAO;AAAA,gBACb,6CAA6C,SAAS,WAAW;AAAA,gBACjE,EAAC,MAAK;AAAA,cACR;AACA;AAAA,YACF;AAEA,kBAAM,eAAe,MAAM,KAAK,QAAQ,OAAO,KAAK,UAAU,OAAO;AACrE,gBAAI,CAAC,cAAc;AACjB,oBAAM,YAAY;AAClB;AAAA,YACF;AAEA,iBAAK,KAAK,cAAc;AAAA,cACtB;AAAA,cACA,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,cAAe,MAAgB;AAAA,cAC/B;AAAA,cACA;AAAA,YACF,CAAC,EAAE,MAAM,eAAa;AACpB,sBAAQ,OAAO,MAAM,yCAAyC,EAAC,OAAO,UAAS,CAAC;AAAA,YAClF,CAAC;AAAA,UACH;AAAA,QACF,CAAC;AAAA,MACH,SAAS,OAAO;AACd,aAAK,UAAU;AAAA,UACb,MAAM,eAAe;AAAA,UACrB,SAAU,MAAgB;AAAA,QAC5B,CAAC;AACD,cAAM;AAAA,MACR,UAAE;AACA,aAAK,IAAI;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH;AACF;AA5YOH,SAAA;AAEL,kBAAAA,QAAA,GAAiB,YADjBD,gBADW;AAKX,kBAAAC,QAAA,GAAiB,mBADjB,sBAJW;AAAA,WAAN,kBAAAA,QAAA,eADP,sBACa;AAAN,kBAAAA,QAAA,GAAM;;;ADrBb,mBAAAK,gBAAA,2BAAAC;AA2BA,6BAACC,SAAQ,IAEPF,iBAAA,CAACG,QAAO,MAAM,QAAQ,IAGtB,iBAACA,QAAO,MAAM,QAAQ;AAJjB,IAAM,gBAAN,MAAoB;AAAA,EAApB;AAEL,wBAAQ,YAAR,kBAAAF,QAAA,6BAAAA,QAAA;AAGA,wBAAQ,YAAR,kBAAAA,QAAA,8BAAAA,QAAA;AAAA;AAAA,EAEA,YAAY,MAAsB;AAChC,WAAO,OAAO,KAAK,IAAI;AAAA,EACzB;AAAA,EAEA,QAAQ,MAA+C;AACrD,WAAO,OAAO,KAAK,IAAI,EAAE,IAAI,UAAQ;AACnC,aAAO;AAAA,QACL;AAAA,QACA,GAAG,KAAK,IAAI;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,qBACE,QACA,iBACA,UACA;AACA,WAAO,SAAS,OAAO,aAAW;AAChC,YAAM,oBAAoB,gBAAgB,kBAAkB,IAAI,OAAO,KAAK;AAC5E,YAAM,MAAM,OAAO,KAAK,OAAO;AAC/B,YAAM,wBACJ,IAAI,SAAS,UACR,IAAI,kCAAkC,OAAO,oBAC9C,OAAO;AAEb,aAAO,oBAAoB;AAAA,IAC7B,CAAC;AAAA,EACH;AAAA,EAEA,oBAAoB,iBAA0C,SAAiB;AAC7E,UAAM,oBAAoB,gBAAgB,kBAAkB,IAAI,OAAO,KAAK;AAC5E,oBAAgB,kBAAkB,IAAI,SAAS,oBAAoB,CAAC;AAAA,EACtE;AAAA,EAEA,oBAAoB,iBAA0C,SAAiB;AAC7E,UAAM,oBAAoB,gBAAgB,kBAAkB,IAAI,OAAO,KAAK;AAC5E,QAAI,qBAAqB,GAAG;AAC1B,sBAAgB,kBAAkB,OAAO,OAAO;AAChD;AAAA,IACF;AAEA,oBAAgB,kBAAkB,IAAI,SAAS,oBAAoB,CAAC;AAAA,EACtE;AAAA,EAEA,yBACE,iBACA,WACA,YACA;AACA,QAAI,UAAU,WAAW,UAAW;AAEpC,cAAU,SAAS;AACnB,oBAAgB,iBAAiB,OAAO,UAAU,IAAI,WAAW;AACjE,SAAK,oBAAoB,iBAAiB,UAAU,IAAI,IAAI;AAC5D,cAAU,gBAAgB;AAE1B,QAAI,eAAe,SAAS;AAC1B,sBAAgB,gBAAgB,IAAI,UAAU,IAAI,aAAa,SAAS;AAAA,IAC1E;AAAA,EACF;AAAA,EAEA,eACE,QACA,iBACA,UACA;AACA,QAAI;AACJ,UAAM,kBAAkB,IAAI,QAAc,aAAW;AACnD,wBAAkB;AAAA,IACpB,CAAC;AAED,UAAM,YAA8B;AAAA,MAClC,KAAK;AAAA,MACL,SAAS,QAAQ,QAAQ;AAAA,MACzB;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IACV;AAEA,SAAK,oBAAoB,iBAAiB,SAAS,IAAI;AACvD,oBAAgB,iBAAiB,IAAI,SAAS,aAAa,SAAS;AAEpE,IAAAG,QAAO,MAAM,2BAA2B,SAAS,WAAW,KAAK,QAAQ;AAEzE,UAAM,mBAAmB,KAAK,SAAS,WAAW,QAAQ,UAAU,MAAM;AACxE,WAAK,yBAAyB,iBAAiB,WAAW,OAAO;AAAA,IACnE,CAAC;AACD,cAAU,UAAU;AAEpB,SAAK,iBACF,MAAM,WAAS;AACd,MAAAA,QAAO,MAAM,kCAAkC,SAAS,IAAI,KAAK,EAAC,MAAK,CAAC;AAAA,IAC1E,CAAC,EACA,QAAQ,MAAM;AACb,UAAI,UAAU,WAAW,WAAW;AAClC,aAAK,yBAAyB,iBAAiB,WAAW,UAAU;AAAA,MACtE,WAAW,UAAU,WAAW,SAAS;AACvC,wBAAgB,gBAAgB,OAAO,SAAS,WAAW;AAAA,MAC7D;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEA,MAAM,kBAAkB,QAA4B,iBAA0C;AAC5F,UAAM,QAAQ,KAAK,CAAC,MAAM,OAAO,YAAY,GAAG,gBAAgB,UAAU,CAAC;AAAA,EAC7E;AAAA,EAEA,MAAM,sBAAsB,iBAA0C;AACpE,UAAM,mBAAmB,MAAM;AAAA,MAC7B,gBAAgB,iBAAiB,OAAO;AAAA,MACxC,eAAa,UAAU;AAAA,IACzB;AAEA,QAAI,iBAAiB,WAAW,EAAG;AACnC,UAAM,QAAQ,KAAK,CAAC,GAAG,kBAAkB,gBAAgB,UAAU,CAAC;AAAA,EACtE;AAAA,EAEA,MAAM,iBAAiB,QAA4B,iBAA0C;AAC3F,UAAM,WAAW,KAAK,YAAY,OAAO,IAAI;AAC7C,UAAM,gBAAkC;AAAA,MACtC,MAAM,OAAO;AAAA,MACb,UAAU,OAAO;AAAA,MACjB,4BAA4B,OAAO;AAAA,MACnC,mBAAmB,OAAO;AAAA,IAC5B;AAEA,IAAAA,QAAO,MAAM,oCAAoC,SAAS,KAAK,IAAI,CAAC,MAAM;AAE1E,WAAO,gBAAgB,SAAS;AAC9B,UAAI,UAAU;AACd,UAAI,wBAAwB;AAE5B,UAAI;AACF,eAAO,gBAAgB,iBAAiB,OAAO,OAAO,cAAc;AAClE,gBAAM,oBAAoB,KAAK,qBAAqB,QAAQ,iBAAiB,QAAQ;AAErF,cAAI,kBAAkB,WAAW,GAAG;AAClC,oCAAwB,gBAAgB,iBAAiB,OAAO;AAChE;AAAA,UACF;AAEA,gBAAM,WAAW,MAAM,KAAK,SAAS;AAAA,YACnC;AAAA,YACA,OAAO;AAAA,UACT;AAEA,cAAI,CAAC,UAAU;AACb,YAAAA,QAAO,MAAM,eAAe;AAC5B,sBAAU;AACV;AAAA,UACF;AAGA,eAAK,eAAe,eAAe,iBAAiB,QAAQ;AAC5D,cAAI,CAAC,gBAAgB,QAAS;AAAA,QAChC;AAAA,MACF,SAAS,OAAO;AACd,QAAAA,QAAO,MAAM,2BAA2B,EAAC,MAAK,CAAC;AAC/C,kBAAU;AAAA,MACZ;AAEA,UAAI,CAAC,gBAAgB,QAAS;AAE9B,YAAM,oBACJ,gBAAgB,iBAAiB,QAAQ,OAAO,gBAChD,gBAAgB,iBAAiB,OAAO;AAE1C,UAAI,qBAAqB,uBAAuB;AAC9C,cAAM,KAAK,sBAAsB,eAAe;AAAA,MAClD,WAAW,WAAW,gBAAgB,iBAAiB,SAAS,GAAG;AACjE,cAAM,KAAK,kBAAkB,QAAQ,eAAe;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,gCAAgC,QAAqD;AACnF,QAAI;AACJ,UAAM,aAAa,IAAI,QAAc,aAAW;AAC9C,mBAAa;AAAA,IACf,CAAC;AAED,UAAM,kBAA2C;AAAA,MAC/C,SAAS;AAAA,MACT,cAAc,OAAO;AAAA,MACrB,kBAAkB,oBAAI,IAAI;AAAA,MAC1B,iBAAiB,oBAAI,IAAI;AAAA,MACzB,mBAAmB,oBAAI,IAAI;AAAA,MAC3B,kBAAkB,QAAQ,QAAQ;AAAA,MAClC;AAAA,MACA;AAAA,MACA,IAAI,oBAAoB;AACtB,eAAO,KAAK,iBAAiB;AAAA,MAC/B;AAAA,MACA,MAAM,YAAY;AAChB,YAAI,gBAAgB,YAAa,QAAO,gBAAgB;AAExD,wBAAgB,eAAe,YAAY;AACzC,UAAAA,QAAO,KAAK,2BAA2B;AACvC,0BAAgB,UAAU;AAC1B,0BAAgB,WAAW;AAE3B,gBAAM,gBAAgB;AAEtB,gBAAM,iBAAiB,MAAM;AAAA,YAC3B,gBAAgB,iBAAiB,OAAO;AAAA,YACxC,eAAa,UAAU;AAAA,UACzB;AACA,gBAAM,QAAQ,IAAI,cAAc;AAAA,QAClC,GAAG;AAEH,eAAO,gBAAgB;AAAA,MACzB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,QAA4B;AAC9C,UAAM,OAAO,KAAK,QAAQ,OAAO,IAAI;AAErC,UAAM,QAAQ;AAAA,MACZ,KACG,OAAO,SAAO,IAAI,SAAS,WAAW,EACtC,IAAI,OAAM,QAAO;AAChB,QAAAA,QAAO,MAAM,6BAA6B,IAAI,IAAI,MAAM;AACxD,cAAM,KAAK,SAAS,gBAAgB,GAAG;AAAA,MACzC,CAAC;AAAA,IACL;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,QAA4B,iBAA0C;AACvF,IAAAA,QAAO,MAAM,qDAAqD;AAClE,SAAK,KAAK,SACP,+BAA+B,OAAO,0BAA0B,EAChE,MAAM,WAASA,QAAO,MAAM,4CAA4C,EAAC,MAAK,CAAC,CAAC;AAEnF,IAAAA,QAAO,MAAM,wCAAwC;AACrD,UAAM,KAAK,cAAc,MAAM;AAE/B,IAAAA,QAAO,KAAK,2CAA2C,OAAO,YAAY,EAAE;AAC5E,UAAM,KAAK,iBAAiB,QAAQ,eAAe;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,YAAiD;AAC5D,UAAM,6BACJ,WAAW,+BAA+B,SACtC,yCACA,WAAW;AAEjB,QACE,+BAA+B,SAC9B,CAAC,OAAO,SAAS,0BAA0B,KAAK,6BAA6B,IAC9E;AACA,YAAM,IAAI,MAAM,qEAAqE;AAAA,IACvF;AAEA,UAAM,SAA6B;AAAA,MACjC,cAAc;AAAA,MACd,cAAc;AAAA,MACd,iBAAiB,KAAK;AAAA,MACtB,GAAG;AAAA,MACH;AAAA,IACF;AAEA,kBAAc,OAAO,IAAI;AAEzB,UAAM,kBAAkB,KAAK,gCAAgC,MAAM;AACnE,IAAAA,QAAO,MAAM,0BAA0B,MAAM;AAE7C,oBAAgB,mBAAmB,KAAK,aAAa,QAAQ,eAAe,EAAE,MAAM,WAAS;AAC3F,sBAAgB,UAAU;AAC1B,MAAAA,QAAO,MAAM,oDAAoD,EAAC,MAAK,CAAC;AAAA,IAC1E,CAAC;AAED,WAAO;AAAA,EACT;AACF;AA/ROH,SAAA;AAEL,kBAAAA,QAAA,GAAQ,YADRD,gBADW;AAKX,kBAAAC,QAAA,GAAQ,YADR,eAJW;AAAA,gBAAN,kBAAAA,QAAA,oBADP,2BACa;AAAN,kBAAAA,QAAA,GAAM;AAiSb,SAAS,cAAc,MAAsB;AAC3C,aAAW,QAAQ,OAAO,KAAK,IAAI,GAAG;AACpC,SAAK,IAAI,EAAE,UAAU;AAAA,EACvB;AACF;;;ASjUA,SAAQ,aAAa,WAAAI,gBAAc;;;ACAnC,SAAQ,wBAA6C;AACrD,SAAQ,wBAAAC,6BAA2B;AACnC,OAAO,WAAW;AAYX,SAAS,eACd,SACmC;AACnC,QAAM,gBAAmD;AAAA,IACvD,GAAG;AAAA,IACH,MAAM;AAAA,IACN,UAAU;AAAA,IACV,cAAc;AAAA,EAChB;AAEA,gBAAc,WAAW,OACvB,oBACG;AACH,QAAI,CAAC,cAAc,SAAS;AAC1B,YAAM,IAAI,MAAM,iDAAiD;AAAA,IACnE;AAEA,UAAM,SAAS,cAAc,SACzB,MAAM,iBAAiB,cAAc,QAAQ,gBAAgB,MAAM,IACnE,gBAAgB;AAEpB,WAAO,MAAM,YAAY;AAAA,MACvB,GAAG;AAAA,MACH,MAAM,cAAc;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,gBAAc,eAAe,OAC3B,SACgC;AAChC,QAAI,CAAC,cAAc,SAAS;AAC1B,YAAM,IAAI,MAAM,iDAAiD;AAAA,IACnE;AAGA,UAAM,gBAAgB,MAAM,QAAQ;AAAA,MAClC,KAAK,IAAI,OAAM,oBAAmB;AAChC,cAAM,SAAS,cAAc,SACzB,MAAM,iBAAiB,cAAc,QAAQ,gBAAgB,MAAM,IACnE,gBAAgB;AAEpB,eAAO;AAAA,UACL,GAAG;AAAA,UACH,MAAM,cAAc;AAAA,UACpB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO,MAAM,aAAa,aAAa;AAAA,EACzC;AAEA,SAAO;AACT;AAEO,SAAS,mBAAmB,SAA4D;AAC7F,QAAM,mBAAmB;AAAA,IACvB,GAAG;AAAA,EACL;AAEA,SAAO,iBAAiB;AAExB,MAAI,UAAU,oBAAoB,iBAAiB,QAAQ,CAAC,iBAAiB,UAAU;AACrF,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AAEA,MAAI,UAAU,oBAAoB,iBAAiB,MAAM;AACvD,IAAAC,sBAAqB,MAAM,iBAAiB,MAAM,EAAC,IAAI,iBAAiB,SAAQ,CAAC,EAAE,KAAK;AAAA,EAC1F;AAEA,QAAM,WACJ,cAAc,mBACV,OAAO,iBAAiB,aAAa,WACnC,MAAM,iBAAiB,QAAQ,IAC/B,iBAAiB,WACnB;AAEN,QAAM,gBAAwC;AAAA,IAC5C,GAAG;AAAA,IACH,UAAU,iBAAiB,YAAY;AAAA,IACvC,MAAM;AAAA,IACN;AAAA,EACF;AAEA,SAAO;AACT;AAKO,IAAM,YAAY,CACvB,YACkB;AAClB,SAAO,QAAQ,SAAS,UACpB,eAAe,OAAc,IAC7B,mBAAmB,OAAc;AACvC;;;AD1GA,IAAM,kBAAkB,oBAAI,QAAqC;AACjE,IAAM,eAAe,oBAAI,IAA8B;AACvD,IAAM,oBAAoB,oBAAI,IAAsD;AACpF,IAAI,oBAA4D,CAAC;AAE1D,SAAS,OAAO;AACrB,SAAO,CAAC,QAAa,YAAwC;AAC3D,IAAAC,SAAQ,EAAE,QAAQ,OAAO;AACzB,oBAAgB,IAAI,QAAQ,EAAC,cAAc,OAAM,CAAC;AAElD,QAAI,OAAO,KAAK,iBAAiB,EAAE,SAAS,GAAG;AAC7C,wBAAkB,IAAI,QAAQ,iBAAiB;AAC/C,0BAAoB,CAAC;AAAA,IACvB;AAAA,EACF;AACF;AASO,SAAS,aAAa,UAAU,CAAC,GAAG;AACzC,SAAO,CAAC,QAAa,YAAsE;AACzF,UAAM,cAAc,OAAO,QAAQ,IAAI;AAEvC,QAAI,QAAQ,SAAS,UAAU;AAC7B,wBAAkB,WAAW,IAAI,CAAC,aAChC,UAAU;AAAA,QACR,GAAG;AAAA,QACH,MAAM;AAAA,QACN,SAAS,SAAS,WAAW,EAAE,KAAK,QAAQ;AAAA,MAC9C,CAAC;AAAA,IACL;AAEA,QAAI,QAAQ,SAAS,SAAS;AAC5B,wBAAkB,WAAW,IAAI,CAAC,aAAkB,SAAS,WAAW;AAAA,IAC1E;AAEA,WAAO;AAAA,EACT;AACF;AASO,SAAS,SAAS,UAAU,CAAC,GAAG;AACrC,SAAO,CAAC,QAAa,YAAsE;AACzF,UAAM,cAAc,OAAO,QAAQ,IAAI;AAEvC,QAAI,QAAQ,SAAS,UAAU;AAC7B,wBAAkB,WAAW,IAAI,CAAC,aAChC,eAAe;AAAA,QACb,GAAG;AAAA,QACH,SAAS,SAAS,WAAW,EAAE,KAAK,QAAQ;AAAA,MAC9C,CAAC;AAAA,IACL;AAEA,QAAI,QAAQ,SAAS,SAAS;AAC5B,wBAAkB,WAAW,IAAI,CAAC,aAAkB,SAAS,WAAW;AAAA,IAC1E;AAEA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,uBAAuB,UAAe;AAC7C,MAAI,aAAa,IAAI,QAAQ,EAAG;AAChC,QAAM,UAAU,kBAAkB,IAAI,SAAS,WAAW,KAAK,CAAC;AAChE,QAAM,OAA4B,CAAC;AACnC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,SAAK,GAAG,IAAI,MAAM,QAAQ;AAAA,EAC5B;AACA,eAAa,IAAI,UAAU,IAAI;AACjC;AAEO,SAAS,eAAe,QAE7B;AACA,QAAM,WAAW,YAAY,MAAM;AAEnC,MAAI,CAAC,gBAAgB,IAAI,SAAS,WAAW,GAAG;AAC9C,UAAM,IAAI,MAAM,8DAA8D;AAAA,EAChF;AAEA,QAAM,mBAAmB,gBAAgB,IAAI,SAAS,WAAW;AACjE,MAAI,iBAAiB,iBAAiB,QAAQ;AAC5C,UAAM,IAAI,MAAM,8DAA8D;AAAA,EAChF;AAEA,yBAAuB,QAAQ;AAE/B,QAAM,UAAU,aAAa,IAAI,QAAQ,KAAK,CAAC;AAE/C,SAAO;AACT;;;Af7FA,IAAM,gBAAgBC,aAAY,aAAa;AAC/C,IAAM,gBAAgBA,aAAY,aAAa;AAC/C,IAAM,kBAAkBA,aAAY,eAAe;AACnD,IAAM,WAAWA,aAAY,QAAQ;AAErC,IAAM,eAAe,CAAC,WAA+B;AACnD,SAAO,cAAc,aAAa,MAAM;AAC1C;AAKA,IAAM,cAAc,CAClB,YACG;AACH,SAAO,cAAc,YAAY,OAAO;AAC1C;AAMA,IAAM,eAAe,CACnB,SACgC;AAChC,SAAO,cAAc,aAAa,IAAI;AACxC;","names":["getInstance","logger","_init","logger","logger","Inject","Service","logger","Inject","Service","MongoCollection","Repository","schemaWithName","_init","Repository","MongoCollection","_jobsRepo_dec","_init","Service","Inject","logger","_a","_jobsRepo_dec","_init","Service","Inject","logger","Service","CronExpressionParser","CronExpressionParser","Service","getInstance"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/services/EventsService.ts","../src/repos/JobsRepo.ts","../src/types/JobRecord.ts","../src/types/StartConfig.ts","../src/services/getNextRunDate.ts","../src/services/WorkerService.ts","../src/services/Executor.ts","../src/repos/JobsHistoryRepo.ts","../../../node_modules/.bun/rambdax@11.3.1/node_modules/rambdax/src/_internals/isInteger.js","../../../node_modules/.bun/rambdax@11.3.1/node_modules/rambdax/src/_internals/createPath.js","../../../node_modules/.bun/rambdax@11.3.1/node_modules/rambdax/src/_internals/compare.js","../../../node_modules/.bun/rambdax@11.3.1/node_modules/rambdax/src/_internals/includes.js","../../../node_modules/.bun/rambdax@11.3.1/node_modules/rambdax/src/omit.js","../src/types/HistoryRecord.ts","../src/service/index.ts","../src/defineJob/index.ts"],"sourcesContent":["import {getInstance} from '@orion-js/services'\nimport {EventsService} from './services/EventsService'\nimport {WorkerService} from './services/WorkerService'\nimport {StartWorkersConfig} from './types/StartConfig'\nimport {ScheduleJobOptions, ScheduleJobsOptions, ScheduleJobsResult} from './types/Events'\nimport {JobsHistoryRepo} from './repos/JobsHistoryRepo'\nimport {JobsRepo} from './repos/JobsRepo'\nimport {SchemaInAnyOrionForm} from '@orion-js/schema'\n\nexport * from './types'\nexport * from './service'\nexport * from './defineJob'\n\nconst workerService = getInstance(WorkerService)\nconst eventsService = getInstance(EventsService)\nconst jobsHistoryRepo = getInstance(JobsHistoryRepo)\nconst jobsRepo = getInstance(JobsRepo)\n\nconst startWorkers = (config: StartWorkersConfig) => {\n return workerService.startWorkers(config)\n}\n\n/**\n * @deprecated Use the event job definition.schedule method instead.\n */\nconst scheduleJob = <TParamsSchema extends SchemaInAnyOrionForm = any>(\n options: ScheduleJobOptions<TParamsSchema>,\n) => {\n return eventsService.scheduleJob(options)\n}\n\n/**\n * Schedule multiple jobs at once for better performance.\n * @deprecated Use the event job definition.scheduleJobs method instead.\n */\nconst scheduleJobs = <TParamsSchema extends SchemaInAnyOrionForm = any>(\n jobs: ScheduleJobsOptions<TParamsSchema>,\n): Promise<ScheduleJobsResult> => {\n return eventsService.scheduleJobs(jobs)\n}\n\nexport {startWorkers, scheduleJob, scheduleJobs, jobsHistoryRepo, jobsRepo}\n","import {logger} from '@orion-js/logger'\nimport {Inject, Service} from '@orion-js/services'\nimport {JobsRepo} from '../repos/JobsRepo'\nimport {ScheduleJobOptions, ScheduleJobsOptions, ScheduleJobsResult} from '../types/Events'\nimport {getNextRunDate} from './getNextRunDate'\n\n@Service()\nexport class EventsService {\n @Inject(() => JobsRepo)\n private jobsRepo: JobsRepo\n\n async scheduleJob(options: ScheduleJobOptions) {\n logger.debug('Scheduling job...', options)\n\n await this.jobsRepo.scheduleJob({\n name: options.name,\n priority: options.priority || 100,\n nextRunAt: getNextRunDate(options),\n params: options.params || null,\n uniqueIdentifier: options.uniqueIdentifier,\n })\n }\n\n async scheduleJobs(jobs: ScheduleJobsOptions): Promise<ScheduleJobsResult> {\n logger.debug(`Scheduling ${jobs.length} jobs...`)\n\n const jobRecords = jobs.map(options => ({\n name: options.name,\n priority: options.priority || 100,\n nextRunAt: getNextRunDate(options),\n params: options.params || null,\n uniqueIdentifier: options.uniqueIdentifier,\n }))\n\n return await this.jobsRepo.scheduleJobs(jobRecords)\n }\n}\n","import {generateId} from '@orion-js/helpers'\nimport {logger} from '@orion-js/logger'\nimport {Collection, MongoCollection, MongoDB, Repository} from '@orion-js/mongodb'\nimport {ScheduleJobRecordOptions, ScheduleJobsResult} from '../types/Events'\nimport {JobRecord, JobRecordSchema} from '../types/JobRecord'\nimport {JobDefinitionWithName, RecurrentJobDefinition} from '../types/JobsDefinition'\nimport {DEFAULT_MAX_TRIES_REACHED_RETENTION_MS} from '../types/StartConfig'\nimport {JobToRun} from '../types/Worker'\n\nexport type JobAcquisitionHint = 'byJobName' | 'globalPriority'\n\nexport const JOB_ACQUISITION_HINTS = {\n byJobName: {\n jobName: 1,\n priority: -1,\n nextRunAt: 1,\n },\n globalPriority: {\n priority: -1,\n nextRunAt: 1,\n },\n} as const satisfies Record<JobAcquisitionHint, MongoDB.IndexSpecification>\n\nexport const INITIAL_JOB_ACQUISITION_HINT = 'byJobName' as const satisfies JobAcquisitionHint\nexport const CANDIDATE_JOB_ACQUISITION_HINT = 'globalPriority' as const satisfies JobAcquisitionHint\n\nconst JOB_ACQUISITION_SORT: MongoDB.Sort = {\n priority: -1,\n nextRunAt: 1,\n}\n\nfunction getJobAcquisitionSelector(jobNames: string[], now: Date): MongoDB.Filter<JobRecord> {\n return {\n jobName: {$in: jobNames},\n nextRunAt: {$lte: now},\n $and: [\n {$or: [{lockedUntil: {$exists: false}}, {lockedUntil: {$lte: now}}]},\n // Exclude event jobs that have reached max tries. Recurrent jobs keep running even\n // if old records still have this status from previous versions.\n {$or: [{type: {$ne: 'event'}}, {status: {$ne: 'maxTriesReached'}}]},\n ],\n }\n}\n\n@Repository()\nexport class JobsRepo {\n @MongoCollection({\n idGeneration: 'uuid',\n name: 'orionjs.jobs_dogs_records',\n schema: JobRecordSchema,\n indexes: [\n {\n keys: JOB_ACQUISITION_HINTS.byJobName,\n },\n {\n keys: JOB_ACQUISITION_HINTS.globalPriority,\n },\n {\n keys: {\n jobName: 1,\n },\n options: {\n unique: true,\n partialFilterExpression: {type: 'recurrent'},\n },\n },\n {\n keys: {\n uniqueIdentifier: 1,\n },\n options: {\n unique: true,\n sparse: true,\n },\n },\n {\n keys: {\n expiresAt: 1,\n },\n name: 'jobs_dogs_records_expires_at_ttl',\n expireAfterSeconds: 0,\n },\n ],\n })\n jobs: Collection<JobRecord>\n\n async getJobAndLock(\n jobNames: string[],\n lockTime: number,\n hint: JobAcquisitionHint = INITIAL_JOB_ACQUISITION_HINT,\n ): Promise<JobToRun> {\n const executionId = generateId()\n const now = new Date()\n const lockedUntil = new Date(now.getTime() + lockTime)\n\n const job = await this.jobs.findOneAndUpdate(\n getJobAcquisitionSelector(jobNames, now),\n {\n $set: {lockId: executionId, lockedUntil, lastRunAt: now},\n $inc: {tries: 1},\n },\n {\n mongoOptions: {\n hint: JOB_ACQUISITION_HINTS[hint],\n sort: JOB_ACQUISITION_SORT,\n returnDocument: 'before',\n },\n },\n )\n\n if (!job) return\n\n const tries = (job.tries || 0) + 1\n const wasStale = Boolean(job.lockedUntil)\n\n if (wasStale) {\n logger.info(`Running job \"${job.jobName}\" that was staled`)\n }\n\n return {\n jobId: job._id,\n executionId,\n lockId: executionId,\n name: job.jobName,\n params: job.params,\n type: job.type,\n tries,\n lockTime,\n priority: job.priority,\n uniqueIdentifier: job.uniqueIdentifier,\n wasStale,\n }\n }\n\n async getJobAcquisitionExecutionTime(\n jobNames: string[],\n hint: JobAcquisitionHint,\n ): Promise<number> {\n const explain = await this.jobs\n .find(getJobAcquisitionSelector(jobNames, new Date()), {\n hint: JOB_ACQUISITION_HINTS[hint],\n maxTimeMS: 1000,\n readPreference: 'primary',\n })\n .sort(JOB_ACQUISITION_SORT)\n .limit(1)\n .explain('executionStats')\n\n const executionTimeMillis = explain.executionStats?.executionTimeMillis\n if (typeof executionTimeMillis !== 'number' || !Number.isFinite(executionTimeMillis)) {\n throw new Error(`Explain for acquisition hint \"${hint}\" returned no execution time`)\n }\n\n return executionTimeMillis\n }\n\n async setJobRecordPriority(jobId: string, priority: number, lockId?: string) {\n const result = await this.jobs.updateOne(lockId ? {_id: jobId, lockId} : jobId, {\n $set: {priority},\n })\n return result.matchedCount > 0\n }\n\n async scheduleNextRun(options: {\n jobId: string\n nextRunAt: Date\n resetTries: boolean\n priority: number\n lockId?: string\n }) {\n const updator: MongoDB.UpdateFilter<JobRecord> = {\n $set: {\n nextRunAt: options.nextRunAt,\n priority: options.priority,\n ...(options.resetTries ? {tries: 0} : {}),\n },\n $unset: {lockId: '', lockedUntil: ''},\n }\n\n const result = await this.jobs.updateOne(\n options.lockId ? {_id: options.jobId, lockId: options.lockId} : options.jobId,\n updator,\n )\n return result.matchedCount > 0\n }\n\n async deleteEventJob(jobId: string, lockId?: string) {\n const result = await this.jobs.deleteOne({\n _id: jobId,\n type: 'event',\n ...(lockId ? {lockId} : {}),\n })\n return result.deletedCount > 0\n }\n\n /**\n * Marks an event job as having reached its maximum tries limit.\n * The job won't be picked up for execution and MongoDB will delete it after\n * the configured retention period.\n */\n async markJobAsMaxTriesReached(\n jobId: string,\n retentionMs: number | null = DEFAULT_MAX_TRIES_REACHED_RETENTION_MS,\n lockId?: string,\n ) {\n const maxTriesReachedAt = new Date()\n const result = await this.jobs.updateOne(\n {_id: jobId, type: 'event', ...(lockId ? {lockId} : {})},\n {\n $set: {\n status: 'maxTriesReached',\n maxTriesReachedAt,\n ...(retentionMs === null\n ? {}\n : {expiresAt: new Date(maxTriesReachedAt.getTime() + retentionMs)}),\n },\n $unset: {\n lockId: '',\n lockedUntil: '',\n ...(retentionMs === null ? {expiresAt: ''} : {}),\n },\n },\n )\n return result.matchedCount > 0\n }\n\n /**\n * Applies the current retention configuration to existing maxTriesReached\n * event jobs. The collection definition ensures the TTL index. Legacy records\n * use lastRunAt as their retention anchor when available.\n */\n async ensureMaxTriesReachedRetention(retentionMs: number | null) {\n const selector = {\n type: 'event' as const,\n status: 'maxTriesReached' as const,\n }\n\n if (retentionMs === null) {\n await this.jobs.updateMany(selector, {$unset: {expiresAt: ''}})\n return\n }\n\n const now = new Date()\n const retentionAnchor = {\n $ifNull: ['$maxTriesReachedAt', {$ifNull: ['$lastRunAt', now]}],\n }\n\n await this.jobs.rawCollection.updateMany(selector, [\n {\n $set: {\n maxTriesReachedAt: retentionAnchor,\n expiresAt: {$add: [retentionAnchor, retentionMs]},\n },\n },\n ])\n }\n\n async extendLockTime(jobId: string, extraTime: number, lockId?: string) {\n return this.updateLockTime(jobId, extraTime, lockId)\n }\n\n /**\n * Updates the lock time for a job to the specified duration from now.\n * Can be used to both extend or shorten the lock time.\n */\n async updateLockTime(jobId: string, lockDuration: number, lockId?: string) {\n const lockedUntil = new Date(Date.now() + lockDuration)\n const result = await this.jobs.updateOne(\n {_id: jobId, ...(lockId ? {lockId} : {})},\n {\n $set: {lockedUntil},\n },\n )\n return result.matchedCount > 0\n }\n\n async unlockAllJobs(): Promise<number> {\n const result = await this.jobs.updateMany(\n {\n lockedUntil: {$exists: true},\n },\n {\n $unset: {lockId: '', lockedUntil: ''},\n },\n )\n\n return result.modifiedCount\n }\n\n async ensureJobRecord(job: JobDefinitionWithName) {\n const result = await this.jobs.upsert(\n {\n jobName: job.name,\n },\n {\n $set: {\n type: job.type,\n priority: (job as RecurrentJobDefinition).priority,\n },\n $unset: {\n status: '',\n },\n $setOnInsert: {\n nextRunAt: new Date(),\n },\n },\n )\n\n if (result.upsertedId) {\n logger.debug(`Created job record for \"${job.name}\"`)\n } else {\n logger.debug(`Record for job \"${job.name}\" already exists`)\n }\n }\n\n async scheduleJob(options: ScheduleJobRecordOptions) {\n try {\n await this.jobs.insertOne({\n jobName: options.name,\n uniqueIdentifier: options.uniqueIdentifier,\n params: options.params,\n nextRunAt: options.nextRunAt,\n priority: options.priority,\n type: 'event',\n })\n } catch (error) {\n if (\n error.isValidationError &&\n Object.values(error.validationErrors).includes('notUnique') &&\n options.uniqueIdentifier\n ) {\n logger.info(\n `Job \"${options.name}\" with identifier \"${options.uniqueIdentifier}\" already exists`,\n )\n } else {\n throw error\n }\n }\n }\n\n async scheduleJobs(jobs: ScheduleJobRecordOptions[]): Promise<ScheduleJobsResult> {\n if (jobs.length === 0) {\n return {scheduledCount: 0, skippedCount: 0, errors: []}\n }\n\n // Process each job individually to handle errors properly\n let scheduledCount = 0\n let skippedCount = 0\n const errors: Array<{index: number; error: Error; job: ScheduleJobRecordOptions}> = []\n\n for (let i = 0; i < jobs.length; i++) {\n const job = jobs[i]\n try {\n // Insert directly to get better error handling than the single scheduleJob method\n await this.jobs.insertOne({\n jobName: job.name,\n uniqueIdentifier: job.uniqueIdentifier,\n params: job.params,\n nextRunAt: job.nextRunAt,\n priority: job.priority,\n type: 'event',\n })\n scheduledCount++\n } catch (error) {\n // Check if it's a validation error with uniqueIdentifier constraint\n if (\n error.isValidationError &&\n Object.values(error.validationErrors).includes('notUnique') &&\n job.uniqueIdentifier\n ) {\n logger.info(`Job \"${job.name}\" with identifier \"${job.uniqueIdentifier}\" already exists`)\n skippedCount++\n } else {\n errors.push({\n index: i,\n error: error instanceof Error ? error : new Error(String(error)),\n job,\n })\n }\n }\n }\n\n logger.debug(\n `Scheduled ${scheduledCount} jobs successfully, skipped ${skippedCount}, errors: ${errors.length}`,\n )\n\n return {\n scheduledCount,\n skippedCount,\n errors,\n }\n }\n}\n","import {createEnum, InferSchemaType, schemaWithName} from '@orion-js/schema'\n\n/**\n * Enum representing the status of a job record.\n * - 'pending': Job is active and can be executed (default for existing records)\n * - 'maxTriesReached': Event job has exhausted all retry attempts and won't be executed\n */\nexport const JobStatusEnum = createEnum('JobStatus', ['pending', 'maxTriesReached'])\n\nexport const JobRecordSchema = schemaWithName('JobRecord', {\n _id: {type: 'string'},\n jobName: {type: 'string'},\n type: {type: createEnum('JobType', ['recurrent', 'event'])},\n priority: {type: 'number'},\n uniqueIdentifier: {type: 'string', optional: true},\n nextRunAt: {type: 'date'},\n lastRunAt: {type: 'date', optional: true},\n lockedUntil: {type: 'date', optional: true},\n /**\n * Identifies the execution that currently owns the lock. Mutations from an execution must match\n * this value so a stale execution cannot modify a newer claim.\n */\n lockId: {type: 'string', optional: true},\n tries: {type: 'number', optional: true},\n params: {type: 'blackbox', optional: true},\n /**\n * Status of the job. Optional for backwards compatibility with existing records.\n * Records without this field are treated as 'pending'.\n */\n status: {type: JobStatusEnum, optional: true},\n /**\n * Date when the job reached its maximum tries. Used as the stable anchor when\n * maxTriesReachedRetentionMs changes between worker restarts.\n */\n maxTriesReachedAt: {type: 'date', optional: true},\n /**\n * Date when MongoDB should remove a terminal event job through the TTL index.\n */\n expiresAt: {type: 'date', optional: true},\n})\n\nexport type JobRecord = InferSchemaType<typeof JobRecordSchema>\n","import {JobsDefinition} from './JobsDefinition'\nimport {JobToRun} from './Worker'\n\nexport type LogLevels = 'debug' | 'info' | 'warn' | 'error' | 'none'\n\nexport const DEFAULT_MAX_TRIES_REACHED_RETENTION_MS = 1000 * 60 * 60 * 24 * 7\n\nexport interface StartWorkersConfig {\n /**\n * Object map of the jobs that this scheduler will execute.\n */\n jobs: JobsDefinition\n /**\n * Maximum number of tries for an event job before it is marked as 'maxTriesReached'.\n * This is a global default that can be overridden per event job definition.\n */\n maxTries?: number\n /**\n * Time in milliseconds to keep event jobs after they reach their maximum tries.\n * Defaults to one week. Set to null to keep them indefinitely.\n */\n maxTriesReachedRetentionMs?: number | null\n /**\n * Callback invoked when an event job reaches its maximum tries limit.\n * Use this to notify administrators (e.g., send an email alert).\n * The job will remain in the database with status 'maxTriesReached' until its\n * configured retention period expires.\n */\n onMaxTriesReached?: (job: JobToRun) => Promise<void>\n /**\n * Time in milliseconds to wait between each look without results for a job\n * to run at the database. Default is 3000.\n */\n pollInterval?: number\n /**\n * @deprecated The centralized scheduler no longer waits after successful job acquisition or\n * execution. This option is accepted for backwards compatibility and ignored.\n */\n cooldownPeriod?: number\n /**\n * Maximum number of concurrent job executions for this scheduler. Default is 4.\n */\n workersCount?: number\n /**\n * Default time in milliseconds to lock a job for execution. Default is 30000 (30 seconds).\n * If a job is locked for longer than this time, it will be considered as failed.\n * This is to prevent a job from being executed multiple times at the same time.\n * You can extend this time inside a job by calling extendLockTime from context.\n * Individual jobs can override this value by setting their own lockTime.\n */\n defaultLockTime?: number\n}\n","import {CronExpressionParser} from 'cron-parser'\n\nexport type Options = {\n getNextRun?: () => Date\n runIn?: number\n runEvery?: number\n runAt?: Date\n cron?: string\n timezone?: string\n currentDate?: Date | string | number\n} & {[key: string]: any}\n\nexport const getNextRunDate = (options: Options) => {\n if (options.runIn) {\n return new Date(Date.now() + options.runIn)\n }\n\n if (options.runEvery) {\n return new Date(Date.now() + options.runEvery)\n }\n\n if (options.cron) {\n if (!options.timezone) {\n throw new Error('Cron recurrent jobs require a timezone')\n }\n\n return CronExpressionParser.parse(options.cron, {\n currentDate: options.currentDate ?? new Date(),\n tz: options.timezone,\n })\n .next()\n .toDate()\n }\n\n if (options.runAt) {\n return options.runAt\n }\n\n if (options.getNextRun) {\n return options.getNextRun()\n }\n\n return new Date()\n}\n","import {sleep} from '@orion-js/helpers'\nimport {logger} from '@orion-js/logger'\nimport {Inject, Service} from '@orion-js/services'\nimport {\n CANDIDATE_JOB_ACQUISITION_HINT,\n INITIAL_JOB_ACQUISITION_HINT,\n JobAcquisitionHint,\n JobsRepo,\n} from '../repos/JobsRepo'\nimport {JobDefinitionWithName, JobsDefinition} from '../types/JobsDefinition'\nimport {DEFAULT_MAX_TRIES_REACHED_RETENTION_MS, StartWorkersConfig} from '../types/StartConfig'\nimport {JobToRun, WorkersInstance} from '../types/Worker'\nimport {ExecuteJobConfig, Executor} from './Executor'\n\ninterface TrackedExecution {\n job: JobToRun\n promise: Promise<void>\n capacityPromise: Promise<void>\n releaseCapacity: () => void\n status: 'running' | 'stale' | 'finished'\n}\n\ninterface InternalWorkersInstance extends WorkersInstance {\n activeExecutions: Map<string, TrackedExecution>\n staleExecutions: Map<string, TrackedExecution>\n runningJobsByName: Map<string, number>\n jobAcquisitionHint: JobAcquisitionHint\n jobAcquisitionHintProbeCycle: number\n hasCompletedInitialJobAcquisitionHintProbe: boolean\n pendingJobAcquisitionHint?: JobAcquisitionHint\n pendingJobAcquisitionHintWins: number\n jobAcquisitionHintProbePromise: Promise<void>\n jobAcquisitionHintProbeTimer?: ReturnType<typeof setTimeout>\n cancelJobAcquisitionHintProbeWait?: () => void\n schedulerPromise: Promise<void>\n stopSignal: Promise<void>\n signalStop: () => void\n stopPromise?: Promise<void>\n}\n\n@Service()\nexport class WorkerService {\n private jobAcquisitionHintProbeIntervalMs = 30 * 60 * 1000\n\n @Inject(() => JobsRepo)\n private jobsRepo: JobsRepo\n\n @Inject(() => Executor)\n private executor: Executor\n\n getJobNames(jobs: JobsDefinition) {\n return Object.keys(jobs)\n }\n\n getJobs(jobs: JobsDefinition): JobDefinitionWithName[] {\n return Object.keys(jobs).map(name => {\n return {\n name,\n ...jobs[name],\n }\n })\n }\n\n getAvailableJobNames(\n config: StartWorkersConfig,\n workersInstance: InternalWorkersInstance,\n jobNames: string[],\n ) {\n return jobNames.filter(jobName => {\n const currentExecutions = workersInstance.runningJobsByName.get(jobName) || 0\n const job = config.jobs[jobName]\n const maxParallelExecutions =\n job.type === 'event'\n ? (job.maxParallelExecutionsPerServer ?? Number.POSITIVE_INFINITY)\n : Number.POSITIVE_INFINITY\n\n return currentExecutions < maxParallelExecutions\n })\n }\n\n reserveJobExecution(workersInstance: InternalWorkersInstance, jobName: string) {\n const currentExecutions = workersInstance.runningJobsByName.get(jobName) || 0\n workersInstance.runningJobsByName.set(jobName, currentExecutions + 1)\n }\n\n releaseJobExecution(workersInstance: InternalWorkersInstance, jobName: string) {\n const currentExecutions = workersInstance.runningJobsByName.get(jobName) || 0\n if (currentExecutions <= 1) {\n workersInstance.runningJobsByName.delete(jobName)\n return\n }\n\n workersInstance.runningJobsByName.set(jobName, currentExecutions - 1)\n }\n\n releaseExecutionCapacity(\n workersInstance: InternalWorkersInstance,\n execution: TrackedExecution,\n nextStatus: 'stale' | 'finished',\n ) {\n if (execution.status !== 'running') return\n\n execution.status = nextStatus\n workersInstance.activeExecutions.delete(execution.job.executionId)\n this.releaseJobExecution(workersInstance, execution.job.name)\n execution.releaseCapacity()\n\n if (nextStatus === 'stale') {\n workersInstance.staleExecutions.set(execution.job.executionId, execution)\n }\n }\n\n startExecution(\n config: ExecuteJobConfig,\n workersInstance: InternalWorkersInstance,\n jobToRun: JobToRun,\n ) {\n let releaseCapacity!: () => void\n const capacityPromise = new Promise<void>(resolve => {\n releaseCapacity = resolve\n })\n\n const execution: TrackedExecution = {\n job: jobToRun,\n promise: Promise.resolve(),\n capacityPromise,\n releaseCapacity,\n status: 'running',\n }\n\n this.reserveJobExecution(workersInstance, jobToRun.name)\n workersInstance.activeExecutions.set(jobToRun.executionId, execution)\n\n logger.debug(`Starting job execution \"${jobToRun.executionId}\"`, jobToRun)\n\n const executionPromise = this.executor.executeJob(config, jobToRun, () => {\n this.releaseExecutionCapacity(workersInstance, execution, 'stale')\n })\n execution.promise = executionPromise\n\n void executionPromise\n .catch(error => {\n logger.error(`Unhandled error executing job \"${jobToRun.name}\"`, {error})\n })\n .finally(() => {\n if (execution.status === 'running') {\n this.releaseExecutionCapacity(workersInstance, execution, 'finished')\n } else if (execution.status === 'stale') {\n workersInstance.staleExecutions.delete(jobToRun.executionId)\n }\n })\n }\n\n async waitForPollOrStop(config: StartWorkersConfig, workersInstance: InternalWorkersInstance) {\n await Promise.race([sleep(config.pollInterval), workersInstance.stopSignal])\n }\n\n async waitForCapacityOrStop(workersInstance: InternalWorkersInstance) {\n const capacityPromises = Array.from(\n workersInstance.activeExecutions.values(),\n execution => execution.capacityPromise,\n )\n\n if (capacityPromises.length === 0) return\n await Promise.race([...capacityPromises, workersInstance.stopSignal])\n }\n\n async runSchedulerLoop(config: StartWorkersConfig, workersInstance: InternalWorkersInstance) {\n const jobNames = this.getJobNames(config.jobs)\n const executeConfig: ExecuteJobConfig = {\n jobs: config.jobs,\n maxTries: config.maxTries,\n maxTriesReachedRetentionMs: config.maxTriesReachedRetentionMs,\n onMaxTriesReached: config.onMaxTriesReached,\n }\n\n logger.debug(`Running scheduler loop for jobs \"${jobNames.join(', ')}\"...`)\n\n while (workersInstance.running) {\n let didMiss = false\n let allJobNamesAtCapacity = false\n\n try {\n while (workersInstance.activeExecutions.size < config.workersCount) {\n const availableJobNames = this.getAvailableJobNames(config, workersInstance, jobNames)\n\n if (availableJobNames.length === 0) {\n allJobNamesAtCapacity = workersInstance.activeExecutions.size > 0\n break\n }\n\n const jobToRun = await this.jobsRepo.getJobAndLock(\n availableJobNames,\n config.defaultLockTime,\n workersInstance.jobAcquisitionHint,\n )\n\n if (!jobToRun) {\n logger.debug('No job to run')\n didMiss = true\n break\n }\n\n // An acquisition already in flight when stop() is called is considered committed.\n this.startExecution(executeConfig, workersInstance, jobToRun)\n if (!workersInstance.running) break\n }\n } catch (error) {\n logger.error('Error in job scheduler.', {error})\n didMiss = true\n }\n\n if (!workersInstance.running) return\n\n const concurrencyIsFull =\n workersInstance.activeExecutions.size >= config.workersCount &&\n workersInstance.activeExecutions.size > 0\n\n if (concurrencyIsFull || allJobNamesAtCapacity) {\n await this.waitForCapacityOrStop(workersInstance)\n } else if (didMiss || workersInstance.activeExecutions.size === 0) {\n await this.waitForPollOrStop(config, workersInstance)\n }\n }\n }\n\n getOtherJobAcquisitionHint(hint: JobAcquisitionHint): JobAcquisitionHint {\n return hint === INITIAL_JOB_ACQUISITION_HINT\n ? CANDIDATE_JOB_ACQUISITION_HINT\n : INITIAL_JOB_ACQUISITION_HINT\n }\n\n getMedian(values: number[]): number {\n const sortedValues = [...values].sort((left, right) => left - right)\n return sortedValues[Math.floor(sortedValues.length / 2)]\n }\n\n resetPendingJobAcquisitionHint(workersInstance: InternalWorkersInstance) {\n workersInstance.pendingJobAcquisitionHint = undefined\n workersInstance.pendingJobAcquisitionHintWins = 0\n }\n\n async runJobAcquisitionHintProbe(\n config: StartWorkersConfig,\n workersInstance: InternalWorkersInstance,\n ) {\n const jobNames = this.getJobNames(config.jobs)\n if (jobNames.length === 0 || !workersInstance.running) return\n\n const byHint: Record<JobAcquisitionHint, number[]> = {\n [INITIAL_JOB_ACQUISITION_HINT]: [],\n [CANDIDATE_JOB_ACQUISITION_HINT]: [],\n }\n const startsWithInitialHint = workersInstance.jobAcquisitionHintProbeCycle % 2 === 0\n const firstHint = startsWithInitialHint\n ? INITIAL_JOB_ACQUISITION_HINT\n : CANDIDATE_JOB_ACQUISITION_HINT\n const secondHint = this.getOtherJobAcquisitionHint(firstHint)\n workersInstance.jobAcquisitionHintProbeCycle++\n\n try {\n for (let sample = 0; sample < 3; sample++) {\n for (const hint of [firstHint, secondHint]) {\n if (!workersInstance.running) return\n const executionTimeMillis = await this.jobsRepo.getJobAcquisitionExecutionTime(\n jobNames,\n hint,\n )\n if (!workersInstance.running) return\n byHint[hint].push(executionTimeMillis)\n }\n }\n } catch (error) {\n this.resetPendingJobAcquisitionHint(workersInstance)\n if (workersInstance.running) {\n logger.warn('Job acquisition hint probe failed; keeping the current hint.', {error})\n }\n return\n }\n\n const currentHint = workersInstance.jobAcquisitionHint\n const otherHint = this.getOtherJobAcquisitionHint(currentHint)\n const currentMedian = this.getMedian(byHint[currentHint])\n const otherMedian = this.getMedian(byHint[otherHint])\n const winner = otherMedian < currentMedian ? otherHint : currentHint\n\n if (!workersInstance.hasCompletedInitialJobAcquisitionHintProbe) {\n workersInstance.hasCompletedInitialJobAcquisitionHintProbe = true\n workersInstance.jobAcquisitionHint = winner\n this.resetPendingJobAcquisitionHint(workersInstance)\n logger.info(`Selected job acquisition hint \"${winner}\" after startup probe.`)\n return\n }\n\n if (winner === currentHint) {\n this.resetPendingJobAcquisitionHint(workersInstance)\n logger.debug(`Keeping job acquisition hint \"${currentHint}\" after probe.`)\n return\n }\n\n if (workersInstance.pendingJobAcquisitionHint === winner) {\n workersInstance.pendingJobAcquisitionHintWins++\n } else {\n workersInstance.pendingJobAcquisitionHint = winner\n workersInstance.pendingJobAcquisitionHintWins = 1\n }\n\n if (workersInstance.pendingJobAcquisitionHintWins < 2) {\n logger.debug(\n `Keeping job acquisition hint \"${currentHint}\"; \"${winner}\" has one consecutive probe win.`,\n )\n return\n }\n\n workersInstance.jobAcquisitionHint = winner\n this.resetPendingJobAcquisitionHint(workersInstance)\n logger.info(`Changed job acquisition hint from \"${currentHint}\" to \"${winner}\".`)\n }\n\n async waitForNextJobAcquisitionHintProbe(workersInstance: InternalWorkersInstance) {\n await new Promise<void>(resolve => {\n let resolved = false\n const finishWait = () => {\n if (resolved) return\n resolved = true\n clearTimeout(workersInstance.jobAcquisitionHintProbeTimer)\n workersInstance.jobAcquisitionHintProbeTimer = undefined\n workersInstance.cancelJobAcquisitionHintProbeWait = undefined\n resolve()\n }\n\n workersInstance.jobAcquisitionHintProbeTimer = setTimeout(\n finishWait,\n this.jobAcquisitionHintProbeIntervalMs,\n )\n workersInstance.cancelJobAcquisitionHintProbeWait = finishWait\n })\n }\n\n async runJobAcquisitionHintProbeLoop(\n config: StartWorkersConfig,\n workersInstance: InternalWorkersInstance,\n ) {\n if (this.getJobNames(config.jobs).length === 0) return\n\n while (workersInstance.running) {\n await this.runJobAcquisitionHintProbe(config, workersInstance)\n if (!workersInstance.running) return\n await this.waitForNextJobAcquisitionHintProbe(workersInstance)\n }\n }\n\n createWorkersInstanceDefinition(config: StartWorkersConfig): InternalWorkersInstance {\n let signalStop!: () => void\n const stopSignal = new Promise<void>(resolve => {\n signalStop = resolve\n })\n\n const workersInstance: InternalWorkersInstance = {\n running: true,\n workersCount: config.workersCount,\n activeExecutions: new Map(),\n staleExecutions: new Map(),\n runningJobsByName: new Map(),\n jobAcquisitionHint: INITIAL_JOB_ACQUISITION_HINT,\n jobAcquisitionHintProbeCycle: 0,\n hasCompletedInitialJobAcquisitionHintProbe: false,\n pendingJobAcquisitionHintWins: 0,\n jobAcquisitionHintProbePromise: Promise.resolve(),\n schedulerPromise: Promise.resolve(),\n stopSignal,\n signalStop,\n get runningExecutions() {\n return this.activeExecutions.size\n },\n stop: async () => {\n if (workersInstance.stopPromise) return workersInstance.stopPromise\n\n workersInstance.stopPromise = (async () => {\n logger.info('Stopping job scheduler...')\n workersInstance.running = false\n workersInstance.signalStop()\n workersInstance.cancelJobAcquisitionHintProbeWait?.()\n\n await Promise.all([\n workersInstance.schedulerPromise,\n workersInstance.jobAcquisitionHintProbePromise,\n ])\n\n const activeCapacity = Array.from(\n workersInstance.activeExecutions.values(),\n execution => execution.capacityPromise,\n )\n await Promise.all(activeCapacity)\n })()\n\n return workersInstance.stopPromise\n },\n }\n\n return workersInstance\n }\n\n async ensureRecords(config: StartWorkersConfig) {\n const jobs = this.getJobs(config.jobs)\n\n await Promise.all(\n jobs\n .filter(job => job.type === 'recurrent')\n .map(async job => {\n logger.debug(`Ensuring records for job \"${job.name}\"...`)\n await this.jobsRepo.ensureJobRecord(job)\n }),\n )\n }\n\n async runScheduler(config: StartWorkersConfig, workersInstance: InternalWorkersInstance) {\n logger.debug('Will ensure maxTriesReached retention and TTL index')\n void this.jobsRepo\n .ensureMaxTriesReachedRetention(config.maxTriesReachedRetentionMs)\n .catch(error => logger.error('Error ensuring maxTriesReached retention', {error}))\n\n logger.debug('Will ensure records for recurrent jobs')\n await this.ensureRecords(config)\n\n logger.info(`Starting job scheduler with concurrency ${config.workersCount}`)\n await this.runSchedulerLoop(config, workersInstance)\n }\n\n /**\n * Starts one job scheduler with the provided concurrency configuration.\n * @param userConfig - Configuration for the scheduler. Required field: jobs\n */\n startWorkers(userConfig: StartWorkersConfig): WorkersInstance {\n const maxTriesReachedRetentionMs =\n userConfig.maxTriesReachedRetentionMs === undefined\n ? DEFAULT_MAX_TRIES_REACHED_RETENTION_MS\n : userConfig.maxTriesReachedRetentionMs\n\n if (\n maxTriesReachedRetentionMs !== null &&\n (!Number.isFinite(maxTriesReachedRetentionMs) || maxTriesReachedRetentionMs < 0)\n ) {\n throw new Error('maxTriesReachedRetentionMs must be null, zero, or a positive number')\n }\n\n const config: StartWorkersConfig = {\n pollInterval: 3000,\n workersCount: 4,\n defaultLockTime: 30 * 1000,\n ...userConfig,\n maxTriesReachedRetentionMs,\n }\n\n setNameToJobs(config.jobs)\n\n const workersInstance = this.createWorkersInstanceDefinition(config)\n logger.debug('Starting job scheduler', config)\n\n workersInstance.jobAcquisitionHintProbePromise = this.runJobAcquisitionHintProbeLoop(\n config,\n workersInstance,\n )\n\n workersInstance.schedulerPromise = this.runScheduler(config, workersInstance).catch(error => {\n workersInstance.running = false\n workersInstance.signalStop()\n workersInstance.cancelJobAcquisitionHintProbeWait?.()\n logger.error('Job scheduler stopped after an unexpected error.', {error})\n })\n\n return workersInstance\n }\n}\n\nfunction setNameToJobs(jobs: JobsDefinition) {\n for (const name of Object.keys(jobs)) {\n jobs[name].jobName = name\n }\n}\n","import {SpanStatusCode, trace} from '@opentelemetry/api'\nimport {logger, runWithOrionAsyncContext, updateOrionAsyncContext} from '@orion-js/logger'\nimport {Blackbox} from '@orion-js/schema'\nimport {Inject, Service} from '@orion-js/services'\nimport {JobsHistoryRepo} from '../repos/JobsHistoryRepo'\nimport {JobsRepo} from '../repos/JobsRepo'\nimport {EventJobDefinition, JobDefinition, JobsDefinition} from '../types/JobsDefinition'\nimport {ExecutionContext, JobToRun} from '../types/Worker'\nimport {getNextRunDate} from './getNextRunDate'\n\n/**\n * Configuration for job execution including max tries settings.\n */\nexport interface ExecuteJobConfig {\n jobs: JobsDefinition\n maxTries?: number\n maxTriesReachedRetentionMs?: number | null\n onMaxTriesReached?: (job: JobToRun) => Promise<void>\n}\n\n@Service()\nexport class Executor {\n @Inject(() => JobsRepo)\n private readonly jobsRepo: JobsRepo\n\n @Inject(() => JobsHistoryRepo)\n private readonly jobsHistoryRepo: JobsHistoryRepo\n\n /**\n * Determines the effective lock time for a job execution.\n * Job-specific lockTime takes precedence over the default lockTime from config.\n */\n getEffectiveLockTime(job: JobDefinition, jobToRun: JobToRun): number {\n return job.lockTime ?? jobToRun.lockTime\n }\n\n getContext(\n job: JobDefinition,\n jobToRun: JobToRun,\n onStale: () => void,\n isExecutionActive: () => boolean,\n ): ExecutionContext {\n const effectiveLockTime = this.getEffectiveLockTime(job, jobToRun)\n let staleTimeout = setTimeout(() => onStale(), effectiveLockTime)\n staleTimeout.unref?.()\n const contextLogger = logger.addMetadata({\n jobName: jobToRun.name,\n jobId: jobToRun.jobId,\n })\n\n return {\n definition: job,\n record: jobToRun,\n tries: jobToRun.tries || 0,\n clearStaleTimeout: () => clearTimeout(staleTimeout),\n extendLockTime: async (extraTime: number) => {\n if (!isExecutionActive()) {\n contextLogger.warn(`Will not extend lock for stale execution \"${jobToRun.executionId}\"`)\n return\n }\n\n clearTimeout(staleTimeout)\n let didExtend = false\n try {\n didExtend = await this.jobsRepo.extendLockTime(jobToRun.jobId, extraTime, jobToRun.lockId)\n } catch (error) {\n onStale()\n throw error\n }\n if (!didExtend) {\n onStale()\n return\n }\n staleTimeout = setTimeout(() => onStale(), extraTime)\n staleTimeout.unref?.()\n },\n logger: contextLogger,\n }\n }\n\n getJobDefinition(jobToRun: JobToRun, jobs: JobsDefinition) {\n const job = jobs[jobToRun.name]\n\n if (jobToRun.type !== job.type) {\n logger.warn(\n `Job record \"${jobToRun.name}\" is \"${jobToRun.type}\" but definition is \"${job.type}\"`,\n )\n return\n }\n\n return job\n }\n\n /**\n * Determines the effective max tries for an event job.\n * Job-specific maxTries takes precedence over the global maxTries from config.\n */\n getEffectiveMaxTries(job: EventJobDefinition, globalMaxTries?: number): number | undefined {\n return job.maxTries ?? globalMaxTries\n }\n\n /**\n * Handles when a job has reached its maximum retry attempts.\n * Marks the job in the database and invokes the onMaxTriesReached callback when provided.\n */\n async handleMaxTriesReached(\n jobToRun: JobToRun,\n retentionMs?: number | null,\n onMaxTriesReached?: (job: JobToRun) => Promise<void>,\n ) {\n const jobLogger = logger.addMetadata({\n jobName: jobToRun.name,\n jobId: jobToRun.jobId,\n })\n\n jobLogger.warn(\n `Job \"${jobToRun.name}\" has exceeded max tries (${jobToRun.tries}). Marking as maxTriesReached.`,\n )\n const didMark = await this.jobsRepo.markJobAsMaxTriesReached(\n jobToRun.jobId,\n retentionMs,\n jobToRun.lockId,\n )\n\n if (!didMark) {\n jobLogger.warn(`Could not mark job \"${jobToRun.name}\" because its lock is no longer owned`)\n return false\n }\n\n if (!onMaxTriesReached) return true\n\n // Invoke the callback to notify administrators\n try {\n await onMaxTriesReached(jobToRun)\n } catch (callbackError) {\n jobLogger.error(`Error in onMaxTriesReached callback for job \"${jobToRun.name}\"`, {\n error: callbackError,\n })\n }\n\n return true\n }\n\n async onError(error: unknown, job: JobDefinition, jobToRun: JobToRun, context: ExecutionContext) {\n // Helper to schedule next run for recurrent jobs (used when dismissing)\n const scheduleRecurrent = async () => {\n if (job.type === 'recurrent') {\n return this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt: getNextRunDate(job),\n resetTries: true,\n priority: job.priority,\n lockId: jobToRun.lockId,\n })\n }\n return true\n }\n\n const handleRetry = async (nextRunAt: Date) => {\n return this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt,\n resetTries: false,\n priority: job.type === 'recurrent' ? job.priority : jobToRun.priority,\n lockId: jobToRun.lockId,\n })\n }\n\n if (!job.onError) {\n context.logger.error(`Error executing job \"${jobToRun.name}\"`, {error})\n\n return scheduleRecurrent()\n }\n\n context.logger.info(`Error executing job \"${jobToRun.name}\"`, {error})\n const result = await job.onError(\n error instanceof Error ? error : new Error(String(error)),\n jobToRun.params,\n context,\n )\n\n if (result.action === 'dismiss') {\n return scheduleRecurrent()\n }\n\n if (result.action === 'retry') {\n return handleRetry(getNextRunDate(result))\n }\n\n return true\n }\n\n async saveExecution(options: {\n startedAt: Date\n status: 'stale' | 'error' | 'success'\n errorMessage?: string\n result?: Blackbox\n job: JobDefinition\n jobToRun: JobToRun\n }) {\n const {startedAt, status, errorMessage, result, job, jobToRun} = options\n const endedAt = new Date()\n\n if (job.saveExecutionsFor !== 0) {\n const oneWeek = 1000 * 60 * 60 * 24 * 7\n const saveExecutionsFor = job.saveExecutionsFor || oneWeek\n await this.jobsHistoryRepo.saveExecution({\n jobId: jobToRun.jobId,\n executionId: jobToRun.executionId,\n jobName: jobToRun.name,\n type: jobToRun.type,\n priority: jobToRun.priority,\n tries: jobToRun.tries,\n uniqueIdentifier: jobToRun.uniqueIdentifier,\n startedAt,\n endedAt,\n duration: endedAt.getTime() - startedAt.getTime(),\n expiresAt: new Date(Date.now() + saveExecutionsFor),\n status,\n errorMessage,\n params: jobToRun.params,\n result,\n })\n }\n }\n\n async afterExecutionSuccess(job: JobDefinition, jobToRun: JobToRun, context: ExecutionContext) {\n if (job.type === 'recurrent') {\n context.logger.debug(`Scheduling next run for recurrent job \"${jobToRun.name}\"`)\n return this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt: getNextRunDate(job),\n resetTries: true,\n priority: job.priority,\n lockId: jobToRun.lockId,\n })\n }\n if (job.type === 'event') {\n context.logger.debug(`Removing event job after success \"${jobToRun.name}\"`)\n return this.jobsRepo.deleteEventJob(jobToRun.jobId, jobToRun.lockId)\n }\n return false\n }\n\n async executeJob(config: ExecuteJobConfig, jobToRun: JobToRun, onExecutionStale: () => void) {\n const job = this.getJobDefinition(jobToRun, config.jobs)\n if (!job) return\n\n if (job.type === 'event') {\n const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries)\n if (typeof effectiveMaxTries === 'number' && jobToRun.tries > effectiveMaxTries) {\n await this.handleMaxTriesReached(\n jobToRun,\n config.maxTriesReachedRetentionMs,\n config.onMaxTriesReached,\n )\n return\n }\n }\n\n // If job has a custom lockTime different from the default, update the database lock\n const effectiveLockTime = this.getEffectiveLockTime(job, jobToRun)\n if (effectiveLockTime !== jobToRun.lockTime) {\n const didUpdateLock = await this.jobsRepo.updateLockTime(\n jobToRun.jobId,\n effectiveLockTime,\n jobToRun.lockId,\n )\n if (!didUpdateLock) {\n logger.warn(`Will not execute job \"${jobToRun.name}\" because its lock is no longer owned`)\n return\n }\n }\n\n const tracer = trace.getTracer('orionjs.dogs', '1.0')\n\n await tracer.startActiveSpan(`job.${jobToRun.name}.${jobToRun.executionId}`, async span => {\n try {\n const startedAt = new Date()\n let executionStatus: 'running' | 'stale' = 'running'\n let staleHandlingPromise: Promise<void> | undefined\n let context: ExecutionContext\n\n const markAsStale = () => {\n if (executionStatus === 'stale') return staleHandlingPromise\n\n executionStatus = 'stale'\n context.clearStaleTimeout()\n\n staleHandlingPromise = (async () => {\n context.logger.warn(`Job \"${jobToRun.name}\" is stale`)\n\n if (job.onStale) {\n void Promise.resolve(job.onStale(jobToRun.params, context)).catch(error => {\n context.logger.error(`Error in onStale callback for job \"${jobToRun.name}\"`, {\n error,\n })\n })\n }\n\n try {\n await this.jobsRepo.setJobRecordPriority(jobToRun.jobId, 0, jobToRun.lockId)\n } catch (error) {\n context.logger.error(`Error lowering priority for stale job \"${jobToRun.name}\"`, {\n error,\n })\n } finally {\n // Preserve the current ordering guarantee: a stale retry only becomes eligible for\n // local capacity after its priority has been lowered.\n onExecutionStale()\n }\n\n await this.saveExecution({\n startedAt,\n status: 'stale',\n result: null,\n errorMessage: null,\n job,\n jobToRun,\n })\n })().catch(error => {\n context.logger.error('Error handling stale execution', {error})\n })\n\n return staleHandlingPromise\n }\n\n context = this.getContext(\n job,\n jobToRun,\n () => void markAsStale(),\n () => executionStatus === 'running',\n )\n\n const extraContext = {\n controllerType: 'job' as const,\n jobName: jobToRun.name,\n jobId: jobToRun.jobId,\n params: jobToRun.params,\n }\n\n await runWithOrionAsyncContext(extraContext, async () => {\n try {\n // Inject async context update\n updateOrionAsyncContext({\n jobName: jobToRun.name,\n jobId: jobToRun.jobId,\n params: jobToRun.params,\n })\n const result = await job.resolve(jobToRun.params, context)\n context.clearStaleTimeout()\n\n if (executionStatus === 'stale') {\n await staleHandlingPromise\n context.logger.warn(\n `Ignoring late success from stale execution \"${jobToRun.executionId}\"`,\n )\n return\n }\n\n const stillOwnsJob = await this.afterExecutionSuccess(job, jobToRun, context)\n if (!stillOwnsJob) {\n await markAsStale()\n return\n }\n\n void this.saveExecution({\n startedAt,\n status: 'success',\n result: result || null,\n errorMessage: null,\n job,\n jobToRun,\n }).catch(error => {\n context.logger.error('Error saving successful execution history', {error})\n })\n } catch (error) {\n context.clearStaleTimeout()\n\n if (executionStatus === 'stale') {\n await staleHandlingPromise\n context.logger.warn(\n `Ignoring late error from stale execution \"${jobToRun.executionId}\"`,\n {error},\n )\n return\n }\n\n const stillOwnsJob = await this.onError(error, job, jobToRun, context)\n if (!stillOwnsJob) {\n await markAsStale()\n return\n }\n\n void this.saveExecution({\n startedAt,\n status: 'error',\n result: null,\n errorMessage: (error as Error).message,\n job,\n jobToRun,\n }).catch(saveError => {\n context.logger.error('Error saving failed execution history', {error: saveError})\n })\n }\n })\n } catch (error) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: (error as Error).message,\n })\n throw error\n } finally {\n span.end()\n }\n })\n }\n}\n","import {Collection, MongoCollection, Repository, MongoDB} from '@orion-js/mongodb'\nimport {omit} from 'rambdax'\nimport {HistoryRecord, HistoryRecordSchema} from '../types/HistoryRecord'\n\n@Repository()\nexport class JobsHistoryRepo {\n @MongoCollection({\n name: 'orionjs.jobs_dogs_history',\n idGeneration: 'uuid',\n schema: HistoryRecordSchema,\n indexes: [\n {\n keys: {\n jobName: 1,\n startedAt: 1,\n },\n },\n {\n keys: {\n executionId: 1,\n },\n },\n {\n keys: {\n expiresAt: 1,\n },\n options: {\n expireAfterSeconds: 0,\n },\n },\n ],\n })\n history: Collection<HistoryRecord>\n\n async saveExecution(record: MongoDB.WithoutId<HistoryRecord>) {\n await this.history.upsert(\n {executionId: record.executionId},\n {\n $setOnInsert: {\n status: record.status,\n },\n $set: {\n ...omit(['status'], record),\n },\n },\n )\n }\n\n async getExecutions(jobName: string, limit?: number, skip?: number): Promise<HistoryRecord[]> {\n const cursor = this.history.find({jobName}).sort({startedAt: -1})\n\n if (skip) {\n cursor.skip(skip)\n }\n\n if (limit) {\n cursor.limit(limit)\n }\n\n return await cursor.toArray()\n }\n}\n","function _isInteger(n){\n return n << 0 === n\n}\n\nexport const isInteger = Number.isInteger || _isInteger\n\n/**\n * Check if `index` is integer even if it is a string.\n */\nexport const isIndexInteger = index => Number.isInteger(Number(index))\n","import { isInteger } from './isInteger.js'\n\nexport function createPath(path, delimiter = '.'){\n return typeof path === 'string' ?\n path.split(delimiter).map(x => isInteger(x) ? Number(x) : x) :\n path\n}\n","export function compare(a, b){\n return String(a) === String(b)\n}\n","import { compare } from './compare.js'\n\nexport function includes(a, list){\n let index = -1\n const { length } = list\n\n while (++index < length)\n if (compare(list[ index ], a))\n return true\n\n return false\n}\n","import { createPath } from './_internals/createPath.js'\nimport { includes } from './_internals/includes.js'\n\nexport function omit(propsToOmit, obj){\n if (arguments.length === 1) return _obj => omit(propsToOmit, _obj)\n\n if (obj === null || obj === undefined)\n return undefined\n\n const propsToOmitValue = createPath(propsToOmit, ',')\n const willReturn = {}\n\n for (const key in obj)\n if (!includes(key, propsToOmitValue))\n willReturn[ key ] = obj[ key ]\n\n return willReturn\n}\n","import {InferSchemaType, schemaWithName} from '@orion-js/schema'\n\nexport const HistoryRecordSchema = schemaWithName('HistoryRecord', {\n _id: {type: 'string'},\n jobId: {type: 'string'},\n executionId: {type: 'string'},\n jobName: {type: 'string'},\n type: {type: 'string'},\n priority: {type: 'number'},\n tries: {type: 'number'},\n uniqueIdentifier: {type: 'string', optional: true},\n startedAt: {type: 'date'},\n endedAt: {type: 'date'},\n duration: {type: 'number'},\n expiresAt: {type: 'date', optional: true},\n status: {type: 'string', enum: ['success', 'error', 'stale']},\n errorMessage: {type: 'string', optional: true},\n params: {type: 'blackbox', optional: true},\n result: {type: 'any', optional: true},\n})\n\nexport type HistoryRecord = InferSchemaType<typeof HistoryRecordSchema>\n","import {getInstance, Service} from '@orion-js/services'\nimport {createEventJob, defineJob} from '../defineJob'\nimport type {CreateEventJobOptions, JobDefinition, RecurrentJobDefinition} from '../types'\n\n// Define metadata storage using WeakMaps\nconst serviceMetadata = new WeakMap<any, {_serviceType: string}>()\nconst jobsMetadata = new Map<any, Record<string, any>>()\nconst jobEntriesByClass = new Map<Function, Record<string, (instance: any) => any>>()\nlet pendingJobEntries: Record<string, (instance: any) => any> = {}\n\nexport function Jobs() {\n return (target: any, context: ClassDecoratorContext<any>) => {\n Service()(target, context)\n serviceMetadata.set(target, {_serviceType: 'jobs'})\n\n if (Object.keys(pendingJobEntries).length > 0) {\n jobEntriesByClass.set(target, pendingJobEntries)\n pendingJobEntries = {}\n }\n }\n}\n\nexport function RecurrentJob(): (\n method: any,\n context: ClassFieldDecoratorContext | ClassMethodDecoratorContext,\n) => any\nexport function RecurrentJob(\n options: Omit<RecurrentJobDefinition, 'resolve' | 'type'>,\n): (method: any, context: ClassMethodDecoratorContext) => any\nexport function RecurrentJob(options = {}) {\n return (method: any, context: ClassFieldDecoratorContext | ClassMethodDecoratorContext) => {\n const propertyKey = String(context.name)\n\n if (context.kind === 'method') {\n pendingJobEntries[propertyKey] = (instance: any) =>\n defineJob({\n ...options,\n type: 'recurrent',\n resolve: instance[propertyKey].bind(instance),\n })\n }\n\n if (context.kind === 'field') {\n pendingJobEntries[propertyKey] = (instance: any) => instance[propertyKey]\n }\n\n return method\n }\n}\n\nexport function EventJob(): (\n method: any,\n context: ClassFieldDecoratorContext | ClassMethodDecoratorContext,\n) => any\nexport function EventJob(\n options: Omit<CreateEventJobOptions<any>, 'resolve'>,\n): (method: any, context: ClassMethodDecoratorContext) => any\nexport function EventJob(options = {}) {\n return (method: any, context: ClassFieldDecoratorContext | ClassMethodDecoratorContext) => {\n const propertyKey = String(context.name)\n\n if (context.kind === 'method') {\n pendingJobEntries[propertyKey] = (instance: any) =>\n createEventJob({\n ...options,\n resolve: instance[propertyKey].bind(instance),\n })\n }\n\n if (context.kind === 'field') {\n pendingJobEntries[propertyKey] = (instance: any) => instance[propertyKey]\n }\n\n return method\n }\n}\n\nfunction initializeJobsIfNeeded(instance: any) {\n if (jobsMetadata.has(instance)) return\n const entries = jobEntriesByClass.get(instance.constructor) || {}\n const jobs: Record<string, any> = {}\n for (const [key, setup] of Object.entries(entries)) {\n jobs[key] = setup(instance)\n }\n jobsMetadata.set(instance, jobs)\n}\n\nexport function getServiceJobs(target: any): {\n [key: string]: JobDefinition\n} {\n const instance = getInstance(target)\n\n if (!serviceMetadata.has(instance.constructor)) {\n throw new Error('You must pass a class decorated with @Jobs to getServiceJobs')\n }\n\n const instanceMetadata = serviceMetadata.get(instance.constructor)\n if (instanceMetadata._serviceType !== 'jobs') {\n throw new Error('You must pass a class decorated with @Jobs to getServiceJobs')\n }\n\n initializeJobsIfNeeded(instance)\n\n const jobsMap = jobsMetadata.get(instance) || {}\n\n return jobsMap\n}\n","import {cleanAndValidate, SchemaInAnyOrionForm} from '@orion-js/schema'\nimport {CronExpressionParser} from 'cron-parser'\nimport parse from 'parse-duration'\nimport {ScheduleJobsResult, scheduleJob, scheduleJobs} from '..'\nimport {ScheduleJobOptionsWithoutName} from '../types/Events'\nimport {\n CreateEventJobOptions,\n CreateJobOptions,\n CreateRecurrentJobOptions,\n EventJobDefinition,\n JobDefinition,\n RecurrentJobDefinition,\n} from '../types/JobsDefinition'\n\nexport function createEventJob<TParamsSchema extends SchemaInAnyOrionForm>(\n options: CreateEventJobOptions<TParamsSchema>,\n): EventJobDefinition<TParamsSchema> {\n const jobDefinition: EventJobDefinition<TParamsSchema> = {\n ...options,\n type: 'event',\n schedule: null,\n scheduleJobs: null,\n }\n\n jobDefinition.schedule = async (\n scheduleOptions: ScheduleJobOptionsWithoutName<TParamsSchema>,\n ) => {\n if (!jobDefinition.jobName) {\n throw new Error('This job has not been registered in the workers')\n }\n\n const params = jobDefinition.params\n ? await cleanAndValidate(jobDefinition.params, scheduleOptions.params)\n : scheduleOptions.params\n\n return await scheduleJob({\n ...scheduleOptions,\n name: jobDefinition.jobName,\n params,\n })\n }\n\n jobDefinition.scheduleJobs = async (\n jobs: Array<ScheduleJobOptionsWithoutName<TParamsSchema>>,\n ): Promise<ScheduleJobsResult> => {\n if (!jobDefinition.jobName) {\n throw new Error('This job has not been registered in the workers')\n }\n\n // Process all job parameters if schema validation is needed\n const processedJobs = await Promise.all(\n jobs.map(async scheduleOptions => {\n const params = jobDefinition.params\n ? await cleanAndValidate(jobDefinition.params, scheduleOptions.params)\n : scheduleOptions.params\n\n return {\n ...scheduleOptions,\n name: jobDefinition.jobName,\n params,\n }\n }),\n )\n\n return await scheduleJobs(processedJobs)\n }\n\n return jobDefinition\n}\n\nexport function createRecurrentJob(options: CreateRecurrentJobOptions): RecurrentJobDefinition {\n const recurrentOptions = {\n ...options,\n } as CreateRecurrentJobOptions & {maxTries?: number}\n\n delete recurrentOptions.maxTries\n\n if ('cron' in recurrentOptions && recurrentOptions.cron && !recurrentOptions.timezone) {\n throw new Error('Cron recurrent jobs require a timezone')\n }\n\n if ('cron' in recurrentOptions && recurrentOptions.cron) {\n CronExpressionParser.parse(recurrentOptions.cron, {tz: recurrentOptions.timezone}).next()\n }\n\n const runEvery =\n 'runEvery' in recurrentOptions\n ? typeof recurrentOptions.runEvery === 'string'\n ? parse(recurrentOptions.runEvery)\n : recurrentOptions.runEvery\n : undefined\n\n const jobDefinition: RecurrentJobDefinition = {\n ...recurrentOptions,\n priority: recurrentOptions.priority ?? 100,\n type: 'recurrent',\n runEvery,\n }\n\n return jobDefinition\n}\n\n/**\n * @deprecated Use `createEventJob` or `createRecurrentJob` instead.\n */\nexport const defineJob = (\n options: CreateJobOptions & {type: 'event' | 'recurrent'},\n): JobDefinition => {\n return options.type === 'event'\n ? createEventJob(options as any)\n : createRecurrentJob(options as any)\n}\n"],"mappings":"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","names":["getInstance","logger","_init","logger","logger","Inject","Service","logger","Inject","Service","MongoCollection","Repository","schemaWithName","_init","Repository","MongoCollection","_jobsRepo_dec","_init","Service","Inject","logger","_a","_jobsRepo_dec","_init","Service","Inject","logger","Service","CronExpressionParser","CronExpressionParser","Service","getInstance"]}
|
package/dist/repos/JobsRepo.d.ts
CHANGED
|
@@ -3,9 +3,24 @@ import { ScheduleJobRecordOptions, ScheduleJobsResult } from '../types/Events';
|
|
|
3
3
|
import { JobRecord } from '../types/JobRecord';
|
|
4
4
|
import { JobDefinitionWithName } from '../types/JobsDefinition';
|
|
5
5
|
import { JobToRun } from '../types/Worker';
|
|
6
|
+
export type JobAcquisitionHint = 'byJobName' | 'globalPriority';
|
|
7
|
+
export declare const JOB_ACQUISITION_HINTS: {
|
|
8
|
+
readonly byJobName: {
|
|
9
|
+
readonly jobName: 1;
|
|
10
|
+
readonly priority: -1;
|
|
11
|
+
readonly nextRunAt: 1;
|
|
12
|
+
};
|
|
13
|
+
readonly globalPriority: {
|
|
14
|
+
readonly priority: -1;
|
|
15
|
+
readonly nextRunAt: 1;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export declare const INITIAL_JOB_ACQUISITION_HINT: "byJobName";
|
|
19
|
+
export declare const CANDIDATE_JOB_ACQUISITION_HINT: "globalPriority";
|
|
6
20
|
export declare class JobsRepo {
|
|
7
21
|
jobs: Collection<JobRecord>;
|
|
8
|
-
getJobAndLock(jobNames: string[], lockTime: number): Promise<JobToRun>;
|
|
22
|
+
getJobAndLock(jobNames: string[], lockTime: number, hint?: JobAcquisitionHint): Promise<JobToRun>;
|
|
23
|
+
getJobAcquisitionExecutionTime(jobNames: string[], hint: JobAcquisitionHint): Promise<number>;
|
|
9
24
|
setJobRecordPriority(jobId: string, priority: number, lockId?: string): Promise<boolean>;
|
|
10
25
|
scheduleNextRun(options: {
|
|
11
26
|
jobId: string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JobAcquisitionHint } from '../repos/JobsRepo';
|
|
1
2
|
import { JobDefinitionWithName, JobsDefinition } from '../types/JobsDefinition';
|
|
2
3
|
import { StartWorkersConfig } from '../types/StartConfig';
|
|
3
4
|
import { JobToRun, WorkersInstance } from '../types/Worker';
|
|
@@ -13,12 +14,21 @@ interface InternalWorkersInstance extends WorkersInstance {
|
|
|
13
14
|
activeExecutions: Map<string, TrackedExecution>;
|
|
14
15
|
staleExecutions: Map<string, TrackedExecution>;
|
|
15
16
|
runningJobsByName: Map<string, number>;
|
|
17
|
+
jobAcquisitionHint: JobAcquisitionHint;
|
|
18
|
+
jobAcquisitionHintProbeCycle: number;
|
|
19
|
+
hasCompletedInitialJobAcquisitionHintProbe: boolean;
|
|
20
|
+
pendingJobAcquisitionHint?: JobAcquisitionHint;
|
|
21
|
+
pendingJobAcquisitionHintWins: number;
|
|
22
|
+
jobAcquisitionHintProbePromise: Promise<void>;
|
|
23
|
+
jobAcquisitionHintProbeTimer?: ReturnType<typeof setTimeout>;
|
|
24
|
+
cancelJobAcquisitionHintProbeWait?: () => void;
|
|
16
25
|
schedulerPromise: Promise<void>;
|
|
17
26
|
stopSignal: Promise<void>;
|
|
18
27
|
signalStop: () => void;
|
|
19
28
|
stopPromise?: Promise<void>;
|
|
20
29
|
}
|
|
21
30
|
export declare class WorkerService {
|
|
31
|
+
private jobAcquisitionHintProbeIntervalMs;
|
|
22
32
|
private jobsRepo;
|
|
23
33
|
private executor;
|
|
24
34
|
getJobNames(jobs: JobsDefinition): string[];
|
|
@@ -31,6 +41,12 @@ export declare class WorkerService {
|
|
|
31
41
|
waitForPollOrStop(config: StartWorkersConfig, workersInstance: InternalWorkersInstance): Promise<void>;
|
|
32
42
|
waitForCapacityOrStop(workersInstance: InternalWorkersInstance): Promise<void>;
|
|
33
43
|
runSchedulerLoop(config: StartWorkersConfig, workersInstance: InternalWorkersInstance): Promise<void>;
|
|
44
|
+
getOtherJobAcquisitionHint(hint: JobAcquisitionHint): JobAcquisitionHint;
|
|
45
|
+
getMedian(values: number[]): number;
|
|
46
|
+
resetPendingJobAcquisitionHint(workersInstance: InternalWorkersInstance): void;
|
|
47
|
+
runJobAcquisitionHintProbe(config: StartWorkersConfig, workersInstance: InternalWorkersInstance): Promise<void>;
|
|
48
|
+
waitForNextJobAcquisitionHintProbe(workersInstance: InternalWorkersInstance): Promise<void>;
|
|
49
|
+
runJobAcquisitionHintProbeLoop(config: StartWorkersConfig, workersInstance: InternalWorkersInstance): Promise<void>;
|
|
34
50
|
createWorkersInstanceDefinition(config: StartWorkersConfig): InternalWorkersInstance;
|
|
35
51
|
ensureRecords(config: StartWorkersConfig): Promise<void>;
|
|
36
52
|
runScheduler(config: StartWorkersConfig, workersInstance: InternalWorkersInstance): Promise<void>;
|