@orion-js/dogs 4.3.3 → 4.3.5
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 +29 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -3
- package/dist/index.d.ts +26 -3
- package/dist/index.js +29 -22
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -173,7 +173,8 @@ var JobsRepo = class {
|
|
|
173
173
|
status: { $ne: "maxTriesReached" }
|
|
174
174
|
},
|
|
175
175
|
{
|
|
176
|
-
$set: { lockedUntil, lastRunAt: /* @__PURE__ */ new Date() }
|
|
176
|
+
$set: { lockedUntil, lastRunAt: /* @__PURE__ */ new Date() },
|
|
177
|
+
$inc: { tries: 1 }
|
|
177
178
|
},
|
|
178
179
|
{
|
|
179
180
|
mongoOptions: {
|
|
@@ -186,12 +187,10 @@ var JobsRepo = class {
|
|
|
186
187
|
}
|
|
187
188
|
);
|
|
188
189
|
if (!job) return;
|
|
189
|
-
|
|
190
|
+
const tries = (job.tries || 0) + 1;
|
|
190
191
|
const wasStale = Boolean(job.lockedUntil);
|
|
191
192
|
if (wasStale) {
|
|
192
193
|
import_logger.logger.info(`Running job "${job.jobName}" that was staled`);
|
|
193
|
-
await this.jobs.updateOne(job._id, { $inc: { tries: 1 } });
|
|
194
|
-
tries++;
|
|
195
194
|
}
|
|
196
195
|
return {
|
|
197
196
|
jobId: job._id,
|
|
@@ -214,10 +213,9 @@ var JobsRepo = class {
|
|
|
214
213
|
$set: {
|
|
215
214
|
nextRunAt: options.nextRunAt,
|
|
216
215
|
priority: options.priority,
|
|
217
|
-
...options.
|
|
216
|
+
...options.resetTries ? { tries: 0 } : {}
|
|
218
217
|
},
|
|
219
|
-
$unset: { lockedUntil: "" }
|
|
220
|
-
...options.addTries ? { $inc: { tries: 1 } } : {}
|
|
218
|
+
$unset: { lockedUntil: "" }
|
|
221
219
|
};
|
|
222
220
|
await this.jobs.updateOne(options.jobId, updator);
|
|
223
221
|
}
|
|
@@ -355,6 +353,7 @@ JobsRepo = __decorateElement(_init, 0, "JobsRepo", _JobsRepo_decorators, JobsRep
|
|
|
355
353
|
__runInitializers(_init, 1, JobsRepo);
|
|
356
354
|
|
|
357
355
|
// src/services/getNextRunDate.ts
|
|
356
|
+
var import_cron_parser = require("cron-parser");
|
|
358
357
|
var getNextRunDate = (options) => {
|
|
359
358
|
if (options.runIn) {
|
|
360
359
|
return new Date(Date.now() + options.runIn);
|
|
@@ -362,6 +361,15 @@ var getNextRunDate = (options) => {
|
|
|
362
361
|
if (options.runEvery) {
|
|
363
362
|
return new Date(Date.now() + options.runEvery);
|
|
364
363
|
}
|
|
364
|
+
if (options.cron) {
|
|
365
|
+
if (!options.timezone) {
|
|
366
|
+
throw new Error("Cron recurrent jobs require a timezone");
|
|
367
|
+
}
|
|
368
|
+
return import_cron_parser.CronExpressionParser.parse(options.cron, {
|
|
369
|
+
currentDate: options.currentDate ?? /* @__PURE__ */ new Date(),
|
|
370
|
+
tz: options.timezone
|
|
371
|
+
}).next().toDate();
|
|
372
|
+
}
|
|
365
373
|
if (options.runAt) {
|
|
366
374
|
return options.runAt;
|
|
367
375
|
}
|
|
@@ -604,7 +612,7 @@ var Executor = class {
|
|
|
604
612
|
jobId: jobToRun.jobId
|
|
605
613
|
});
|
|
606
614
|
jobLogger.warn(
|
|
607
|
-
`Job "${jobToRun.name}" has
|
|
615
|
+
`Job "${jobToRun.name}" has exceeded max tries (${jobToRun.tries}). Marking as maxTriesReached.`
|
|
608
616
|
);
|
|
609
617
|
await this.jobsRepo.markJobAsMaxTriesReached(jobToRun.jobId);
|
|
610
618
|
try {
|
|
@@ -616,35 +624,26 @@ var Executor = class {
|
|
|
616
624
|
}
|
|
617
625
|
}
|
|
618
626
|
async onError(error, job, jobToRun, context, config) {
|
|
619
|
-
const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries);
|
|
620
627
|
const scheduleRecurrent = async () => {
|
|
621
628
|
if (job.type === "recurrent") {
|
|
622
629
|
await this.jobsRepo.scheduleNextRun({
|
|
623
630
|
jobId: jobToRun.jobId,
|
|
624
631
|
nextRunAt: getNextRunDate(job),
|
|
625
|
-
|
|
632
|
+
resetTries: true,
|
|
626
633
|
priority: job.priority
|
|
627
634
|
});
|
|
628
635
|
}
|
|
629
636
|
};
|
|
630
637
|
const handleRetry = async (nextRunAt) => {
|
|
631
|
-
if (jobToRun.tries >= effectiveMaxTries) {
|
|
632
|
-
await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached);
|
|
633
|
-
return;
|
|
634
|
-
}
|
|
635
638
|
await this.jobsRepo.scheduleNextRun({
|
|
636
639
|
jobId: jobToRun.jobId,
|
|
637
640
|
nextRunAt,
|
|
638
|
-
|
|
641
|
+
resetTries: false,
|
|
639
642
|
priority: job.type === "recurrent" ? job.priority : jobToRun.priority
|
|
640
643
|
});
|
|
641
644
|
};
|
|
642
645
|
if (!job.onError) {
|
|
643
646
|
context.logger.error(`Error executing job "${jobToRun.name}"`, { error });
|
|
644
|
-
if (jobToRun.tries >= effectiveMaxTries) {
|
|
645
|
-
await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached);
|
|
646
|
-
return;
|
|
647
|
-
}
|
|
648
647
|
await scheduleRecurrent();
|
|
649
648
|
return;
|
|
650
649
|
}
|
|
@@ -693,7 +692,7 @@ var Executor = class {
|
|
|
693
692
|
await this.jobsRepo.scheduleNextRun({
|
|
694
693
|
jobId: jobToRun.jobId,
|
|
695
694
|
nextRunAt: getNextRunDate(job),
|
|
696
|
-
|
|
695
|
+
resetTries: true,
|
|
697
696
|
priority: job.priority
|
|
698
697
|
});
|
|
699
698
|
}
|
|
@@ -706,7 +705,7 @@ var Executor = class {
|
|
|
706
705
|
const job = this.getJobDefinition(jobToRun, config.jobs);
|
|
707
706
|
if (!job) return;
|
|
708
707
|
const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries);
|
|
709
|
-
if (jobToRun.
|
|
708
|
+
if (jobToRun.tries > effectiveMaxTries) {
|
|
710
709
|
await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached);
|
|
711
710
|
return;
|
|
712
711
|
}
|
|
@@ -997,6 +996,7 @@ var import_services4 = require("@orion-js/services");
|
|
|
997
996
|
|
|
998
997
|
// src/defineJob/index.ts
|
|
999
998
|
var import_schema3 = require("@orion-js/schema");
|
|
999
|
+
var import_cron_parser2 = require("cron-parser");
|
|
1000
1000
|
var import_parse_duration = __toESM(require("parse-duration"), 1);
|
|
1001
1001
|
function createEventJob(options) {
|
|
1002
1002
|
const jobDefinition = {
|
|
@@ -1035,11 +1035,18 @@ function createEventJob(options) {
|
|
|
1035
1035
|
return jobDefinition;
|
|
1036
1036
|
}
|
|
1037
1037
|
function createRecurrentJob(options) {
|
|
1038
|
+
if ("cron" in options && options.cron && !options.timezone) {
|
|
1039
|
+
throw new Error("Cron recurrent jobs require a timezone");
|
|
1040
|
+
}
|
|
1041
|
+
if ("cron" in options && options.cron) {
|
|
1042
|
+
import_cron_parser2.CronExpressionParser.parse(options.cron, { tz: options.timezone }).next();
|
|
1043
|
+
}
|
|
1044
|
+
const runEvery = "runEvery" in options ? typeof options.runEvery === "string" ? (0, import_parse_duration.default)(options.runEvery) : options.runEvery : void 0;
|
|
1038
1045
|
const jobDefinition = {
|
|
1039
1046
|
...options,
|
|
1040
1047
|
priority: options.priority ?? 100,
|
|
1041
1048
|
type: "recurrent",
|
|
1042
|
-
runEvery
|
|
1049
|
+
runEvery
|
|
1043
1050
|
};
|
|
1044
1051
|
return jobDefinition;
|
|
1045
1052
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/services/EventsService.ts","../src/repos/JobsRepo.ts","../src/types/JobRecord.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 {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 })\n jobs: Collection<JobRecord>\n\n async getJobAndLock(jobNames: string[], lockTime: number): Promise<JobToRun> {\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 $or: [{lockedUntil: {$exists: false}}, {lockedUntil: {$lte: new Date()}}],\n // Exclude jobs that have reached max tries. Using $ne handles backwards compatibility\n // since records without the status field will still match (undefined !== 'maxTriesReached')\n status: {$ne: 'maxTriesReached'},\n },\n {\n $set: {lockedUntil, lastRunAt: new Date()},\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 let tries = job.tries || 1\n const wasStale = Boolean(job.lockedUntil)\n\n if (wasStale) {\n logger.info(`Running job \"${job.jobName}\" that was staled`)\n await this.jobs.updateOne(job._id, {$inc: {tries: 1}})\n tries++\n }\n\n return {\n jobId: job._id,\n executionId: generateId(),\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) {\n await this.jobs.updateOne(jobId, {$set: {priority}})\n }\n\n async scheduleNextRun(options: {\n jobId: string\n nextRunAt: Date\n addTries: boolean\n priority: number\n }) {\n const updator: MongoDB.UpdateFilter<JobRecord> = {\n $set: {\n nextRunAt: options.nextRunAt,\n priority: options.priority,\n ...(options.addTries ? {} : {tries: 0}),\n },\n $unset: {lockedUntil: ''},\n ...(options.addTries ? {$inc: {tries: 1}} : {}),\n }\n\n await this.jobs.updateOne(options.jobId, updator)\n }\n\n async deleteEventJob(jobId: string) {\n await this.jobs.deleteOne({_id: jobId, type: 'event'})\n }\n\n /**\n * Marks a job as having reached its maximum tries limit.\n * The job will remain in the database but won't be picked up for execution.\n */\n async markJobAsMaxTriesReached(jobId: string) {\n await this.jobs.updateOne(\n {_id: jobId},\n {\n $set: {status: 'maxTriesReached'},\n $unset: {lockedUntil: ''},\n },\n )\n }\n\n async extendLockTime(jobId: string, extraTime: number) {\n await this.updateLockTime(jobId, extraTime)\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) {\n const lockedUntil = new Date(Date.now() + lockDuration)\n await this.jobs.updateOne(\n {\n _id: jobId,\n },\n {\n $set: {lockedUntil},\n },\n )\n }\n\n async unlockAllJobs(): Promise<number> {\n const result = await this.jobs.updateMany(\n {\n lockedUntil: {$exists: true},\n },\n {\n $unset: {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 $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': 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 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\nexport type JobRecord = InferSchemaType<typeof JobRecordSchema>\n","export type Options = {\n getNextRun?: () => Date\n runIn?: number\n runEvery?: number\n runAt?: Date\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.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 {StartWorkersConfig} from '../types/StartConfig'\nimport {JobToRun, WorkerInstance, WorkersInstance} from '../types/Worker'\nimport {ExecuteJobConfig, Executor} from './Executor'\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: WorkersInstance,\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: WorkersInstance, jobName: string) {\n const currentExecutions = workersInstance.runningJobsByName.get(jobName) || 0\n workersInstance.runningJobsByName.set(jobName, currentExecutions + 1)\n }\n\n releaseJobExecution(workersInstance: WorkersInstance, 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 async withJobAcquisitionLock<T>(workersInstance: WorkersInstance, callback: () => Promise<T>) {\n const previousLock = workersInstance.jobAcquisitionLock\n let releaseLock!: () => void\n workersInstance.jobAcquisitionLock = new Promise<void>(resolve => {\n releaseLock = resolve\n })\n\n await previousLock\n\n try {\n return await callback()\n } finally {\n releaseLock()\n }\n }\n\n async getJobAndReserveExecution(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n jobNames: string[],\n ): Promise<JobToRun | undefined> {\n return this.withJobAcquisitionLock(workersInstance, async () => {\n const availableJobNames = this.getAvailableJobNames(config, workersInstance, jobNames)\n if (availableJobNames.length === 0) return\n\n const jobToRun = await this.jobsRepo.getJobAndLock(availableJobNames, config.defaultLockTime)\n if (!jobToRun) return\n\n this.reserveJobExecution(workersInstance, jobToRun.name)\n return jobToRun\n })\n }\n\n async runWorkerLoop(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n workerInstance: WorkerInstance,\n jobNames: string[],\n executeConfig: ExecuteJobConfig,\n ) {\n const jobToRun = await this.getJobAndReserveExecution(config, workersInstance, jobNames)\n if (!jobToRun) {\n logger.debug('No job to run')\n return false\n }\n\n logger.debug(`Got job [w${workerInstance.workerIndex}] to run:`, jobToRun)\n\n try {\n await this.executor.executeJob(executeConfig, jobToRun, workerInstance.respawn)\n } finally {\n this.releaseJobExecution(workersInstance, jobToRun.name)\n }\n\n return true\n }\n\n async startWorker(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n workerInstance: WorkerInstance,\n ) {\n const names = this.getJobNames(config.jobs)\n logger.debug(\n `Running worker loop [w${workerInstance.workerIndex}] for jobs \"${names.join(', ')}\"...`,\n )\n const executeConfig: ExecuteJobConfig = {\n jobs: config.jobs,\n maxTries: config.maxTries,\n onMaxTriesReached: config.onMaxTriesReached,\n }\n\n while (true) {\n if (!workerInstance.running) {\n logger.info(`Got signal to stop. Stopping worker [w${workerInstance.workerIndex}]...`)\n return\n }\n\n try {\n const didRun = await this.runWorkerLoop(\n config,\n workersInstance,\n workerInstance,\n names,\n executeConfig,\n )\n if (!didRun) await sleep(config.pollInterval)\n if (didRun) await sleep(config.cooldownPeriod)\n } catch (error) {\n logger.error('Error in job runner.', {error})\n await sleep(config.pollInterval)\n }\n }\n }\n\n createWorkersInstanceDefinition(config: StartWorkersConfig): WorkersInstance {\n const workersInstance: WorkersInstance = {\n running: true,\n workersCount: config.workersCount,\n workers: [],\n runningJobsByName: new Map(),\n jobAcquisitionLock: Promise.resolve(),\n stop: async () => {\n logger.info('Stopping workers...')\n workersInstance.running = false\n const stopingPromises = workersInstance.workers.map(worker => worker.stop())\n await Promise.all(stopingPromises)\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 startANewWorker(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n workerIndex = workersInstance.workers.length,\n ) {\n if (!workersInstance.running) {\n return\n }\n\n const workerInstance: WorkerInstance = {\n running: true,\n workerIndex,\n stop: async () => {\n logger.info(`Stopping worker [w${workerIndex}]...`)\n workerInstance.running = false\n await workerInstance.promise\n },\n respawn: async () => {\n logger.info(`Respawning worker [w${workerIndex}]...`)\n workerInstance.running = false\n await this.startANewWorker(config, workersInstance, workerIndex)\n },\n }\n\n const workerPromise = this.startWorker(config, workersInstance, workerInstance)\n\n workerInstance.promise = workerPromise\n workersInstance.workers[workerIndex] = workerInstance\n }\n\n async runWorkers(config: StartWorkersConfig, workersInstance: WorkersInstance) {\n logger.debug('Will ensure records for recurrent jobs')\n await this.ensureRecords(config)\n\n const workersCount = config.workersCount\n const workerWord = workersCount === 1 ? 'worker' : 'workers'\n logger.info(`Starting ${workersCount} ${workerWord}`)\n\n for (let workerIndex = 0; workerIndex < workersCount; workerIndex++) {\n this.startANewWorker(config, workersInstance, workerIndex)\n }\n }\n\n /**\n * Starts the job workers with the provided configuration.\n * @param userConfig - Configuration for the workers. Required fields: jobs, maxTries, onMaxTriesReached\n */\n startWorkers(userConfig: StartWorkersConfig): WorkersInstance {\n // Apply defaults for optional fields\n const config: StartWorkersConfig = {\n cooldownPeriod: 100,\n pollInterval: 3000,\n workersCount: 4,\n defaultLockTime: 30 * 1000,\n ...userConfig,\n }\n\n setNameToJobs(config.jobs)\n\n const workersInstance = this.createWorkersInstanceDefinition(config)\n logger.debug('Starting workers', config)\n\n this.runWorkers(config, workersInstance)\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 {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 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(job: JobDefinition, jobToRun: JobToRun, onStale: Function): ExecutionContext {\n const effectiveLockTime = this.getEffectiveLockTime(job, jobToRun)\n let staleTimeout = setTimeout(() => onStale(), effectiveLockTime)\n staleTimeout.unref?.()\n return {\n definition: job,\n record: jobToRun,\n tries: jobToRun.tries || 0,\n clearStaleTimeout: () => clearTimeout(staleTimeout),\n extendLockTime: async (extraTime: number) => {\n clearTimeout(staleTimeout)\n staleTimeout = setTimeout(() => onStale(), extraTime)\n staleTimeout.unref?.()\n await this.jobsRepo.extendLockTime(jobToRun.jobId, extraTime)\n },\n logger: logger.addMetadata({\n jobName: jobToRun.name,\n jobId: jobToRun.jobId,\n }),\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 a job.\n * Job-specific maxTries takes precedence over the global maxTries from config.\n */\n getEffectiveMaxTries(job: JobDefinition, globalMaxTries: number): number {\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.\n */\n async handleMaxTriesReached(\n jobToRun: JobToRun,\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 reached max tries (${jobToRun.tries}). Marking as maxTriesReached.`,\n )\n await this.jobsRepo.markJobAsMaxTriesReached(jobToRun.jobId)\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\n async onError(\n error: unknown,\n job: JobDefinition,\n jobToRun: JobToRun,\n context: ExecutionContext,\n config: ExecuteJobConfig,\n ) {\n const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries)\n\n // Helper to schedule next run for recurrent jobs (used when dismissing)\n const scheduleRecurrent = async () => {\n if (job.type === 'recurrent') {\n await this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt: getNextRunDate(job),\n addTries: false,\n priority: job.priority,\n })\n }\n }\n\n // Helper to handle retry with max tries check\n const handleRetry = async (nextRunAt: Date) => {\n // Check if we've reached max tries before scheduling another retry\n if (jobToRun.tries >= effectiveMaxTries) {\n await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached)\n return\n }\n\n await this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt,\n addTries: true,\n priority: job.type === 'recurrent' ? job.priority : jobToRun.priority,\n })\n }\n\n // If no custom error handler, check max tries and schedule recurrent if applicable\n if (!job.onError) {\n context.logger.error(`Error executing job \"${jobToRun.name}\"`, {error})\n\n // For jobs without onError, check if max tries reached\n if (jobToRun.tries >= effectiveMaxTries) {\n await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached)\n return\n }\n\n await scheduleRecurrent()\n return\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 await scheduleRecurrent()\n return\n }\n\n if (result.action === 'retry') {\n await handleRetry(getNextRunDate(result))\n }\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 await this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt: getNextRunDate(job),\n addTries: false,\n priority: job.priority,\n })\n }\n if (job.type === 'event') {\n context.logger.debug(`Removing event job after success \"${jobToRun.name}\"`)\n await this.jobsRepo.deleteEventJob(jobToRun.jobId)\n }\n }\n\n async executeJob(config: ExecuteJobConfig, jobToRun: JobToRun, respawnWorker: () => void) {\n const job = this.getJobDefinition(jobToRun, config.jobs)\n if (!job) return\n\n const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries)\n if (jobToRun.wasStale && jobToRun.tries >= effectiveMaxTries) {\n await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached)\n return\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 await this.jobsRepo.updateLockTime(jobToRun.jobId, effectiveLockTime)\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\n const onStale = async () => {\n if (job.onStale) {\n context.logger.info(`Job \"${jobToRun.name}\" is stale`)\n job.onStale(jobToRun.params, context)\n } else {\n context.logger.error(`Job \"${jobToRun.name}\" is stale`)\n }\n\n await this.jobsRepo.setJobRecordPriority(jobToRun.jobId, 0)\n\n void respawnWorker()\n\n void this.saveExecution({\n startedAt,\n status: 'stale',\n result: null,\n errorMessage: null,\n job,\n jobToRun,\n }).catch(error => {\n context.logger.error('Error saving stale execution history', {error})\n })\n }\n\n const context = this.getContext(job, jobToRun, onStale)\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 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\n await this.afterExecutionSuccess(job, jobToRun, context)\n } catch (error) {\n context.clearStaleTimeout()\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 await this.onError(error, job, jobToRun, context, config)\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 {\n CreateEventJobOptions,\n CreateJobOptions,\n CreateRecurrentJobOptions,\n EventJobDefinition,\n JobDefinition,\n RecurrentJobDefinition,\n} from '../types/JobsDefinition'\nimport {scheduleJob, ScheduleJobsResult, scheduleJobs} from '..'\nimport {ScheduleJobOptionsWithoutName} from '../types/Events'\nimport {cleanAndValidate, SchemaInAnyOrionForm} from '@orion-js/schema'\nimport parse from 'parse-duration'\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 (scheduleOptions: ScheduleJobOptionsWithoutName<TParamsSchema>) => {\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 jobDefinition: RecurrentJobDefinition = {\n ...options,\n priority: options.priority ?? 100,\n type: 'recurrent',\n runEvery: typeof options.runEvery === 'string' ? parse(options.runEvery) : options.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":["import_services","import_logger","_init","import_helpers","import_logger","import_services","import_logger","import_services","import_mongodb","import_schema","_init","_jobsRepo_dec","_init","_a","_jobsRepo_dec","_init","import_services","import_schema","parse"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/services/EventsService.ts","../src/repos/JobsRepo.ts","../src/types/JobRecord.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 {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 })\n jobs: Collection<JobRecord>\n\n async getJobAndLock(jobNames: string[], lockTime: number): Promise<JobToRun> {\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 $or: [{lockedUntil: {$exists: false}}, {lockedUntil: {$lte: new Date()}}],\n // Exclude jobs that have reached max tries. Using $ne handles backwards compatibility\n // since records without the status field will still match (undefined !== 'maxTriesReached')\n status: {$ne: 'maxTriesReached'},\n },\n {\n $set: {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: generateId(),\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) {\n await this.jobs.updateOne(jobId, {$set: {priority}})\n }\n\n async scheduleNextRun(options: {\n jobId: string\n nextRunAt: Date\n resetTries: boolean\n priority: number\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: {lockedUntil: ''},\n }\n\n await this.jobs.updateOne(options.jobId, updator)\n }\n\n async deleteEventJob(jobId: string) {\n await this.jobs.deleteOne({_id: jobId, type: 'event'})\n }\n\n /**\n * Marks a job as having reached its maximum tries limit.\n * The job will remain in the database but won't be picked up for execution.\n */\n async markJobAsMaxTriesReached(jobId: string) {\n await this.jobs.updateOne(\n {_id: jobId},\n {\n $set: {status: 'maxTriesReached'},\n $unset: {lockedUntil: ''},\n },\n )\n }\n\n async extendLockTime(jobId: string, extraTime: number) {\n await this.updateLockTime(jobId, extraTime)\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) {\n const lockedUntil = new Date(Date.now() + lockDuration)\n await this.jobs.updateOne(\n {\n _id: jobId,\n },\n {\n $set: {lockedUntil},\n },\n )\n }\n\n async unlockAllJobs(): Promise<number> {\n const result = await this.jobs.updateMany(\n {\n lockedUntil: {$exists: true},\n },\n {\n $unset: {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 $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': 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 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\nexport type JobRecord = InferSchemaType<typeof JobRecordSchema>\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 {StartWorkersConfig} from '../types/StartConfig'\nimport {JobToRun, WorkerInstance, WorkersInstance} from '../types/Worker'\nimport {ExecuteJobConfig, Executor} from './Executor'\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: WorkersInstance,\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: WorkersInstance, jobName: string) {\n const currentExecutions = workersInstance.runningJobsByName.get(jobName) || 0\n workersInstance.runningJobsByName.set(jobName, currentExecutions + 1)\n }\n\n releaseJobExecution(workersInstance: WorkersInstance, 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 async withJobAcquisitionLock<T>(workersInstance: WorkersInstance, callback: () => Promise<T>) {\n const previousLock = workersInstance.jobAcquisitionLock\n let releaseLock!: () => void\n workersInstance.jobAcquisitionLock = new Promise<void>(resolve => {\n releaseLock = resolve\n })\n\n await previousLock\n\n try {\n return await callback()\n } finally {\n releaseLock()\n }\n }\n\n async getJobAndReserveExecution(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n jobNames: string[],\n ): Promise<JobToRun | undefined> {\n return this.withJobAcquisitionLock(workersInstance, async () => {\n const availableJobNames = this.getAvailableJobNames(config, workersInstance, jobNames)\n if (availableJobNames.length === 0) return\n\n const jobToRun = await this.jobsRepo.getJobAndLock(availableJobNames, config.defaultLockTime)\n if (!jobToRun) return\n\n this.reserveJobExecution(workersInstance, jobToRun.name)\n return jobToRun\n })\n }\n\n async runWorkerLoop(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n workerInstance: WorkerInstance,\n jobNames: string[],\n executeConfig: ExecuteJobConfig,\n ) {\n const jobToRun = await this.getJobAndReserveExecution(config, workersInstance, jobNames)\n if (!jobToRun) {\n logger.debug('No job to run')\n return false\n }\n\n logger.debug(`Got job [w${workerInstance.workerIndex}] to run:`, jobToRun)\n\n try {\n await this.executor.executeJob(executeConfig, jobToRun, workerInstance.respawn)\n } finally {\n this.releaseJobExecution(workersInstance, jobToRun.name)\n }\n\n return true\n }\n\n async startWorker(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n workerInstance: WorkerInstance,\n ) {\n const names = this.getJobNames(config.jobs)\n logger.debug(\n `Running worker loop [w${workerInstance.workerIndex}] for jobs \"${names.join(', ')}\"...`,\n )\n const executeConfig: ExecuteJobConfig = {\n jobs: config.jobs,\n maxTries: config.maxTries,\n onMaxTriesReached: config.onMaxTriesReached,\n }\n\n while (true) {\n if (!workerInstance.running) {\n logger.info(`Got signal to stop. Stopping worker [w${workerInstance.workerIndex}]...`)\n return\n }\n\n try {\n const didRun = await this.runWorkerLoop(\n config,\n workersInstance,\n workerInstance,\n names,\n executeConfig,\n )\n if (!didRun) await sleep(config.pollInterval)\n if (didRun) await sleep(config.cooldownPeriod)\n } catch (error) {\n logger.error('Error in job runner.', {error})\n await sleep(config.pollInterval)\n }\n }\n }\n\n createWorkersInstanceDefinition(config: StartWorkersConfig): WorkersInstance {\n const workersInstance: WorkersInstance = {\n running: true,\n workersCount: config.workersCount,\n workers: [],\n runningJobsByName: new Map(),\n jobAcquisitionLock: Promise.resolve(),\n stop: async () => {\n logger.info('Stopping workers...')\n workersInstance.running = false\n const stopingPromises = workersInstance.workers.map(worker => worker.stop())\n await Promise.all(stopingPromises)\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 startANewWorker(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n workerIndex = workersInstance.workers.length,\n ) {\n if (!workersInstance.running) {\n return\n }\n\n const workerInstance: WorkerInstance = {\n running: true,\n workerIndex,\n stop: async () => {\n logger.info(`Stopping worker [w${workerIndex}]...`)\n workerInstance.running = false\n await workerInstance.promise\n },\n respawn: async () => {\n logger.info(`Respawning worker [w${workerIndex}]...`)\n workerInstance.running = false\n await this.startANewWorker(config, workersInstance, workerIndex)\n },\n }\n\n const workerPromise = this.startWorker(config, workersInstance, workerInstance)\n\n workerInstance.promise = workerPromise\n workersInstance.workers[workerIndex] = workerInstance\n }\n\n async runWorkers(config: StartWorkersConfig, workersInstance: WorkersInstance) {\n logger.debug('Will ensure records for recurrent jobs')\n await this.ensureRecords(config)\n\n const workersCount = config.workersCount\n const workerWord = workersCount === 1 ? 'worker' : 'workers'\n logger.info(`Starting ${workersCount} ${workerWord}`)\n\n for (let workerIndex = 0; workerIndex < workersCount; workerIndex++) {\n this.startANewWorker(config, workersInstance, workerIndex)\n }\n }\n\n /**\n * Starts the job workers with the provided configuration.\n * @param userConfig - Configuration for the workers. Required fields: jobs, maxTries, onMaxTriesReached\n */\n startWorkers(userConfig: StartWorkersConfig): WorkersInstance {\n // Apply defaults for optional fields\n const config: StartWorkersConfig = {\n cooldownPeriod: 100,\n pollInterval: 3000,\n workersCount: 4,\n defaultLockTime: 30 * 1000,\n ...userConfig,\n }\n\n setNameToJobs(config.jobs)\n\n const workersInstance = this.createWorkersInstanceDefinition(config)\n logger.debug('Starting workers', config)\n\n this.runWorkers(config, workersInstance)\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 {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 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(job: JobDefinition, jobToRun: JobToRun, onStale: Function): ExecutionContext {\n const effectiveLockTime = this.getEffectiveLockTime(job, jobToRun)\n let staleTimeout = setTimeout(() => onStale(), effectiveLockTime)\n staleTimeout.unref?.()\n return {\n definition: job,\n record: jobToRun,\n tries: jobToRun.tries || 0,\n clearStaleTimeout: () => clearTimeout(staleTimeout),\n extendLockTime: async (extraTime: number) => {\n clearTimeout(staleTimeout)\n staleTimeout = setTimeout(() => onStale(), extraTime)\n staleTimeout.unref?.()\n await this.jobsRepo.extendLockTime(jobToRun.jobId, extraTime)\n },\n logger: logger.addMetadata({\n jobName: jobToRun.name,\n jobId: jobToRun.jobId,\n }),\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 a job.\n * Job-specific maxTries takes precedence over the global maxTries from config.\n */\n getEffectiveMaxTries(job: JobDefinition, globalMaxTries: number): number {\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.\n */\n async handleMaxTriesReached(\n jobToRun: JobToRun,\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 await this.jobsRepo.markJobAsMaxTriesReached(jobToRun.jobId)\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\n async onError(\n error: unknown,\n job: JobDefinition,\n jobToRun: JobToRun,\n context: ExecutionContext,\n config: ExecuteJobConfig,\n ) {\n // Helper to schedule next run for recurrent jobs (used when dismissing)\n const scheduleRecurrent = async () => {\n if (job.type === 'recurrent') {\n await this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt: getNextRunDate(job),\n resetTries: true,\n priority: job.priority,\n })\n }\n }\n\n const handleRetry = async (nextRunAt: Date) => {\n await this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt,\n resetTries: false,\n priority: job.type === 'recurrent' ? job.priority : jobToRun.priority,\n })\n }\n\n if (!job.onError) {\n context.logger.error(`Error executing job \"${jobToRun.name}\"`, {error})\n\n await scheduleRecurrent()\n return\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 await scheduleRecurrent()\n return\n }\n\n if (result.action === 'retry') {\n await handleRetry(getNextRunDate(result))\n }\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 await this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt: getNextRunDate(job),\n resetTries: true,\n priority: job.priority,\n })\n }\n if (job.type === 'event') {\n context.logger.debug(`Removing event job after success \"${jobToRun.name}\"`)\n await this.jobsRepo.deleteEventJob(jobToRun.jobId)\n }\n }\n\n async executeJob(config: ExecuteJobConfig, jobToRun: JobToRun, respawnWorker: () => void) {\n const job = this.getJobDefinition(jobToRun, config.jobs)\n if (!job) return\n\n const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries)\n if (jobToRun.tries > effectiveMaxTries) {\n await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached)\n return\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 await this.jobsRepo.updateLockTime(jobToRun.jobId, effectiveLockTime)\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\n const onStale = async () => {\n if (job.onStale) {\n context.logger.info(`Job \"${jobToRun.name}\" is stale`)\n job.onStale(jobToRun.params, context)\n } else {\n context.logger.error(`Job \"${jobToRun.name}\" is stale`)\n }\n\n await this.jobsRepo.setJobRecordPriority(jobToRun.jobId, 0)\n\n void respawnWorker()\n\n void this.saveExecution({\n startedAt,\n status: 'stale',\n result: null,\n errorMessage: null,\n job,\n jobToRun,\n }).catch(error => {\n context.logger.error('Error saving stale execution history', {error})\n })\n }\n\n const context = this.getContext(job, jobToRun, onStale)\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 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\n await this.afterExecutionSuccess(job, jobToRun, context)\n } catch (error) {\n context.clearStaleTimeout()\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 await this.onError(error, job, jobToRun, context, config)\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 if ('cron' in options && options.cron && !options.timezone) {\n throw new Error('Cron recurrent jobs require a timezone')\n }\n\n if ('cron' in options && options.cron) {\n CronExpressionParser.parse(options.cron, {tz: options.timezone}).next()\n }\n\n const runEvery =\n 'runEvery' in options\n ? typeof options.runEvery === 'string'\n ? parse(options.runEvery)\n : options.runEvery\n : undefined\n\n const jobDefinition: RecurrentJobDefinition = {\n ...options,\n priority: options.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":["import_services","import_logger","_init","import_helpers","import_logger","import_services","import_logger","import_services","import_mongodb","import_schema","_init","_jobsRepo_dec","_init","_a","_jobsRepo_dec","_init","import_services","import_schema","import_cron_parser","parse"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -269,6 +269,14 @@ interface RecurrentJobDefinition extends BaseJobDefinition {
|
|
|
269
269
|
* Run every x milliseconds. This will be ignored if getNextRun is defined.
|
|
270
270
|
*/
|
|
271
271
|
runEvery?: number;
|
|
272
|
+
/**
|
|
273
|
+
* Cron expression used to calculate the next run. Requires timezone.
|
|
274
|
+
*/
|
|
275
|
+
cron?: string;
|
|
276
|
+
/**
|
|
277
|
+
* IANA timezone used to calculate cron-based schedules.
|
|
278
|
+
*/
|
|
279
|
+
timezone?: string;
|
|
272
280
|
/**
|
|
273
281
|
* The priority of the job. Higher is more priority. Default is 100.
|
|
274
282
|
*/
|
|
@@ -306,13 +314,28 @@ interface EventJobDefinition<TParamsSchema extends SchemaInAnyOrionForm = any> e
|
|
|
306
314
|
resolve: (params: InferSchemaType<TParamsSchema>, context: ExecutionContext) => Promise<any>;
|
|
307
315
|
}
|
|
308
316
|
type CreateEventJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = Omit<EventJobDefinition<TParamsSchema>, 'type' | 'schedule' | 'scheduleJobs'>;
|
|
309
|
-
type
|
|
317
|
+
type CreateRecurrentJobBaseOptions = Omit<RecurrentJobDefinition, 'type' | 'runEvery' | 'cron' | 'timezone'>;
|
|
318
|
+
type CreateRecurrentJobRunEveryOptions = CreateRecurrentJobBaseOptions & {
|
|
310
319
|
/**
|
|
311
320
|
* Run every x milliseconds.
|
|
312
321
|
* Accepts https://github.com/jkroso/parse-duration strings.
|
|
313
322
|
*/
|
|
314
323
|
runEvery: number | string;
|
|
324
|
+
cron?: never;
|
|
325
|
+
timezone?: string;
|
|
326
|
+
};
|
|
327
|
+
type CreateRecurrentJobCronOptions = CreateRecurrentJobBaseOptions & {
|
|
328
|
+
/**
|
|
329
|
+
* Cron expression used to calculate the next run.
|
|
330
|
+
*/
|
|
331
|
+
cron: string;
|
|
332
|
+
/**
|
|
333
|
+
* IANA timezone used to calculate cron-based schedules.
|
|
334
|
+
*/
|
|
335
|
+
timezone: string;
|
|
336
|
+
runEvery?: never;
|
|
315
337
|
};
|
|
338
|
+
type CreateRecurrentJobOptions = CreateRecurrentJobRunEveryOptions | CreateRecurrentJobCronOptions;
|
|
316
339
|
type CreateJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = CreateEventJobOptions<TParamsSchema> | CreateRecurrentJobOptions;
|
|
317
340
|
type JobDefinition<TParamsSchema extends SchemaInAnyOrionForm = any> = RecurrentJobDefinition | EventJobDefinition<TParamsSchema>;
|
|
318
341
|
type JobDefinitionWithName<TParamsSchema extends SchemaInAnyOrionForm = any> = JobDefinition<TParamsSchema> & {
|
|
@@ -375,7 +398,7 @@ declare class JobsRepo {
|
|
|
375
398
|
scheduleNextRun(options: {
|
|
376
399
|
jobId: string;
|
|
377
400
|
nextRunAt: Date;
|
|
378
|
-
|
|
401
|
+
resetTries: boolean;
|
|
379
402
|
priority: number;
|
|
380
403
|
}): Promise<void>;
|
|
381
404
|
deleteEventJob(jobId: string): Promise<void>;
|
|
@@ -427,4 +450,4 @@ declare const scheduleJob: <TParamsSchema extends SchemaInAnyOrionForm = any>(op
|
|
|
427
450
|
*/
|
|
428
451
|
declare const scheduleJobs: <TParamsSchema extends SchemaInAnyOrionForm = any>(jobs: ScheduleJobsOptions<TParamsSchema>) => Promise<ScheduleJobsResult>;
|
|
429
452
|
|
|
430
|
-
export { type BaseJobDefinition, type CreateEventJobOptions, type CreateJobOptions, type CreateRecurrentJobOptions, EventJob, type EventJobDefinition, type ExecutionContext, type HistoryRecord, HistoryRecordSchema, type JobDefinition, type JobDefinitionWithName, type JobRecord, JobRecordSchema, type JobRetryResult, type JobRetryResultBase, type JobRetryResultRunAt, type JobRetryResultRunIn, JobStatusEnum, type JobToRun, Jobs, type JobsDefinition, type LogLevels, RecurrentJob, type RecurrentJobDefinition, type ScheduleJobOptions, type ScheduleJobOptionsBase, type ScheduleJobOptionsRunAt, type ScheduleJobOptionsRunIn, type ScheduleJobOptionsWithoutName, type ScheduleJobRecordOptions, type ScheduleJobsOptions, type ScheduleJobsResult, type StartWorkersConfig, type WorkerInstance, type WorkersInstance, createEventJob, createRecurrentJob, defineJob, getServiceJobs, jobsHistoryRepo, jobsRepo, scheduleJob, scheduleJobs, startWorkers };
|
|
453
|
+
export { type BaseJobDefinition, type CreateEventJobOptions, type CreateJobOptions, type CreateRecurrentJobCronOptions, type CreateRecurrentJobOptions, type CreateRecurrentJobRunEveryOptions, EventJob, type EventJobDefinition, type ExecutionContext, type HistoryRecord, HistoryRecordSchema, type JobDefinition, type JobDefinitionWithName, type JobRecord, JobRecordSchema, type JobRetryResult, type JobRetryResultBase, type JobRetryResultRunAt, type JobRetryResultRunIn, JobStatusEnum, type JobToRun, Jobs, type JobsDefinition, type LogLevels, RecurrentJob, type RecurrentJobDefinition, type ScheduleJobOptions, type ScheduleJobOptionsBase, type ScheduleJobOptionsRunAt, type ScheduleJobOptionsRunIn, type ScheduleJobOptionsWithoutName, type ScheduleJobRecordOptions, type ScheduleJobsOptions, type ScheduleJobsResult, type StartWorkersConfig, type WorkerInstance, type WorkersInstance, createEventJob, createRecurrentJob, defineJob, getServiceJobs, jobsHistoryRepo, jobsRepo, scheduleJob, scheduleJobs, startWorkers };
|
package/dist/index.d.ts
CHANGED
|
@@ -269,6 +269,14 @@ interface RecurrentJobDefinition extends BaseJobDefinition {
|
|
|
269
269
|
* Run every x milliseconds. This will be ignored if getNextRun is defined.
|
|
270
270
|
*/
|
|
271
271
|
runEvery?: number;
|
|
272
|
+
/**
|
|
273
|
+
* Cron expression used to calculate the next run. Requires timezone.
|
|
274
|
+
*/
|
|
275
|
+
cron?: string;
|
|
276
|
+
/**
|
|
277
|
+
* IANA timezone used to calculate cron-based schedules.
|
|
278
|
+
*/
|
|
279
|
+
timezone?: string;
|
|
272
280
|
/**
|
|
273
281
|
* The priority of the job. Higher is more priority. Default is 100.
|
|
274
282
|
*/
|
|
@@ -306,13 +314,28 @@ interface EventJobDefinition<TParamsSchema extends SchemaInAnyOrionForm = any> e
|
|
|
306
314
|
resolve: (params: InferSchemaType<TParamsSchema>, context: ExecutionContext) => Promise<any>;
|
|
307
315
|
}
|
|
308
316
|
type CreateEventJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = Omit<EventJobDefinition<TParamsSchema>, 'type' | 'schedule' | 'scheduleJobs'>;
|
|
309
|
-
type
|
|
317
|
+
type CreateRecurrentJobBaseOptions = Omit<RecurrentJobDefinition, 'type' | 'runEvery' | 'cron' | 'timezone'>;
|
|
318
|
+
type CreateRecurrentJobRunEveryOptions = CreateRecurrentJobBaseOptions & {
|
|
310
319
|
/**
|
|
311
320
|
* Run every x milliseconds.
|
|
312
321
|
* Accepts https://github.com/jkroso/parse-duration strings.
|
|
313
322
|
*/
|
|
314
323
|
runEvery: number | string;
|
|
324
|
+
cron?: never;
|
|
325
|
+
timezone?: string;
|
|
326
|
+
};
|
|
327
|
+
type CreateRecurrentJobCronOptions = CreateRecurrentJobBaseOptions & {
|
|
328
|
+
/**
|
|
329
|
+
* Cron expression used to calculate the next run.
|
|
330
|
+
*/
|
|
331
|
+
cron: string;
|
|
332
|
+
/**
|
|
333
|
+
* IANA timezone used to calculate cron-based schedules.
|
|
334
|
+
*/
|
|
335
|
+
timezone: string;
|
|
336
|
+
runEvery?: never;
|
|
315
337
|
};
|
|
338
|
+
type CreateRecurrentJobOptions = CreateRecurrentJobRunEveryOptions | CreateRecurrentJobCronOptions;
|
|
316
339
|
type CreateJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = CreateEventJobOptions<TParamsSchema> | CreateRecurrentJobOptions;
|
|
317
340
|
type JobDefinition<TParamsSchema extends SchemaInAnyOrionForm = any> = RecurrentJobDefinition | EventJobDefinition<TParamsSchema>;
|
|
318
341
|
type JobDefinitionWithName<TParamsSchema extends SchemaInAnyOrionForm = any> = JobDefinition<TParamsSchema> & {
|
|
@@ -375,7 +398,7 @@ declare class JobsRepo {
|
|
|
375
398
|
scheduleNextRun(options: {
|
|
376
399
|
jobId: string;
|
|
377
400
|
nextRunAt: Date;
|
|
378
|
-
|
|
401
|
+
resetTries: boolean;
|
|
379
402
|
priority: number;
|
|
380
403
|
}): Promise<void>;
|
|
381
404
|
deleteEventJob(jobId: string): Promise<void>;
|
|
@@ -427,4 +450,4 @@ declare const scheduleJob: <TParamsSchema extends SchemaInAnyOrionForm = any>(op
|
|
|
427
450
|
*/
|
|
428
451
|
declare const scheduleJobs: <TParamsSchema extends SchemaInAnyOrionForm = any>(jobs: ScheduleJobsOptions<TParamsSchema>) => Promise<ScheduleJobsResult>;
|
|
429
452
|
|
|
430
|
-
export { type BaseJobDefinition, type CreateEventJobOptions, type CreateJobOptions, type CreateRecurrentJobOptions, EventJob, type EventJobDefinition, type ExecutionContext, type HistoryRecord, HistoryRecordSchema, type JobDefinition, type JobDefinitionWithName, type JobRecord, JobRecordSchema, type JobRetryResult, type JobRetryResultBase, type JobRetryResultRunAt, type JobRetryResultRunIn, JobStatusEnum, type JobToRun, Jobs, type JobsDefinition, type LogLevels, RecurrentJob, type RecurrentJobDefinition, type ScheduleJobOptions, type ScheduleJobOptionsBase, type ScheduleJobOptionsRunAt, type ScheduleJobOptionsRunIn, type ScheduleJobOptionsWithoutName, type ScheduleJobRecordOptions, type ScheduleJobsOptions, type ScheduleJobsResult, type StartWorkersConfig, type WorkerInstance, type WorkersInstance, createEventJob, createRecurrentJob, defineJob, getServiceJobs, jobsHistoryRepo, jobsRepo, scheduleJob, scheduleJobs, startWorkers };
|
|
453
|
+
export { type BaseJobDefinition, type CreateEventJobOptions, type CreateJobOptions, type CreateRecurrentJobCronOptions, type CreateRecurrentJobOptions, type CreateRecurrentJobRunEveryOptions, EventJob, type EventJobDefinition, type ExecutionContext, type HistoryRecord, HistoryRecordSchema, type JobDefinition, type JobDefinitionWithName, type JobRecord, JobRecordSchema, type JobRetryResult, type JobRetryResultBase, type JobRetryResultRunAt, type JobRetryResultRunIn, JobStatusEnum, type JobToRun, Jobs, type JobsDefinition, type LogLevels, RecurrentJob, type RecurrentJobDefinition, type ScheduleJobOptions, type ScheduleJobOptionsBase, type ScheduleJobOptionsRunAt, type ScheduleJobOptionsRunIn, type ScheduleJobOptionsWithoutName, type ScheduleJobRecordOptions, type ScheduleJobsOptions, type ScheduleJobsResult, type StartWorkersConfig, type WorkerInstance, type WorkersInstance, createEventJob, createRecurrentJob, defineJob, getServiceJobs, jobsHistoryRepo, jobsRepo, scheduleJob, scheduleJobs, startWorkers };
|
package/dist/index.js
CHANGED
|
@@ -130,7 +130,8 @@ var JobsRepo = class {
|
|
|
130
130
|
status: { $ne: "maxTriesReached" }
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
|
-
$set: { lockedUntil, lastRunAt: /* @__PURE__ */ new Date() }
|
|
133
|
+
$set: { lockedUntil, lastRunAt: /* @__PURE__ */ new Date() },
|
|
134
|
+
$inc: { tries: 1 }
|
|
134
135
|
},
|
|
135
136
|
{
|
|
136
137
|
mongoOptions: {
|
|
@@ -143,12 +144,10 @@ var JobsRepo = class {
|
|
|
143
144
|
}
|
|
144
145
|
);
|
|
145
146
|
if (!job) return;
|
|
146
|
-
|
|
147
|
+
const tries = (job.tries || 0) + 1;
|
|
147
148
|
const wasStale = Boolean(job.lockedUntil);
|
|
148
149
|
if (wasStale) {
|
|
149
150
|
logger.info(`Running job "${job.jobName}" that was staled`);
|
|
150
|
-
await this.jobs.updateOne(job._id, { $inc: { tries: 1 } });
|
|
151
|
-
tries++;
|
|
152
151
|
}
|
|
153
152
|
return {
|
|
154
153
|
jobId: job._id,
|
|
@@ -171,10 +170,9 @@ var JobsRepo = class {
|
|
|
171
170
|
$set: {
|
|
172
171
|
nextRunAt: options.nextRunAt,
|
|
173
172
|
priority: options.priority,
|
|
174
|
-
...options.
|
|
173
|
+
...options.resetTries ? { tries: 0 } : {}
|
|
175
174
|
},
|
|
176
|
-
$unset: { lockedUntil: "" }
|
|
177
|
-
...options.addTries ? { $inc: { tries: 1 } } : {}
|
|
175
|
+
$unset: { lockedUntil: "" }
|
|
178
176
|
};
|
|
179
177
|
await this.jobs.updateOne(options.jobId, updator);
|
|
180
178
|
}
|
|
@@ -312,6 +310,7 @@ JobsRepo = __decorateElement(_init, 0, "JobsRepo", _JobsRepo_decorators, JobsRep
|
|
|
312
310
|
__runInitializers(_init, 1, JobsRepo);
|
|
313
311
|
|
|
314
312
|
// src/services/getNextRunDate.ts
|
|
313
|
+
import { CronExpressionParser } from "cron-parser";
|
|
315
314
|
var getNextRunDate = (options) => {
|
|
316
315
|
if (options.runIn) {
|
|
317
316
|
return new Date(Date.now() + options.runIn);
|
|
@@ -319,6 +318,15 @@ var getNextRunDate = (options) => {
|
|
|
319
318
|
if (options.runEvery) {
|
|
320
319
|
return new Date(Date.now() + options.runEvery);
|
|
321
320
|
}
|
|
321
|
+
if (options.cron) {
|
|
322
|
+
if (!options.timezone) {
|
|
323
|
+
throw new Error("Cron recurrent jobs require a timezone");
|
|
324
|
+
}
|
|
325
|
+
return CronExpressionParser.parse(options.cron, {
|
|
326
|
+
currentDate: options.currentDate ?? /* @__PURE__ */ new Date(),
|
|
327
|
+
tz: options.timezone
|
|
328
|
+
}).next().toDate();
|
|
329
|
+
}
|
|
322
330
|
if (options.runAt) {
|
|
323
331
|
return options.runAt;
|
|
324
332
|
}
|
|
@@ -561,7 +569,7 @@ var Executor = class {
|
|
|
561
569
|
jobId: jobToRun.jobId
|
|
562
570
|
});
|
|
563
571
|
jobLogger.warn(
|
|
564
|
-
`Job "${jobToRun.name}" has
|
|
572
|
+
`Job "${jobToRun.name}" has exceeded max tries (${jobToRun.tries}). Marking as maxTriesReached.`
|
|
565
573
|
);
|
|
566
574
|
await this.jobsRepo.markJobAsMaxTriesReached(jobToRun.jobId);
|
|
567
575
|
try {
|
|
@@ -573,35 +581,26 @@ var Executor = class {
|
|
|
573
581
|
}
|
|
574
582
|
}
|
|
575
583
|
async onError(error, job, jobToRun, context, config) {
|
|
576
|
-
const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries);
|
|
577
584
|
const scheduleRecurrent = async () => {
|
|
578
585
|
if (job.type === "recurrent") {
|
|
579
586
|
await this.jobsRepo.scheduleNextRun({
|
|
580
587
|
jobId: jobToRun.jobId,
|
|
581
588
|
nextRunAt: getNextRunDate(job),
|
|
582
|
-
|
|
589
|
+
resetTries: true,
|
|
583
590
|
priority: job.priority
|
|
584
591
|
});
|
|
585
592
|
}
|
|
586
593
|
};
|
|
587
594
|
const handleRetry = async (nextRunAt) => {
|
|
588
|
-
if (jobToRun.tries >= effectiveMaxTries) {
|
|
589
|
-
await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached);
|
|
590
|
-
return;
|
|
591
|
-
}
|
|
592
595
|
await this.jobsRepo.scheduleNextRun({
|
|
593
596
|
jobId: jobToRun.jobId,
|
|
594
597
|
nextRunAt,
|
|
595
|
-
|
|
598
|
+
resetTries: false,
|
|
596
599
|
priority: job.type === "recurrent" ? job.priority : jobToRun.priority
|
|
597
600
|
});
|
|
598
601
|
};
|
|
599
602
|
if (!job.onError) {
|
|
600
603
|
context.logger.error(`Error executing job "${jobToRun.name}"`, { error });
|
|
601
|
-
if (jobToRun.tries >= effectiveMaxTries) {
|
|
602
|
-
await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached);
|
|
603
|
-
return;
|
|
604
|
-
}
|
|
605
604
|
await scheduleRecurrent();
|
|
606
605
|
return;
|
|
607
606
|
}
|
|
@@ -650,7 +649,7 @@ var Executor = class {
|
|
|
650
649
|
await this.jobsRepo.scheduleNextRun({
|
|
651
650
|
jobId: jobToRun.jobId,
|
|
652
651
|
nextRunAt: getNextRunDate(job),
|
|
653
|
-
|
|
652
|
+
resetTries: true,
|
|
654
653
|
priority: job.priority
|
|
655
654
|
});
|
|
656
655
|
}
|
|
@@ -663,7 +662,7 @@ var Executor = class {
|
|
|
663
662
|
const job = this.getJobDefinition(jobToRun, config.jobs);
|
|
664
663
|
if (!job) return;
|
|
665
664
|
const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries);
|
|
666
|
-
if (jobToRun.
|
|
665
|
+
if (jobToRun.tries > effectiveMaxTries) {
|
|
667
666
|
await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached);
|
|
668
667
|
return;
|
|
669
668
|
}
|
|
@@ -954,6 +953,7 @@ import { getInstance, Service as Service4 } from "@orion-js/services";
|
|
|
954
953
|
|
|
955
954
|
// src/defineJob/index.ts
|
|
956
955
|
import { cleanAndValidate } from "@orion-js/schema";
|
|
956
|
+
import { CronExpressionParser as CronExpressionParser2 } from "cron-parser";
|
|
957
957
|
import parse from "parse-duration";
|
|
958
958
|
function createEventJob(options) {
|
|
959
959
|
const jobDefinition = {
|
|
@@ -992,11 +992,18 @@ function createEventJob(options) {
|
|
|
992
992
|
return jobDefinition;
|
|
993
993
|
}
|
|
994
994
|
function createRecurrentJob(options) {
|
|
995
|
+
if ("cron" in options && options.cron && !options.timezone) {
|
|
996
|
+
throw new Error("Cron recurrent jobs require a timezone");
|
|
997
|
+
}
|
|
998
|
+
if ("cron" in options && options.cron) {
|
|
999
|
+
CronExpressionParser2.parse(options.cron, { tz: options.timezone }).next();
|
|
1000
|
+
}
|
|
1001
|
+
const runEvery = "runEvery" in options ? typeof options.runEvery === "string" ? parse(options.runEvery) : options.runEvery : void 0;
|
|
995
1002
|
const jobDefinition = {
|
|
996
1003
|
...options,
|
|
997
1004
|
priority: options.priority ?? 100,
|
|
998
1005
|
type: "recurrent",
|
|
999
|
-
runEvery
|
|
1006
|
+
runEvery
|
|
1000
1007
|
};
|
|
1001
1008
|
return jobDefinition;
|
|
1002
1009
|
}
|
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/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 {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 })\n jobs: Collection<JobRecord>\n\n async getJobAndLock(jobNames: string[], lockTime: number): Promise<JobToRun> {\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 $or: [{lockedUntil: {$exists: false}}, {lockedUntil: {$lte: new Date()}}],\n // Exclude jobs that have reached max tries. Using $ne handles backwards compatibility\n // since records without the status field will still match (undefined !== 'maxTriesReached')\n status: {$ne: 'maxTriesReached'},\n },\n {\n $set: {lockedUntil, lastRunAt: new Date()},\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 let tries = job.tries || 1\n const wasStale = Boolean(job.lockedUntil)\n\n if (wasStale) {\n logger.info(`Running job \"${job.jobName}\" that was staled`)\n await this.jobs.updateOne(job._id, {$inc: {tries: 1}})\n tries++\n }\n\n return {\n jobId: job._id,\n executionId: generateId(),\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) {\n await this.jobs.updateOne(jobId, {$set: {priority}})\n }\n\n async scheduleNextRun(options: {\n jobId: string\n nextRunAt: Date\n addTries: boolean\n priority: number\n }) {\n const updator: MongoDB.UpdateFilter<JobRecord> = {\n $set: {\n nextRunAt: options.nextRunAt,\n priority: options.priority,\n ...(options.addTries ? {} : {tries: 0}),\n },\n $unset: {lockedUntil: ''},\n ...(options.addTries ? {$inc: {tries: 1}} : {}),\n }\n\n await this.jobs.updateOne(options.jobId, updator)\n }\n\n async deleteEventJob(jobId: string) {\n await this.jobs.deleteOne({_id: jobId, type: 'event'})\n }\n\n /**\n * Marks a job as having reached its maximum tries limit.\n * The job will remain in the database but won't be picked up for execution.\n */\n async markJobAsMaxTriesReached(jobId: string) {\n await this.jobs.updateOne(\n {_id: jobId},\n {\n $set: {status: 'maxTriesReached'},\n $unset: {lockedUntil: ''},\n },\n )\n }\n\n async extendLockTime(jobId: string, extraTime: number) {\n await this.updateLockTime(jobId, extraTime)\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) {\n const lockedUntil = new Date(Date.now() + lockDuration)\n await this.jobs.updateOne(\n {\n _id: jobId,\n },\n {\n $set: {lockedUntil},\n },\n )\n }\n\n async unlockAllJobs(): Promise<number> {\n const result = await this.jobs.updateMany(\n {\n lockedUntil: {$exists: true},\n },\n {\n $unset: {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 $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': 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 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\nexport type JobRecord = InferSchemaType<typeof JobRecordSchema>\n","export type Options = {\n getNextRun?: () => Date\n runIn?: number\n runEvery?: number\n runAt?: Date\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.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 {StartWorkersConfig} from '../types/StartConfig'\nimport {JobToRun, WorkerInstance, WorkersInstance} from '../types/Worker'\nimport {ExecuteJobConfig, Executor} from './Executor'\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: WorkersInstance,\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: WorkersInstance, jobName: string) {\n const currentExecutions = workersInstance.runningJobsByName.get(jobName) || 0\n workersInstance.runningJobsByName.set(jobName, currentExecutions + 1)\n }\n\n releaseJobExecution(workersInstance: WorkersInstance, 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 async withJobAcquisitionLock<T>(workersInstance: WorkersInstance, callback: () => Promise<T>) {\n const previousLock = workersInstance.jobAcquisitionLock\n let releaseLock!: () => void\n workersInstance.jobAcquisitionLock = new Promise<void>(resolve => {\n releaseLock = resolve\n })\n\n await previousLock\n\n try {\n return await callback()\n } finally {\n releaseLock()\n }\n }\n\n async getJobAndReserveExecution(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n jobNames: string[],\n ): Promise<JobToRun | undefined> {\n return this.withJobAcquisitionLock(workersInstance, async () => {\n const availableJobNames = this.getAvailableJobNames(config, workersInstance, jobNames)\n if (availableJobNames.length === 0) return\n\n const jobToRun = await this.jobsRepo.getJobAndLock(availableJobNames, config.defaultLockTime)\n if (!jobToRun) return\n\n this.reserveJobExecution(workersInstance, jobToRun.name)\n return jobToRun\n })\n }\n\n async runWorkerLoop(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n workerInstance: WorkerInstance,\n jobNames: string[],\n executeConfig: ExecuteJobConfig,\n ) {\n const jobToRun = await this.getJobAndReserveExecution(config, workersInstance, jobNames)\n if (!jobToRun) {\n logger.debug('No job to run')\n return false\n }\n\n logger.debug(`Got job [w${workerInstance.workerIndex}] to run:`, jobToRun)\n\n try {\n await this.executor.executeJob(executeConfig, jobToRun, workerInstance.respawn)\n } finally {\n this.releaseJobExecution(workersInstance, jobToRun.name)\n }\n\n return true\n }\n\n async startWorker(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n workerInstance: WorkerInstance,\n ) {\n const names = this.getJobNames(config.jobs)\n logger.debug(\n `Running worker loop [w${workerInstance.workerIndex}] for jobs \"${names.join(', ')}\"...`,\n )\n const executeConfig: ExecuteJobConfig = {\n jobs: config.jobs,\n maxTries: config.maxTries,\n onMaxTriesReached: config.onMaxTriesReached,\n }\n\n while (true) {\n if (!workerInstance.running) {\n logger.info(`Got signal to stop. Stopping worker [w${workerInstance.workerIndex}]...`)\n return\n }\n\n try {\n const didRun = await this.runWorkerLoop(\n config,\n workersInstance,\n workerInstance,\n names,\n executeConfig,\n )\n if (!didRun) await sleep(config.pollInterval)\n if (didRun) await sleep(config.cooldownPeriod)\n } catch (error) {\n logger.error('Error in job runner.', {error})\n await sleep(config.pollInterval)\n }\n }\n }\n\n createWorkersInstanceDefinition(config: StartWorkersConfig): WorkersInstance {\n const workersInstance: WorkersInstance = {\n running: true,\n workersCount: config.workersCount,\n workers: [],\n runningJobsByName: new Map(),\n jobAcquisitionLock: Promise.resolve(),\n stop: async () => {\n logger.info('Stopping workers...')\n workersInstance.running = false\n const stopingPromises = workersInstance.workers.map(worker => worker.stop())\n await Promise.all(stopingPromises)\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 startANewWorker(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n workerIndex = workersInstance.workers.length,\n ) {\n if (!workersInstance.running) {\n return\n }\n\n const workerInstance: WorkerInstance = {\n running: true,\n workerIndex,\n stop: async () => {\n logger.info(`Stopping worker [w${workerIndex}]...`)\n workerInstance.running = false\n await workerInstance.promise\n },\n respawn: async () => {\n logger.info(`Respawning worker [w${workerIndex}]...`)\n workerInstance.running = false\n await this.startANewWorker(config, workersInstance, workerIndex)\n },\n }\n\n const workerPromise = this.startWorker(config, workersInstance, workerInstance)\n\n workerInstance.promise = workerPromise\n workersInstance.workers[workerIndex] = workerInstance\n }\n\n async runWorkers(config: StartWorkersConfig, workersInstance: WorkersInstance) {\n logger.debug('Will ensure records for recurrent jobs')\n await this.ensureRecords(config)\n\n const workersCount = config.workersCount\n const workerWord = workersCount === 1 ? 'worker' : 'workers'\n logger.info(`Starting ${workersCount} ${workerWord}`)\n\n for (let workerIndex = 0; workerIndex < workersCount; workerIndex++) {\n this.startANewWorker(config, workersInstance, workerIndex)\n }\n }\n\n /**\n * Starts the job workers with the provided configuration.\n * @param userConfig - Configuration for the workers. Required fields: jobs, maxTries, onMaxTriesReached\n */\n startWorkers(userConfig: StartWorkersConfig): WorkersInstance {\n // Apply defaults for optional fields\n const config: StartWorkersConfig = {\n cooldownPeriod: 100,\n pollInterval: 3000,\n workersCount: 4,\n defaultLockTime: 30 * 1000,\n ...userConfig,\n }\n\n setNameToJobs(config.jobs)\n\n const workersInstance = this.createWorkersInstanceDefinition(config)\n logger.debug('Starting workers', config)\n\n this.runWorkers(config, workersInstance)\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 {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 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(job: JobDefinition, jobToRun: JobToRun, onStale: Function): ExecutionContext {\n const effectiveLockTime = this.getEffectiveLockTime(job, jobToRun)\n let staleTimeout = setTimeout(() => onStale(), effectiveLockTime)\n staleTimeout.unref?.()\n return {\n definition: job,\n record: jobToRun,\n tries: jobToRun.tries || 0,\n clearStaleTimeout: () => clearTimeout(staleTimeout),\n extendLockTime: async (extraTime: number) => {\n clearTimeout(staleTimeout)\n staleTimeout = setTimeout(() => onStale(), extraTime)\n staleTimeout.unref?.()\n await this.jobsRepo.extendLockTime(jobToRun.jobId, extraTime)\n },\n logger: logger.addMetadata({\n jobName: jobToRun.name,\n jobId: jobToRun.jobId,\n }),\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 a job.\n * Job-specific maxTries takes precedence over the global maxTries from config.\n */\n getEffectiveMaxTries(job: JobDefinition, globalMaxTries: number): number {\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.\n */\n async handleMaxTriesReached(\n jobToRun: JobToRun,\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 reached max tries (${jobToRun.tries}). Marking as maxTriesReached.`,\n )\n await this.jobsRepo.markJobAsMaxTriesReached(jobToRun.jobId)\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\n async onError(\n error: unknown,\n job: JobDefinition,\n jobToRun: JobToRun,\n context: ExecutionContext,\n config: ExecuteJobConfig,\n ) {\n const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries)\n\n // Helper to schedule next run for recurrent jobs (used when dismissing)\n const scheduleRecurrent = async () => {\n if (job.type === 'recurrent') {\n await this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt: getNextRunDate(job),\n addTries: false,\n priority: job.priority,\n })\n }\n }\n\n // Helper to handle retry with max tries check\n const handleRetry = async (nextRunAt: Date) => {\n // Check if we've reached max tries before scheduling another retry\n if (jobToRun.tries >= effectiveMaxTries) {\n await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached)\n return\n }\n\n await this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt,\n addTries: true,\n priority: job.type === 'recurrent' ? job.priority : jobToRun.priority,\n })\n }\n\n // If no custom error handler, check max tries and schedule recurrent if applicable\n if (!job.onError) {\n context.logger.error(`Error executing job \"${jobToRun.name}\"`, {error})\n\n // For jobs without onError, check if max tries reached\n if (jobToRun.tries >= effectiveMaxTries) {\n await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached)\n return\n }\n\n await scheduleRecurrent()\n return\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 await scheduleRecurrent()\n return\n }\n\n if (result.action === 'retry') {\n await handleRetry(getNextRunDate(result))\n }\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 await this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt: getNextRunDate(job),\n addTries: false,\n priority: job.priority,\n })\n }\n if (job.type === 'event') {\n context.logger.debug(`Removing event job after success \"${jobToRun.name}\"`)\n await this.jobsRepo.deleteEventJob(jobToRun.jobId)\n }\n }\n\n async executeJob(config: ExecuteJobConfig, jobToRun: JobToRun, respawnWorker: () => void) {\n const job = this.getJobDefinition(jobToRun, config.jobs)\n if (!job) return\n\n const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries)\n if (jobToRun.wasStale && jobToRun.tries >= effectiveMaxTries) {\n await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached)\n return\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 await this.jobsRepo.updateLockTime(jobToRun.jobId, effectiveLockTime)\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\n const onStale = async () => {\n if (job.onStale) {\n context.logger.info(`Job \"${jobToRun.name}\" is stale`)\n job.onStale(jobToRun.params, context)\n } else {\n context.logger.error(`Job \"${jobToRun.name}\" is stale`)\n }\n\n await this.jobsRepo.setJobRecordPriority(jobToRun.jobId, 0)\n\n void respawnWorker()\n\n void this.saveExecution({\n startedAt,\n status: 'stale',\n result: null,\n errorMessage: null,\n job,\n jobToRun,\n }).catch(error => {\n context.logger.error('Error saving stale execution history', {error})\n })\n }\n\n const context = this.getContext(job, jobToRun, onStale)\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 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\n await this.afterExecutionSuccess(job, jobToRun, context)\n } catch (error) {\n context.clearStaleTimeout()\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 await this.onError(error, job, jobToRun, context, config)\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 {\n CreateEventJobOptions,\n CreateJobOptions,\n CreateRecurrentJobOptions,\n EventJobDefinition,\n JobDefinition,\n RecurrentJobDefinition,\n} from '../types/JobsDefinition'\nimport {scheduleJob, ScheduleJobsResult, scheduleJobs} from '..'\nimport {ScheduleJobOptionsWithoutName} from '../types/Events'\nimport {cleanAndValidate, SchemaInAnyOrionForm} from '@orion-js/schema'\nimport parse from 'parse-duration'\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 (scheduleOptions: ScheduleJobOptionsWithoutName<TParamsSchema>) => {\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 jobDefinition: RecurrentJobDefinition = {\n ...options,\n priority: options.priority ?? 100,\n type: 'recurrent',\n runEvery: typeof options.runEvery === 'string' ? parse(options.runEvery) : options.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","_a","logger","_jobsRepo_dec","_init","Service","Inject","logger","Service","Service","getInstance"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/services/EventsService.ts","../src/repos/JobsRepo.ts","../src/types/JobRecord.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 {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 })\n jobs: Collection<JobRecord>\n\n async getJobAndLock(jobNames: string[], lockTime: number): Promise<JobToRun> {\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 $or: [{lockedUntil: {$exists: false}}, {lockedUntil: {$lte: new Date()}}],\n // Exclude jobs that have reached max tries. Using $ne handles backwards compatibility\n // since records without the status field will still match (undefined !== 'maxTriesReached')\n status: {$ne: 'maxTriesReached'},\n },\n {\n $set: {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: generateId(),\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) {\n await this.jobs.updateOne(jobId, {$set: {priority}})\n }\n\n async scheduleNextRun(options: {\n jobId: string\n nextRunAt: Date\n resetTries: boolean\n priority: number\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: {lockedUntil: ''},\n }\n\n await this.jobs.updateOne(options.jobId, updator)\n }\n\n async deleteEventJob(jobId: string) {\n await this.jobs.deleteOne({_id: jobId, type: 'event'})\n }\n\n /**\n * Marks a job as having reached its maximum tries limit.\n * The job will remain in the database but won't be picked up for execution.\n */\n async markJobAsMaxTriesReached(jobId: string) {\n await this.jobs.updateOne(\n {_id: jobId},\n {\n $set: {status: 'maxTriesReached'},\n $unset: {lockedUntil: ''},\n },\n )\n }\n\n async extendLockTime(jobId: string, extraTime: number) {\n await this.updateLockTime(jobId, extraTime)\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) {\n const lockedUntil = new Date(Date.now() + lockDuration)\n await this.jobs.updateOne(\n {\n _id: jobId,\n },\n {\n $set: {lockedUntil},\n },\n )\n }\n\n async unlockAllJobs(): Promise<number> {\n const result = await this.jobs.updateMany(\n {\n lockedUntil: {$exists: true},\n },\n {\n $unset: {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 $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': 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 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\nexport type JobRecord = InferSchemaType<typeof JobRecordSchema>\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 {StartWorkersConfig} from '../types/StartConfig'\nimport {JobToRun, WorkerInstance, WorkersInstance} from '../types/Worker'\nimport {ExecuteJobConfig, Executor} from './Executor'\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: WorkersInstance,\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: WorkersInstance, jobName: string) {\n const currentExecutions = workersInstance.runningJobsByName.get(jobName) || 0\n workersInstance.runningJobsByName.set(jobName, currentExecutions + 1)\n }\n\n releaseJobExecution(workersInstance: WorkersInstance, 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 async withJobAcquisitionLock<T>(workersInstance: WorkersInstance, callback: () => Promise<T>) {\n const previousLock = workersInstance.jobAcquisitionLock\n let releaseLock!: () => void\n workersInstance.jobAcquisitionLock = new Promise<void>(resolve => {\n releaseLock = resolve\n })\n\n await previousLock\n\n try {\n return await callback()\n } finally {\n releaseLock()\n }\n }\n\n async getJobAndReserveExecution(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n jobNames: string[],\n ): Promise<JobToRun | undefined> {\n return this.withJobAcquisitionLock(workersInstance, async () => {\n const availableJobNames = this.getAvailableJobNames(config, workersInstance, jobNames)\n if (availableJobNames.length === 0) return\n\n const jobToRun = await this.jobsRepo.getJobAndLock(availableJobNames, config.defaultLockTime)\n if (!jobToRun) return\n\n this.reserveJobExecution(workersInstance, jobToRun.name)\n return jobToRun\n })\n }\n\n async runWorkerLoop(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n workerInstance: WorkerInstance,\n jobNames: string[],\n executeConfig: ExecuteJobConfig,\n ) {\n const jobToRun = await this.getJobAndReserveExecution(config, workersInstance, jobNames)\n if (!jobToRun) {\n logger.debug('No job to run')\n return false\n }\n\n logger.debug(`Got job [w${workerInstance.workerIndex}] to run:`, jobToRun)\n\n try {\n await this.executor.executeJob(executeConfig, jobToRun, workerInstance.respawn)\n } finally {\n this.releaseJobExecution(workersInstance, jobToRun.name)\n }\n\n return true\n }\n\n async startWorker(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n workerInstance: WorkerInstance,\n ) {\n const names = this.getJobNames(config.jobs)\n logger.debug(\n `Running worker loop [w${workerInstance.workerIndex}] for jobs \"${names.join(', ')}\"...`,\n )\n const executeConfig: ExecuteJobConfig = {\n jobs: config.jobs,\n maxTries: config.maxTries,\n onMaxTriesReached: config.onMaxTriesReached,\n }\n\n while (true) {\n if (!workerInstance.running) {\n logger.info(`Got signal to stop. Stopping worker [w${workerInstance.workerIndex}]...`)\n return\n }\n\n try {\n const didRun = await this.runWorkerLoop(\n config,\n workersInstance,\n workerInstance,\n names,\n executeConfig,\n )\n if (!didRun) await sleep(config.pollInterval)\n if (didRun) await sleep(config.cooldownPeriod)\n } catch (error) {\n logger.error('Error in job runner.', {error})\n await sleep(config.pollInterval)\n }\n }\n }\n\n createWorkersInstanceDefinition(config: StartWorkersConfig): WorkersInstance {\n const workersInstance: WorkersInstance = {\n running: true,\n workersCount: config.workersCount,\n workers: [],\n runningJobsByName: new Map(),\n jobAcquisitionLock: Promise.resolve(),\n stop: async () => {\n logger.info('Stopping workers...')\n workersInstance.running = false\n const stopingPromises = workersInstance.workers.map(worker => worker.stop())\n await Promise.all(stopingPromises)\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 startANewWorker(\n config: StartWorkersConfig,\n workersInstance: WorkersInstance,\n workerIndex = workersInstance.workers.length,\n ) {\n if (!workersInstance.running) {\n return\n }\n\n const workerInstance: WorkerInstance = {\n running: true,\n workerIndex,\n stop: async () => {\n logger.info(`Stopping worker [w${workerIndex}]...`)\n workerInstance.running = false\n await workerInstance.promise\n },\n respawn: async () => {\n logger.info(`Respawning worker [w${workerIndex}]...`)\n workerInstance.running = false\n await this.startANewWorker(config, workersInstance, workerIndex)\n },\n }\n\n const workerPromise = this.startWorker(config, workersInstance, workerInstance)\n\n workerInstance.promise = workerPromise\n workersInstance.workers[workerIndex] = workerInstance\n }\n\n async runWorkers(config: StartWorkersConfig, workersInstance: WorkersInstance) {\n logger.debug('Will ensure records for recurrent jobs')\n await this.ensureRecords(config)\n\n const workersCount = config.workersCount\n const workerWord = workersCount === 1 ? 'worker' : 'workers'\n logger.info(`Starting ${workersCount} ${workerWord}`)\n\n for (let workerIndex = 0; workerIndex < workersCount; workerIndex++) {\n this.startANewWorker(config, workersInstance, workerIndex)\n }\n }\n\n /**\n * Starts the job workers with the provided configuration.\n * @param userConfig - Configuration for the workers. Required fields: jobs, maxTries, onMaxTriesReached\n */\n startWorkers(userConfig: StartWorkersConfig): WorkersInstance {\n // Apply defaults for optional fields\n const config: StartWorkersConfig = {\n cooldownPeriod: 100,\n pollInterval: 3000,\n workersCount: 4,\n defaultLockTime: 30 * 1000,\n ...userConfig,\n }\n\n setNameToJobs(config.jobs)\n\n const workersInstance = this.createWorkersInstanceDefinition(config)\n logger.debug('Starting workers', config)\n\n this.runWorkers(config, workersInstance)\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 {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 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(job: JobDefinition, jobToRun: JobToRun, onStale: Function): ExecutionContext {\n const effectiveLockTime = this.getEffectiveLockTime(job, jobToRun)\n let staleTimeout = setTimeout(() => onStale(), effectiveLockTime)\n staleTimeout.unref?.()\n return {\n definition: job,\n record: jobToRun,\n tries: jobToRun.tries || 0,\n clearStaleTimeout: () => clearTimeout(staleTimeout),\n extendLockTime: async (extraTime: number) => {\n clearTimeout(staleTimeout)\n staleTimeout = setTimeout(() => onStale(), extraTime)\n staleTimeout.unref?.()\n await this.jobsRepo.extendLockTime(jobToRun.jobId, extraTime)\n },\n logger: logger.addMetadata({\n jobName: jobToRun.name,\n jobId: jobToRun.jobId,\n }),\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 a job.\n * Job-specific maxTries takes precedence over the global maxTries from config.\n */\n getEffectiveMaxTries(job: JobDefinition, globalMaxTries: number): number {\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.\n */\n async handleMaxTriesReached(\n jobToRun: JobToRun,\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 await this.jobsRepo.markJobAsMaxTriesReached(jobToRun.jobId)\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\n async onError(\n error: unknown,\n job: JobDefinition,\n jobToRun: JobToRun,\n context: ExecutionContext,\n config: ExecuteJobConfig,\n ) {\n // Helper to schedule next run for recurrent jobs (used when dismissing)\n const scheduleRecurrent = async () => {\n if (job.type === 'recurrent') {\n await this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt: getNextRunDate(job),\n resetTries: true,\n priority: job.priority,\n })\n }\n }\n\n const handleRetry = async (nextRunAt: Date) => {\n await this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt,\n resetTries: false,\n priority: job.type === 'recurrent' ? job.priority : jobToRun.priority,\n })\n }\n\n if (!job.onError) {\n context.logger.error(`Error executing job \"${jobToRun.name}\"`, {error})\n\n await scheduleRecurrent()\n return\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 await scheduleRecurrent()\n return\n }\n\n if (result.action === 'retry') {\n await handleRetry(getNextRunDate(result))\n }\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 await this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt: getNextRunDate(job),\n resetTries: true,\n priority: job.priority,\n })\n }\n if (job.type === 'event') {\n context.logger.debug(`Removing event job after success \"${jobToRun.name}\"`)\n await this.jobsRepo.deleteEventJob(jobToRun.jobId)\n }\n }\n\n async executeJob(config: ExecuteJobConfig, jobToRun: JobToRun, respawnWorker: () => void) {\n const job = this.getJobDefinition(jobToRun, config.jobs)\n if (!job) return\n\n const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries)\n if (jobToRun.tries > effectiveMaxTries) {\n await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached)\n return\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 await this.jobsRepo.updateLockTime(jobToRun.jobId, effectiveLockTime)\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\n const onStale = async () => {\n if (job.onStale) {\n context.logger.info(`Job \"${jobToRun.name}\" is stale`)\n job.onStale(jobToRun.params, context)\n } else {\n context.logger.error(`Job \"${jobToRun.name}\" is stale`)\n }\n\n await this.jobsRepo.setJobRecordPriority(jobToRun.jobId, 0)\n\n void respawnWorker()\n\n void this.saveExecution({\n startedAt,\n status: 'stale',\n result: null,\n errorMessage: null,\n job,\n jobToRun,\n }).catch(error => {\n context.logger.error('Error saving stale execution history', {error})\n })\n }\n\n const context = this.getContext(job, jobToRun, onStale)\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 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\n await this.afterExecutionSuccess(job, jobToRun, context)\n } catch (error) {\n context.clearStaleTimeout()\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 await this.onError(error, job, jobToRun, context, config)\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 if ('cron' in options && options.cron && !options.timezone) {\n throw new Error('Cron recurrent jobs require a timezone')\n }\n\n if ('cron' in options && options.cron) {\n CronExpressionParser.parse(options.cron, {tz: options.timezone}).next()\n }\n\n const runEvery =\n 'runEvery' in options\n ? typeof options.runEvery === 'string'\n ? parse(options.runEvery)\n : options.runEvery\n : undefined\n\n const jobDefinition: RecurrentJobDefinition = {\n ...options,\n priority: options.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","_a","logger","_jobsRepo_dec","_init","Service","Inject","logger","Service","CronExpressionParser","CronExpressionParser","Service","getInstance"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orion-js/dogs",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"@orion-js/schema": "4.3.1",
|
|
29
29
|
"@orion-js/services": "4.3.1",
|
|
30
30
|
"@orion-js/typed-model": "4.3.1",
|
|
31
|
+
"cron-parser": "^5.5.0",
|
|
31
32
|
"dataloader": "2.2.2",
|
|
32
33
|
"dot-object": "^2.1.5",
|
|
33
34
|
"parse-duration": "^2.1.3"
|