@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 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
- let tries = job.tries || 1;
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.addTries ? {} : { tries: 0 }
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 reached max tries (${jobToRun.tries}). Marking as maxTriesReached.`
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
- addTries: false,
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
- addTries: true,
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
- addTries: false,
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.wasStale && jobToRun.tries >= effectiveMaxTries) {
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: typeof options.runEvery === "string" ? (0, import_parse_duration.default)(options.runEvery) : options.runEvery
1049
+ runEvery
1043
1050
  };
1044
1051
  return jobDefinition;
1045
1052
  }
@@ -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 CreateRecurrentJobOptions = Omit<RecurrentJobDefinition, 'type' | 'runEvery'> & {
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
- addTries: boolean;
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 CreateRecurrentJobOptions = Omit<RecurrentJobDefinition, 'type' | 'runEvery'> & {
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
- addTries: boolean;
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
- let tries = job.tries || 1;
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.addTries ? {} : { tries: 0 }
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 reached max tries (${jobToRun.tries}). Marking as maxTriesReached.`
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
- addTries: false,
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
- addTries: true,
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
- addTries: false,
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.wasStale && jobToRun.tries >= effectiveMaxTries) {
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: typeof options.runEvery === "string" ? parse(options.runEvery) : options.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",
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"