@orion-js/dogs 4.1.10 → 4.2.0
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 +111 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -7
- package/dist/index.d.ts +55 -7
- package/dist/index.js +110 -23
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -77,6 +77,7 @@ __export(index_exports, {
|
|
|
77
77
|
EventJob: () => EventJob,
|
|
78
78
|
HistoryRecordSchema: () => HistoryRecordSchema,
|
|
79
79
|
JobRecordSchema: () => JobRecordSchema,
|
|
80
|
+
JobStatusEnum: () => JobStatusEnum,
|
|
80
81
|
Jobs: () => Jobs,
|
|
81
82
|
RecurrentJob: () => RecurrentJob,
|
|
82
83
|
createEventJob: () => createEventJob,
|
|
@@ -104,6 +105,7 @@ var import_mongodb2 = require("@orion-js/mongodb");
|
|
|
104
105
|
|
|
105
106
|
// src/types/JobRecord.ts
|
|
106
107
|
var import_schema = require("@orion-js/schema");
|
|
108
|
+
var JobStatusEnum = (0, import_schema.createEnum)("JobStatus", ["pending", "maxTriesReached"]);
|
|
107
109
|
var JobRecordSchema = (0, import_schema.schemaWithName)("JobRecord", {
|
|
108
110
|
_id: { type: "string" },
|
|
109
111
|
jobName: { type: "string" },
|
|
@@ -114,7 +116,12 @@ var JobRecordSchema = (0, import_schema.schemaWithName)("JobRecord", {
|
|
|
114
116
|
lastRunAt: { type: "date", optional: true },
|
|
115
117
|
lockedUntil: { type: "date", optional: true },
|
|
116
118
|
tries: { type: "number", optional: true },
|
|
117
|
-
params: { type: "blackbox", optional: true }
|
|
119
|
+
params: { type: "blackbox", optional: true },
|
|
120
|
+
/**
|
|
121
|
+
* Status of the job. Optional for backwards compatibility with existing records.
|
|
122
|
+
* Records without this field are treated as 'pending'.
|
|
123
|
+
*/
|
|
124
|
+
status: { type: JobStatusEnum, optional: true }
|
|
118
125
|
});
|
|
119
126
|
|
|
120
127
|
// src/repos/JobsRepo.ts
|
|
@@ -161,7 +168,10 @@ var JobsRepo = class {
|
|
|
161
168
|
{
|
|
162
169
|
jobName: { $in: jobNames },
|
|
163
170
|
nextRunAt: { $lte: /* @__PURE__ */ new Date() },
|
|
164
|
-
$or: [{ lockedUntil: { $exists: false } }, { lockedUntil: { $lte: /* @__PURE__ */ new Date() } }]
|
|
171
|
+
$or: [{ lockedUntil: { $exists: false } }, { lockedUntil: { $lte: /* @__PURE__ */ new Date() } }],
|
|
172
|
+
// Exclude jobs that have reached max tries. Using $ne handles backwards compatibility
|
|
173
|
+
// since records without the status field will still match (undefined !== 'maxTriesReached')
|
|
174
|
+
status: { $ne: "maxTriesReached" }
|
|
165
175
|
},
|
|
166
176
|
{
|
|
167
177
|
$set: { lockedUntil, lastRunAt: /* @__PURE__ */ new Date() }
|
|
@@ -213,8 +223,28 @@ var JobsRepo = class {
|
|
|
213
223
|
async deleteEventJob(jobId) {
|
|
214
224
|
await this.jobs.deleteOne({ _id: jobId, type: "event" });
|
|
215
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* Marks a job as having reached its maximum tries limit.
|
|
228
|
+
* The job will remain in the database but won't be picked up for execution.
|
|
229
|
+
*/
|
|
230
|
+
async markJobAsMaxTriesReached(jobId) {
|
|
231
|
+
await this.jobs.updateOne(
|
|
232
|
+
{ _id: jobId },
|
|
233
|
+
{
|
|
234
|
+
$set: { status: "maxTriesReached" },
|
|
235
|
+
$unset: { lockedUntil: "" }
|
|
236
|
+
}
|
|
237
|
+
);
|
|
238
|
+
}
|
|
216
239
|
async extendLockTime(jobId, extraTime) {
|
|
217
|
-
|
|
240
|
+
await this.updateLockTime(jobId, extraTime);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Updates the lock time for a job to the specified duration from now.
|
|
244
|
+
* Can be used to both extend or shorten the lock time.
|
|
245
|
+
*/
|
|
246
|
+
async updateLockTime(jobId, lockDuration) {
|
|
247
|
+
const lockedUntil = new Date(Date.now() + lockDuration);
|
|
218
248
|
await this.jobs.updateOne(
|
|
219
249
|
{
|
|
220
250
|
_id: jobId
|
|
@@ -532,8 +562,16 @@ var Executor = class {
|
|
|
532
562
|
__publicField(this, "jobsRepo", __runInitializers(_init4, 8, this)), __runInitializers(_init4, 11, this);
|
|
533
563
|
__publicField(this, "jobsHistoryRepo", __runInitializers(_init4, 12, this)), __runInitializers(_init4, 15, this);
|
|
534
564
|
}
|
|
565
|
+
/**
|
|
566
|
+
* Determines the effective lock time for a job execution.
|
|
567
|
+
* Job-specific lockTime takes precedence over the default lockTime from config.
|
|
568
|
+
*/
|
|
569
|
+
getEffectiveLockTime(job, jobToRun) {
|
|
570
|
+
return job.lockTime ?? jobToRun.lockTime;
|
|
571
|
+
}
|
|
535
572
|
getContext(job, jobToRun, onStale) {
|
|
536
|
-
|
|
573
|
+
const effectiveLockTime = this.getEffectiveLockTime(job, jobToRun);
|
|
574
|
+
let staleTimeout = setTimeout(() => onStale(), effectiveLockTime);
|
|
537
575
|
return {
|
|
538
576
|
definition: job,
|
|
539
577
|
record: jobToRun,
|
|
@@ -560,7 +598,32 @@ var Executor = class {
|
|
|
560
598
|
}
|
|
561
599
|
return job;
|
|
562
600
|
}
|
|
563
|
-
|
|
601
|
+
/**
|
|
602
|
+
* Determines the effective max tries for a job.
|
|
603
|
+
* Job-specific maxTries takes precedence over the global maxTries from config.
|
|
604
|
+
*/
|
|
605
|
+
getEffectiveMaxTries(job, globalMaxTries) {
|
|
606
|
+
return job.maxTries ?? globalMaxTries;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Handles when a job has reached its maximum retry attempts.
|
|
610
|
+
* Marks the job in the database and invokes the onMaxTriesReached callback.
|
|
611
|
+
*/
|
|
612
|
+
async handleMaxTriesReached(jobToRun, context, onMaxTriesReached) {
|
|
613
|
+
context.logger.warn(
|
|
614
|
+
`Job "${jobToRun.name}" has reached max tries (${jobToRun.tries}). Marking as maxTriesReached.`
|
|
615
|
+
);
|
|
616
|
+
await this.jobsRepo.markJobAsMaxTriesReached(jobToRun.jobId);
|
|
617
|
+
try {
|
|
618
|
+
await onMaxTriesReached(jobToRun);
|
|
619
|
+
} catch (callbackError) {
|
|
620
|
+
context.logger.error(`Error in onMaxTriesReached callback for job "${jobToRun.name}"`, {
|
|
621
|
+
error: callbackError
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
async onError(error, job, jobToRun, context, config) {
|
|
626
|
+
const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries);
|
|
564
627
|
const scheduleRecurrent = async () => {
|
|
565
628
|
if (job.type === "recurrent") {
|
|
566
629
|
await this.jobsRepo.scheduleNextRun({
|
|
@@ -571,24 +634,39 @@ var Executor = class {
|
|
|
571
634
|
});
|
|
572
635
|
}
|
|
573
636
|
};
|
|
637
|
+
const handleRetry = async (nextRunAt) => {
|
|
638
|
+
if (jobToRun.tries >= effectiveMaxTries) {
|
|
639
|
+
await this.handleMaxTriesReached(jobToRun, context, config.onMaxTriesReached);
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
await this.jobsRepo.scheduleNextRun({
|
|
643
|
+
jobId: jobToRun.jobId,
|
|
644
|
+
nextRunAt,
|
|
645
|
+
addTries: true,
|
|
646
|
+
priority: job.type === "recurrent" ? job.priority : jobToRun.priority
|
|
647
|
+
});
|
|
648
|
+
};
|
|
574
649
|
if (!job.onError) {
|
|
575
650
|
context.logger.error(`Error executing job "${jobToRun.name}"`, { error });
|
|
651
|
+
if (jobToRun.tries >= effectiveMaxTries) {
|
|
652
|
+
await this.handleMaxTriesReached(jobToRun, context, config.onMaxTriesReached);
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
576
655
|
await scheduleRecurrent();
|
|
577
656
|
return;
|
|
578
657
|
}
|
|
579
658
|
context.logger.info(`Error executing job "${jobToRun.name}"`, { error });
|
|
580
|
-
const result = await job.onError(
|
|
659
|
+
const result = await job.onError(
|
|
660
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
661
|
+
jobToRun.params,
|
|
662
|
+
context
|
|
663
|
+
);
|
|
581
664
|
if (result.action === "dismiss") {
|
|
582
665
|
await scheduleRecurrent();
|
|
583
666
|
return;
|
|
584
667
|
}
|
|
585
668
|
if (result.action === "retry") {
|
|
586
|
-
await
|
|
587
|
-
jobId: jobToRun.jobId,
|
|
588
|
-
nextRunAt: getNextRunDate(result),
|
|
589
|
-
addTries: true,
|
|
590
|
-
priority: job.type === "recurrent" ? job.priority : jobToRun.priority
|
|
591
|
-
});
|
|
669
|
+
await handleRetry(getNextRunDate(result));
|
|
592
670
|
}
|
|
593
671
|
}
|
|
594
672
|
async saveExecution(options) {
|
|
@@ -631,9 +709,13 @@ var Executor = class {
|
|
|
631
709
|
await this.jobsRepo.deleteEventJob(jobToRun.jobId);
|
|
632
710
|
}
|
|
633
711
|
}
|
|
634
|
-
async executeJob(
|
|
635
|
-
const job = this.getJobDefinition(jobToRun, jobs);
|
|
712
|
+
async executeJob(config, jobToRun, respawnWorker) {
|
|
713
|
+
const job = this.getJobDefinition(jobToRun, config.jobs);
|
|
636
714
|
if (!job) return;
|
|
715
|
+
const effectiveLockTime = this.getEffectiveLockTime(job, jobToRun);
|
|
716
|
+
if (effectiveLockTime !== jobToRun.lockTime) {
|
|
717
|
+
await this.jobsRepo.updateLockTime(jobToRun.jobId, effectiveLockTime);
|
|
718
|
+
}
|
|
637
719
|
const tracer = import_api.trace.getTracer("orionjs.dogs", "1.0");
|
|
638
720
|
await tracer.startActiveSpan(`job.${jobToRun.name}.${jobToRun.executionId}`, async (span) => {
|
|
639
721
|
try {
|
|
@@ -689,7 +771,7 @@ var Executor = class {
|
|
|
689
771
|
job,
|
|
690
772
|
jobToRun
|
|
691
773
|
});
|
|
692
|
-
await this.onError(error, job, jobToRun, context);
|
|
774
|
+
await this.onError(error, job, jobToRun, context, config);
|
|
693
775
|
}
|
|
694
776
|
});
|
|
695
777
|
} catch (error) {
|
|
@@ -735,13 +817,18 @@ var WorkerService = class {
|
|
|
735
817
|
import_logger4.logger.debug(
|
|
736
818
|
`Running worker loop [w${workerInstance.workerIndex}] for jobs "${names.join(", ")}"...`
|
|
737
819
|
);
|
|
738
|
-
const jobToRun = await this.jobsRepo.getJobAndLock(names, config.
|
|
820
|
+
const jobToRun = await this.jobsRepo.getJobAndLock(names, config.defaultLockTime);
|
|
739
821
|
if (!jobToRun) {
|
|
740
822
|
import_logger4.logger.debug("No job to run");
|
|
741
823
|
return false;
|
|
742
824
|
}
|
|
743
825
|
import_logger4.logger.debug(`Got job [w${workerInstance.workerIndex}] to run:`, jobToRun);
|
|
744
|
-
|
|
826
|
+
const executeConfig = {
|
|
827
|
+
jobs: config.jobs,
|
|
828
|
+
maxTries: config.maxTries,
|
|
829
|
+
onMaxTriesReached: config.onMaxTriesReached
|
|
830
|
+
};
|
|
831
|
+
await this.executor.executeJob(executeConfig, jobToRun, workerInstance.respawn);
|
|
745
832
|
return true;
|
|
746
833
|
}
|
|
747
834
|
async startWorker(config, workerInstance) {
|
|
@@ -811,16 +898,16 @@ var WorkerService = class {
|
|
|
811
898
|
this.startANewWorker(config, workersInstance);
|
|
812
899
|
}
|
|
813
900
|
}
|
|
901
|
+
/**
|
|
902
|
+
* Starts the job workers with the provided configuration.
|
|
903
|
+
* @param userConfig - Configuration for the workers. Required fields: jobs, maxTries, onMaxTriesReached
|
|
904
|
+
*/
|
|
814
905
|
startWorkers(userConfig) {
|
|
815
|
-
const
|
|
816
|
-
jobs: {},
|
|
906
|
+
const config = {
|
|
817
907
|
cooldownPeriod: 100,
|
|
818
908
|
pollInterval: 3e3,
|
|
819
909
|
workersCount: 4,
|
|
820
|
-
|
|
821
|
-
};
|
|
822
|
-
const config = {
|
|
823
|
-
...defaultConfig,
|
|
910
|
+
defaultLockTime: 30 * 1e3,
|
|
824
911
|
...userConfig
|
|
825
912
|
};
|
|
826
913
|
setNameToJobs(config.jobs);
|
|
@@ -978,6 +1065,7 @@ var scheduleJobs = (jobs) => {
|
|
|
978
1065
|
EventJob,
|
|
979
1066
|
HistoryRecordSchema,
|
|
980
1067
|
JobRecordSchema,
|
|
1068
|
+
JobStatusEnum,
|
|
981
1069
|
Jobs,
|
|
982
1070
|
RecurrentJob,
|
|
983
1071
|
createEventJob,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/services/EventsService.ts","../src/repos/JobsRepo.ts","../src/types/JobRecord.ts","../src/services/getNextRunDate.ts","../src/services/WorkerService.ts","../../../node_modules/.pnpm/rambdax@11.3.1/node_modules/rambdax/src/_internals/isInteger.js","../../../node_modules/.pnpm/rambdax@11.3.1/node_modules/rambdax/src/_internals/createPath.js","../../../node_modules/.pnpm/rambdax@11.3.1/node_modules/rambdax/src/_internals/compare.js","../../../node_modules/.pnpm/rambdax@11.3.1/node_modules/rambdax/src/_internals/includes.js","../../../node_modules/.pnpm/rambdax@11.3.1/node_modules/rambdax/src/omit.js","../../../node_modules/.pnpm/rambdax@11.3.1/node_modules/rambdax/src/range.js","../src/services/Executor.ts","../src/repos/JobsHistoryRepo.ts","../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: Partial<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, MongoDB, MongoCollection} from '@orion-js/mongodb'\nimport {ScheduleJobRecordOptions, ScheduleJobsResult} from '../types/Events'\nimport {JobRecord} from '../types/JobRecord'\nimport {JobDefinitionWithName, RecurrentJobDefinition} from '../types/JobsDefinition'\nimport {JobToRun} from '../types/Worker'\nimport {Repository} from '@orion-js/mongodb'\nimport {JobRecordSchema} from '../types/JobRecord'\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 },\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\n if (job.lockedUntil) {\n logger.info(`Running job \"${job.jobName}\" that was staled`)\n 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 }\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 async extendLockTime(jobId: string, extraTime: number) {\n const lockedUntil = new Date(Date.now() + extraTime)\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\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\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 {Inject, Service} from '@orion-js/services'\nimport {range} from 'rambdax'\nimport {JobsRepo} from '../repos/JobsRepo'\nimport {JobDefinitionWithName, JobsDefinition} from '../types/JobsDefinition'\nimport {StartWorkersConfig} from '../types/StartConfig'\nimport {sleep} from '@orion-js/helpers'\nimport {Executor} from './Executor'\nimport {WorkerInstance, WorkersInstance} from '../types/Worker'\nimport {logger} from '@orion-js/logger'\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 async runWorkerLoop(config: StartWorkersConfig, workerInstance: WorkerInstance) {\n const names = this.getJobNames(config.jobs)\n logger.debug(\n `Running worker loop [w${workerInstance.workerIndex}] for jobs \"${names.join(', ')}\"...`,\n )\n const jobToRun = await this.jobsRepo.getJobAndLock(names, config.lockTime)\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 await this.executor.executeJob(config.jobs, jobToRun, workerInstance.respawn)\n\n return true\n }\n\n async startWorker(config: StartWorkersConfig, workerInstance: WorkerInstance) {\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(config, workerInstance)\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 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(config: StartWorkersConfig, workersInstance: WorkersInstance) {\n const workerIndex = workersInstance.workers.length\n\n logger.info(`Starting worker [w${workerIndex}]`)\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.stop()\n await this.startANewWorker(config, workersInstance)\n },\n }\n\n const workerPromise = this.startWorker(config, workerInstance)\n\n workerInstance.promise = workerPromise\n workersInstance.workers.push(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 for (const _ of range(0, config.workersCount)) {\n this.startANewWorker(config, workersInstance)\n }\n }\n\n startWorkers(userConfig: Partial<StartWorkersConfig>): WorkersInstance {\n const defaultConfig: StartWorkersConfig = {\n jobs: {},\n cooldownPeriod: 100,\n pollInterval: 3000,\n workersCount: 4,\n lockTime: 30 * 1000,\n }\n\n const config = {\n ...defaultConfig,\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 return Object.keys(jobs).map(name => {\n jobs[name].jobName = name\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","export function range(start, end){\n if (arguments.length === 1) return _end => range(start, _end)\n\n if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))){\n throw new TypeError('Both arguments to range must be numbers')\n }\n\n if (end < start) return []\n\n const len = end - start\n const willReturn = Array(len)\n\n for (let i = 0; i < len; i++){\n willReturn[ i ] = start + i\n }\n\n return willReturn\n}\n","import {logger, runWithOrionAsyncContext, updateOrionAsyncContext} from '@orion-js/logger'\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'\nimport {trace, SpanStatusCode} from '@opentelemetry/api'\nimport {Blackbox} from '@orion-js/schema'\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 getContext(job: JobDefinition, jobToRun: JobToRun, onStale: Function): ExecutionContext {\n let staleTimeout = setTimeout(() => onStale(), jobToRun.lockTime)\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 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 async onError(error: any, job: JobDefinition, jobToRun: JobToRun, context: ExecutionContext) {\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 if (!job.onError) {\n context.logger.error(`Error executing job \"${jobToRun.name}\"`, {error})\n await scheduleRecurrent()\n return\n }\n context.logger.info(`Error executing job \"${jobToRun.name}\"`, {error})\n\n const result = await job.onError(error, jobToRun.params, context)\n\n if (result.action === 'dismiss') {\n await scheduleRecurrent()\n return\n }\n\n if (result.action === 'retry') {\n await this.jobsRepo.scheduleNextRun({\n jobId: jobToRun.jobId,\n nextRunAt: getNextRunDate(result),\n addTries: true,\n priority: job.type === 'recurrent' ? job.priority : jobToRun.priority,\n })\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(jobs: JobsDefinition, jobToRun: JobToRun, respawnWorker: Function) {\n const job = this.getJobDefinition(jobToRun, jobs)\n if (!job) return\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 respawnWorker()\n\n this.saveExecution({\n startedAt,\n status: 'stale',\n result: null,\n errorMessage: null,\n job,\n jobToRun,\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 params: jobToRun.params,\n }\n\n await runWithOrionAsyncContext(extraContext, async () => {\n try {\n // Inject async context update\n updateOrionAsyncContext({\n jobName: jobToRun.name,\n params: jobToRun.params,\n })\n const result = await job.resolve(jobToRun.params, context)\n context.clearStaleTimeout()\n\n this.saveExecution({\n startedAt,\n status: 'success',\n result: result || null,\n errorMessage: null,\n job,\n jobToRun,\n })\n\n await this.afterExecutionSuccess(job, jobToRun, context)\n } catch (error) {\n context.clearStaleTimeout()\n this.saveExecution({\n startedAt,\n status: 'error',\n result: null,\n errorMessage: (error as Error).message,\n job,\n jobToRun,\n })\n\n await this.onError(error, job, jobToRun, context)\n }\n })\n } catch (error) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 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","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>>()\n\nexport function Jobs() {\n return (target: any, context: ClassDecoratorContext<any>) => {\n Service()(target, context)\n\n context.addInitializer(function (this) {\n serviceMetadata.set(this, {_serviceType: 'jobs'})\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 context.addInitializer(function (this) {\n const jobs = jobsMetadata.get(this) || {}\n\n if (context.kind === 'method') {\n jobs[propertyKey] = defineJob({\n ...options,\n type: 'recurrent',\n resolve: this[propertyKey].bind(this),\n })\n }\n\n if (context.kind === 'field') {\n jobs[propertyKey] = this[propertyKey]\n }\n\n jobsMetadata.set(this, jobs)\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 context.addInitializer(function (this) {\n const jobs = jobsMetadata.get(this) || {}\n\n if (context.kind === 'method') {\n jobs[propertyKey] = createEventJob({\n ...options,\n resolve: this[propertyKey].bind(this),\n })\n }\n\n if (context.kind === 'field') {\n jobs[propertyKey] = this[propertyKey]\n }\n\n jobsMetadata.set(this, jobs)\n })\n\n return method\n }\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 const jobsMap = jobsMetadata.get(instance) || {}\n\n return jobsMap\n}\n\n/**\n * Logs\n * after event job {\n job1: { type: 'event', resolve: [Function: bound job1] AsyncFunction }\n}\nbefore recurrent job Map(1) {\n ExampleJobsService {} => {\n job1: { type: 'event', resolve: [Function: bound job1] AsyncFunction }\n }\n}\nbefore recurrent job undefined\nafter recurrent job {\n job2: {\n runEvery: 1000,\n type: 'recurrent',\n resolve: [Function: bound job2] AsyncFunction,\n priority: 100\n }\n}\n{\n serviceJobs: {\n job2: {\n runEvery: 1000,\n type: 'recurrent',\n resolve: [Function: bound job2] AsyncFunction,\n priority: 100\n }\n }\n}\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","import_mongodb","_init","import_services","import_helpers","import_logger","import_services","import_mongodb","import_schema","_init","_jobsRepo_dec","_init","import_logger","_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","../../../node_modules/.pnpm/rambdax@11.3.1/node_modules/rambdax/src/_internals/isInteger.js","../../../node_modules/.pnpm/rambdax@11.3.1/node_modules/rambdax/src/_internals/createPath.js","../../../node_modules/.pnpm/rambdax@11.3.1/node_modules/rambdax/src/_internals/compare.js","../../../node_modules/.pnpm/rambdax@11.3.1/node_modules/rambdax/src/_internals/includes.js","../../../node_modules/.pnpm/rambdax@11.3.1/node_modules/rambdax/src/omit.js","../../../node_modules/.pnpm/rambdax@11.3.1/node_modules/rambdax/src/range.js","../src/services/Executor.ts","../src/repos/JobsHistoryRepo.ts","../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, MongoDB, MongoCollection} from '@orion-js/mongodb'\nimport {ScheduleJobRecordOptions, ScheduleJobsResult} from '../types/Events'\nimport {JobRecord} from '../types/JobRecord'\nimport {JobDefinitionWithName, RecurrentJobDefinition} from '../types/JobsDefinition'\nimport {JobToRun} from '../types/Worker'\nimport {Repository} from '@orion-js/mongodb'\nimport {JobRecordSchema} from '../types/JobRecord'\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\n if (job.lockedUntil) {\n logger.info(`Running job \"${job.jobName}\" that was staled`)\n 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 }\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 {Inject, Service} from '@orion-js/services'\nimport {range} from 'rambdax'\nimport {JobsRepo} from '../repos/JobsRepo'\nimport {JobDefinitionWithName, JobsDefinition} from '../types/JobsDefinition'\nimport {StartWorkersConfig} from '../types/StartConfig'\nimport {sleep} from '@orion-js/helpers'\nimport {Executor, ExecuteJobConfig} from './Executor'\nimport {WorkerInstance, WorkersInstance} from '../types/Worker'\nimport {logger} from '@orion-js/logger'\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 async runWorkerLoop(config: StartWorkersConfig, workerInstance: WorkerInstance) {\n const names = this.getJobNames(config.jobs)\n logger.debug(\n `Running worker loop [w${workerInstance.workerIndex}] for jobs \"${names.join(', ')}\"...`,\n )\n const jobToRun = await this.jobsRepo.getJobAndLock(names, config.defaultLockTime)\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 // Build the execution config from the worker config\n const executeConfig: ExecuteJobConfig = {\n jobs: config.jobs,\n maxTries: config.maxTries,\n onMaxTriesReached: config.onMaxTriesReached,\n }\n\n await this.executor.executeJob(executeConfig, jobToRun, workerInstance.respawn)\n\n return true\n }\n\n async startWorker(config: StartWorkersConfig, workerInstance: WorkerInstance) {\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(config, workerInstance)\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 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(config: StartWorkersConfig, workersInstance: WorkersInstance) {\n const workerIndex = workersInstance.workers.length\n\n logger.info(`Starting worker [w${workerIndex}]`)\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.stop()\n await this.startANewWorker(config, workersInstance)\n },\n }\n\n const workerPromise = this.startWorker(config, workerInstance)\n\n workerInstance.promise = workerPromise\n workersInstance.workers.push(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 for (const _ of range(0, config.workersCount)) {\n this.startANewWorker(config, workersInstance)\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 return Object.keys(jobs).map(name => {\n jobs[name].jobName = name\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","export function range(start, end){\n if (arguments.length === 1) return _end => range(start, _end)\n\n if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))){\n throw new TypeError('Both arguments to range must be numbers')\n }\n\n if (end < start) return []\n\n const len = end - start\n const willReturn = Array(len)\n\n for (let i = 0; i < len; i++){\n willReturn[ i ] = start + i\n }\n\n return willReturn\n}\n","import {logger, runWithOrionAsyncContext, updateOrionAsyncContext} from '@orion-js/logger'\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'\nimport {trace, SpanStatusCode} from '@opentelemetry/api'\nimport {Blackbox} from '@orion-js/schema'\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 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 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 context: ExecutionContext,\n onMaxTriesReached: (job: JobToRun) => Promise<void>,\n ) {\n context.logger.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 context.logger.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, context, 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, context, 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 // 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 respawnWorker()\n\n this.saveExecution({\n startedAt,\n status: 'stale',\n result: null,\n errorMessage: null,\n job,\n jobToRun,\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 params: jobToRun.params,\n }\n\n await runWithOrionAsyncContext(extraContext, async () => {\n try {\n // Inject async context update\n updateOrionAsyncContext({\n jobName: jobToRun.name,\n params: jobToRun.params,\n })\n const result = await job.resolve(jobToRun.params, context)\n context.clearStaleTimeout()\n\n this.saveExecution({\n startedAt,\n status: 'success',\n result: result || null,\n errorMessage: null,\n job,\n jobToRun,\n })\n\n await this.afterExecutionSuccess(job, jobToRun, context)\n } catch (error) {\n context.clearStaleTimeout()\n this.saveExecution({\n startedAt,\n status: 'error',\n result: null,\n errorMessage: (error as Error).message,\n job,\n jobToRun,\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","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>>()\n\nexport function Jobs() {\n return (target: any, context: ClassDecoratorContext<any>) => {\n Service()(target, context)\n\n context.addInitializer(function (this) {\n serviceMetadata.set(this, {_serviceType: 'jobs'})\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 context.addInitializer(function (this) {\n const jobs = jobsMetadata.get(this) || {}\n\n if (context.kind === 'method') {\n jobs[propertyKey] = defineJob({\n ...options,\n type: 'recurrent',\n resolve: this[propertyKey].bind(this),\n })\n }\n\n if (context.kind === 'field') {\n jobs[propertyKey] = this[propertyKey]\n }\n\n jobsMetadata.set(this, jobs)\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 context.addInitializer(function (this) {\n const jobs = jobsMetadata.get(this) || {}\n\n if (context.kind === 'method') {\n jobs[propertyKey] = createEventJob({\n ...options,\n resolve: this[propertyKey].bind(this),\n })\n }\n\n if (context.kind === 'field') {\n jobs[propertyKey] = this[propertyKey]\n }\n\n jobsMetadata.set(this, jobs)\n })\n\n return method\n }\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 const jobsMap = jobsMetadata.get(instance) || {}\n\n return jobsMap\n}\n\n/**\n * Logs\n * after event job {\n job1: { type: 'event', resolve: [Function: bound job1] AsyncFunction }\n}\nbefore recurrent job Map(1) {\n ExampleJobsService {} => {\n job1: { type: 'event', resolve: [Function: bound job1] AsyncFunction }\n }\n}\nbefore recurrent job undefined\nafter recurrent job {\n job2: {\n runEvery: 1000,\n type: 'recurrent',\n resolve: [Function: bound job2] AsyncFunction,\n priority: 100\n }\n}\n{\n serviceJobs: {\n job2: {\n runEvery: 1000,\n type: 'recurrent',\n resolve: [Function: bound job2] AsyncFunction,\n priority: 100\n }\n }\n}\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","import_mongodb","_init","import_services","import_helpers","import_logger","import_services","import_mongodb","import_schema","_init","_jobsRepo_dec","_init","import_logger","_jobsRepo_dec","_init","import_services","import_schema","parse"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -123,6 +123,12 @@ declare const HistoryRecordSchema: {
|
|
|
123
123
|
};
|
|
124
124
|
type HistoryRecord = InferSchemaType<typeof HistoryRecordSchema>;
|
|
125
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Enum representing the status of a job record.
|
|
128
|
+
* - 'pending': Job is active and can be executed (default for existing records)
|
|
129
|
+
* - 'maxTriesReached': Job has exhausted all retry attempts and won't be executed
|
|
130
|
+
*/
|
|
131
|
+
declare const JobStatusEnum: _orion_js_schema.FieldType<"pending" | "maxTriesReached">;
|
|
126
132
|
declare const JobRecordSchema: {
|
|
127
133
|
_id: {
|
|
128
134
|
type: "string";
|
|
@@ -159,6 +165,14 @@ declare const JobRecordSchema: {
|
|
|
159
165
|
type: "blackbox";
|
|
160
166
|
optional: true;
|
|
161
167
|
};
|
|
168
|
+
/**
|
|
169
|
+
* Status of the job. Optional for backwards compatibility with existing records.
|
|
170
|
+
* Records without this field are treated as 'pending'.
|
|
171
|
+
*/
|
|
172
|
+
status: {
|
|
173
|
+
type: _orion_js_schema.FieldType<"pending" | "maxTriesReached">;
|
|
174
|
+
optional: true;
|
|
175
|
+
};
|
|
162
176
|
};
|
|
163
177
|
type JobRecord = InferSchemaType<typeof JobRecordSchema>;
|
|
164
178
|
|
|
@@ -226,6 +240,18 @@ interface BaseJobDefinition {
|
|
|
226
240
|
* This is set automatically when the job is passed to startWorkers.
|
|
227
241
|
*/
|
|
228
242
|
jobName?: string;
|
|
243
|
+
/**
|
|
244
|
+
* Time in milliseconds to lock this specific job for execution.
|
|
245
|
+
* Overrides the defaultLockTime set in startWorkers config.
|
|
246
|
+
* If not set, the defaultLockTime from config will be used.
|
|
247
|
+
*/
|
|
248
|
+
lockTime?: number;
|
|
249
|
+
/**
|
|
250
|
+
* Maximum number of tries for this specific job before it is marked as 'maxTriesReached'.
|
|
251
|
+
* Overrides the global maxTries set in startWorkers config.
|
|
252
|
+
* If not set, the global maxTries from config will be used.
|
|
253
|
+
*/
|
|
254
|
+
maxTries?: number;
|
|
229
255
|
}
|
|
230
256
|
interface RecurrentJobDefinition extends BaseJobDefinition {
|
|
231
257
|
/**
|
|
@@ -294,26 +320,38 @@ interface StartWorkersConfig {
|
|
|
294
320
|
* Object map of the jobs that this workers will execute
|
|
295
321
|
*/
|
|
296
322
|
jobs: JobsDefinition;
|
|
323
|
+
/**
|
|
324
|
+
* Maximum number of tries for a job before it is marked as 'maxTriesReached'.
|
|
325
|
+
* This is a required global default that can be overridden per job definition.
|
|
326
|
+
*/
|
|
327
|
+
maxTries: number;
|
|
328
|
+
/**
|
|
329
|
+
* Callback invoked when a job reaches its maximum tries limit.
|
|
330
|
+
* Use this to notify administrators (e.g., send an email alert).
|
|
331
|
+
* The job will remain in the database with status 'maxTriesReached'.
|
|
332
|
+
*/
|
|
333
|
+
onMaxTriesReached: (job: JobToRun) => Promise<void>;
|
|
297
334
|
/**
|
|
298
335
|
* Time in milliseconds to wait between each look without results for a job
|
|
299
336
|
* to run at the database. Default is 3000.
|
|
300
337
|
*/
|
|
301
|
-
pollInterval
|
|
338
|
+
pollInterval?: number;
|
|
302
339
|
/**
|
|
303
340
|
* Time in milliseconds to wait too look for a job after a job execution. Default is 100.
|
|
304
341
|
*/
|
|
305
|
-
cooldownPeriod
|
|
342
|
+
cooldownPeriod?: number;
|
|
306
343
|
/**
|
|
307
344
|
* Number of workers to start. Default is 1.
|
|
308
345
|
*/
|
|
309
|
-
workersCount
|
|
346
|
+
workersCount?: number;
|
|
310
347
|
/**
|
|
311
|
-
*
|
|
348
|
+
* Default time in milliseconds to lock a job for execution. Default is 30000 (30 seconds).
|
|
312
349
|
* If a job is locked for longer than this time, it will be considered as failed.
|
|
313
350
|
* This is to prevent a job from being executed multiple times at the same time.
|
|
314
351
|
* You can extend this time inside a job by calling extendLockTime from context.
|
|
352
|
+
* Individual jobs can override this value by setting their own lockTime.
|
|
315
353
|
*/
|
|
316
|
-
|
|
354
|
+
defaultLockTime?: number;
|
|
317
355
|
}
|
|
318
356
|
|
|
319
357
|
declare class JobsHistoryRepo {
|
|
@@ -333,7 +371,17 @@ declare class JobsRepo {
|
|
|
333
371
|
priority: number;
|
|
334
372
|
}): Promise<void>;
|
|
335
373
|
deleteEventJob(jobId: string): Promise<void>;
|
|
374
|
+
/**
|
|
375
|
+
* Marks a job as having reached its maximum tries limit.
|
|
376
|
+
* The job will remain in the database but won't be picked up for execution.
|
|
377
|
+
*/
|
|
378
|
+
markJobAsMaxTriesReached(jobId: string): Promise<void>;
|
|
336
379
|
extendLockTime(jobId: string, extraTime: number): Promise<void>;
|
|
380
|
+
/**
|
|
381
|
+
* Updates the lock time for a job to the specified duration from now.
|
|
382
|
+
* Can be used to both extend or shorten the lock time.
|
|
383
|
+
*/
|
|
384
|
+
updateLockTime(jobId: string, lockDuration: number): Promise<void>;
|
|
337
385
|
unlockAllJobs(): Promise<number>;
|
|
338
386
|
ensureJobRecord(job: JobDefinitionWithName): Promise<void>;
|
|
339
387
|
scheduleJob(options: ScheduleJobRecordOptions): Promise<void>;
|
|
@@ -360,7 +408,7 @@ declare const defineJob: (options: CreateJobOptions & {
|
|
|
360
408
|
|
|
361
409
|
declare const jobsHistoryRepo: JobsHistoryRepo;
|
|
362
410
|
declare const jobsRepo: JobsRepo;
|
|
363
|
-
declare const startWorkers: (config:
|
|
411
|
+
declare const startWorkers: (config: StartWorkersConfig) => WorkersInstance;
|
|
364
412
|
/**
|
|
365
413
|
* @deprecated Use the event job definition.schedule method instead.
|
|
366
414
|
*/
|
|
@@ -371,4 +419,4 @@ declare const scheduleJob: <TParamsSchema extends SchemaInAnyOrionForm = any>(op
|
|
|
371
419
|
*/
|
|
372
420
|
declare const scheduleJobs: <TParamsSchema extends SchemaInAnyOrionForm = any>(jobs: ScheduleJobsOptions<TParamsSchema>) => Promise<ScheduleJobsResult>;
|
|
373
421
|
|
|
374
|
-
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, 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 };
|
|
422
|
+
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 };
|