@orion-js/dogs 4.3.5 → 4.4.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.d.ts CHANGED
@@ -1,445 +1,14 @@
1
- import * as _orion_js_schema from '@orion-js/schema';
2
- import { SchemaInAnyOrionForm, Blackbox, InferSchemaType } from '@orion-js/schema';
3
- import { OrionLogger } from '@orion-js/logger';
4
- import { Collection, MongoDB } from '@orion-js/mongodb';
5
-
6
- /**
7
- * Base type for schedule params that varies based on schema presence
8
- */
9
- type ScheduleJobParamsType<TParamsSchema extends SchemaInAnyOrionForm> = TParamsSchema extends undefined ? {
10
- params?: Blackbox;
11
- } : {
12
- params: InferSchemaType<TParamsSchema>;
13
- };
14
- /**
15
- * Common options shared by all schedule job variants (without name)
16
- */
17
- type ScheduleJobCommonOptions = {
18
- priority?: number;
19
- uniqueIdentifier?: string;
20
- };
21
- /**
22
- * Schedule options without name - used by job definition's schedule method.
23
- * This is a distributive type that properly handles runIn/runAt variants.
24
- */
25
- type ScheduleJobOptionsWithoutName<TParamsSchema extends SchemaInAnyOrionForm = any> = (ScheduleJobCommonOptions & ScheduleJobParamsType<TParamsSchema> & {
26
- runIn: number;
27
- }) | (ScheduleJobCommonOptions & ScheduleJobParamsType<TParamsSchema> & {
28
- runAt: Date;
29
- }) | (ScheduleJobCommonOptions & ScheduleJobParamsType<TParamsSchema>);
30
- /**
31
- * Full schedule options including job name - used by direct scheduleJob calls
32
- */
33
- type ScheduleJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = ScheduleJobOptionsWithoutName<TParamsSchema> & {
34
- name: string;
35
- };
36
- /**
37
- * Legacy type aliases for backwards compatibility
38
- */
39
- type ScheduleJobOptionsBase<TParamsSchema extends SchemaInAnyOrionForm> = {
40
- name: string;
41
- priority?: number;
42
- uniqueIdentifier?: string;
43
- } & ScheduleJobParamsType<TParamsSchema>;
44
- type ScheduleJobOptionsRunIn<TParamsSchema extends SchemaInAnyOrionForm> = ScheduleJobOptionsBase<TParamsSchema> & {
45
- runIn: number;
46
- };
47
- type ScheduleJobOptionsRunAt<TParamsSchema extends SchemaInAnyOrionForm> = ScheduleJobOptionsBase<TParamsSchema> & {
48
- runAt: Date;
49
- };
50
- interface ScheduleJobRecordOptions {
51
- name: string;
52
- params: Blackbox;
53
- nextRunAt: Date;
54
- priority: number;
55
- uniqueIdentifier?: string;
56
- }
57
- type ScheduleJobsOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = ScheduleJobOptions<TParamsSchema>[];
58
- interface ScheduleJobsResult {
59
- scheduledCount: number;
60
- skippedCount: number;
61
- errors: Array<{
62
- index: number;
63
- error: Error;
64
- job: ScheduleJobOptions;
65
- }>;
66
- }
67
-
68
- declare const HistoryRecordSchema: {
69
- _id: {
70
- type: "string";
71
- };
72
- jobId: {
73
- type: "string";
74
- };
75
- executionId: {
76
- type: "string";
77
- };
78
- jobName: {
79
- type: "string";
80
- };
81
- type: {
82
- type: "string";
83
- };
84
- priority: {
85
- type: "number";
86
- };
87
- tries: {
88
- type: "number";
89
- };
90
- uniqueIdentifier: {
91
- type: "string";
92
- optional: true;
93
- };
94
- startedAt: {
95
- type: "date";
96
- };
97
- endedAt: {
98
- type: "date";
99
- };
100
- duration: {
101
- type: "number";
102
- };
103
- expiresAt: {
104
- type: "date";
105
- optional: true;
106
- };
107
- status: {
108
- type: "string";
109
- enum: string[];
110
- };
111
- errorMessage: {
112
- type: "string";
113
- optional: true;
114
- };
115
- params: {
116
- type: "blackbox";
117
- optional: true;
118
- };
119
- result: {
120
- type: "any";
121
- optional: true;
122
- };
123
- };
124
- type HistoryRecord = InferSchemaType<typeof HistoryRecordSchema>;
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">;
132
- declare const JobRecordSchema: {
133
- _id: {
134
- type: "string";
135
- };
136
- jobName: {
137
- type: "string";
138
- };
139
- type: {
140
- type: _orion_js_schema.FieldType<"recurrent" | "event">;
141
- };
142
- priority: {
143
- type: "number";
144
- };
145
- uniqueIdentifier: {
146
- type: "string";
147
- optional: true;
148
- };
149
- nextRunAt: {
150
- type: "date";
151
- };
152
- lastRunAt: {
153
- type: "date";
154
- optional: true;
155
- };
156
- lockedUntil: {
157
- type: "date";
158
- optional: true;
159
- };
160
- tries: {
161
- type: "number";
162
- optional: true;
163
- };
164
- params: {
165
- type: "blackbox";
166
- optional: true;
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
- };
176
- };
177
- type JobRecord = InferSchemaType<typeof JobRecordSchema>;
178
-
179
- interface JobToRun {
180
- jobId: string;
181
- executionId: string;
182
- name: string;
183
- type: 'event' | 'recurrent';
184
- params: Blackbox;
185
- tries: number;
186
- lockTime: number;
187
- priority: number;
188
- uniqueIdentifier?: string;
189
- wasStale?: boolean;
190
- }
191
- interface ExecutionContext {
192
- record: JobToRun;
193
- definition: JobDefinition;
194
- tries: number;
195
- logger: OrionLogger;
196
- extendLockTime: (extraTime: number) => Promise<void>;
197
- clearStaleTimeout: () => void;
198
- }
199
- interface WorkerInstance {
200
- running: boolean;
201
- workerIndex: number;
202
- stop: () => Promise<void>;
203
- respawn: () => Promise<void>;
204
- promise?: Promise<any>;
205
- }
206
- interface WorkersInstance {
207
- running: boolean;
208
- workersCount: number;
209
- workers: WorkerInstance[];
210
- runningJobsByName: Map<string, number>;
211
- jobAcquisitionLock: Promise<void>;
212
- /**
213
- * Stop all workers and wait for them to finish
214
- */
215
- stop: () => Promise<void>;
216
- }
217
-
218
- interface JobRetryResultBase {
219
- action: 'retry' | 'dismiss';
220
- }
221
- type JobRetryResultRunIn = JobRetryResultBase & {
222
- runIn: number;
223
- };
224
- type JobRetryResultRunAt = JobRetryResultBase & {
225
- runAt: Date;
226
- };
227
- type JobRetryResult = JobRetryResultRunIn | JobRetryResultRunAt | JobRetryResultBase;
228
- interface BaseJobDefinition {
229
- /**
230
- * Called if the job fails.
231
- */
232
- onError?: (error: Error, params: Blackbox, context: ExecutionContext) => Promise<JobRetryResult>;
233
- /**
234
- * Called if the job locktime is expired. The job will be executed again.
235
- */
236
- onStale?: (params: Blackbox, context: ExecutionContext) => Promise<void>;
237
- /**
238
- * Save the executions of the job time in milliseconds. Default is 1 week. Set to 0 to disable.
239
- */
240
- saveExecutionsFor?: number;
241
- /**
242
- * The name of the job.
243
- * This is set automatically when the job is passed to startWorkers.
244
- */
245
- jobName?: string;
246
- /**
247
- * Time in milliseconds to lock this specific job for execution.
248
- * Overrides the defaultLockTime set in startWorkers config.
249
- * If not set, the defaultLockTime from config will be used.
250
- */
251
- lockTime?: number;
252
- /**
253
- * Maximum number of tries for this specific job before it is marked as 'maxTriesReached'.
254
- * Overrides the global maxTries set in startWorkers config.
255
- * If not set, the global maxTries from config will be used.
256
- */
257
- maxTries?: number;
258
- }
259
- interface RecurrentJobDefinition extends BaseJobDefinition {
260
- /**
261
- * Type of the job.
262
- */
263
- type: 'recurrent';
264
- /**
265
- * A function executed after each execution that returns the date of the next run.
266
- */
267
- getNextRun?: () => Date;
268
- /**
269
- * Run every x milliseconds. This will be ignored if getNextRun is defined.
270
- */
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;
280
- /**
281
- * The priority of the job. Higher is more priority. Default is 100.
282
- */
283
- priority?: number;
284
- /**
285
- * The function to execute when the job is executed.
286
- */
287
- resolve: (_: any, context: ExecutionContext) => Promise<Blackbox | void>;
288
- }
289
- interface EventJobDefinition<TParamsSchema extends SchemaInAnyOrionForm = any> extends BaseJobDefinition {
290
- /**
291
- * Type of the job.
292
- */
293
- type: 'event';
294
- /**
295
- * Schedule of the job. Supports optional runIn (milliseconds) or runAt (Date) for delayed execution.
296
- */
297
- schedule: (options: ScheduleJobOptionsWithoutName<TParamsSchema>) => Promise<void>;
298
- /**
299
- * Schedule multiple jobs at once. Each job supports optional runIn or runAt for delayed execution.
300
- */
301
- scheduleJobs: (jobs: Array<ScheduleJobOptionsWithoutName<TParamsSchema>>) => Promise<ScheduleJobsResult>;
302
- /**
303
- * The schema of the params of the job.
304
- */
305
- params?: TParamsSchema;
306
- /**
307
- * Maximum number of executions of this job that can run in parallel on the same server.
308
- * If not set, the job can use all available workers on the current server.
309
- */
310
- maxParallelExecutionsPerServer?: number;
311
- /**
312
- * The function to execute when the job is executed.
313
- */
314
- resolve: (params: InferSchemaType<TParamsSchema>, context: ExecutionContext) => Promise<any>;
315
- }
316
- type CreateEventJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = Omit<EventJobDefinition<TParamsSchema>, 'type' | 'schedule' | 'scheduleJobs'>;
317
- type CreateRecurrentJobBaseOptions = Omit<RecurrentJobDefinition, 'type' | 'runEvery' | 'cron' | 'timezone'>;
318
- type CreateRecurrentJobRunEveryOptions = CreateRecurrentJobBaseOptions & {
319
- /**
320
- * Run every x milliseconds.
321
- * Accepts https://github.com/jkroso/parse-duration strings.
322
- */
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;
337
- };
338
- type CreateRecurrentJobOptions = CreateRecurrentJobRunEveryOptions | CreateRecurrentJobCronOptions;
339
- type CreateJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = CreateEventJobOptions<TParamsSchema> | CreateRecurrentJobOptions;
340
- type JobDefinition<TParamsSchema extends SchemaInAnyOrionForm = any> = RecurrentJobDefinition | EventJobDefinition<TParamsSchema>;
341
- type JobDefinitionWithName<TParamsSchema extends SchemaInAnyOrionForm = any> = JobDefinition<TParamsSchema> & {
342
- name: string;
343
- };
344
- interface JobsDefinition {
345
- [jobName: string]: JobDefinition;
346
- }
347
-
348
- type LogLevels = 'debug' | 'info' | 'warn' | 'error' | 'none';
349
- interface StartWorkersConfig {
350
- /**
351
- * Object map of the jobs that this workers will execute
352
- */
353
- jobs: JobsDefinition;
354
- /**
355
- * Maximum number of tries for a job before it is marked as 'maxTriesReached'.
356
- * This is a required global default that can be overridden per job definition.
357
- */
358
- maxTries: number;
359
- /**
360
- * Callback invoked when a job reaches its maximum tries limit.
361
- * Use this to notify administrators (e.g., send an email alert).
362
- * The job will remain in the database with status 'maxTriesReached'.
363
- */
364
- onMaxTriesReached: (job: JobToRun) => Promise<void>;
365
- /**
366
- * Time in milliseconds to wait between each look without results for a job
367
- * to run at the database. Default is 3000.
368
- */
369
- pollInterval?: number;
370
- /**
371
- * Time in milliseconds to wait too look for a job after a job execution. Default is 100.
372
- */
373
- cooldownPeriod?: number;
374
- /**
375
- * Number of workers to start. Default is 1.
376
- */
377
- workersCount?: number;
378
- /**
379
- * Default time in milliseconds to lock a job for execution. Default is 30000 (30 seconds).
380
- * If a job is locked for longer than this time, it will be considered as failed.
381
- * This is to prevent a job from being executed multiple times at the same time.
382
- * You can extend this time inside a job by calling extendLockTime from context.
383
- * Individual jobs can override this value by setting their own lockTime.
384
- */
385
- defaultLockTime?: number;
386
- }
387
-
388
- declare class JobsHistoryRepo {
389
- history: Collection<HistoryRecord>;
390
- saveExecution(record: MongoDB.WithoutId<HistoryRecord>): Promise<void>;
391
- getExecutions(jobName: string, limit?: number, skip?: number): Promise<HistoryRecord[]>;
392
- }
393
-
394
- declare class JobsRepo {
395
- jobs: Collection<JobRecord>;
396
- getJobAndLock(jobNames: string[], lockTime: number): Promise<JobToRun>;
397
- setJobRecordPriority(jobId: string, priority: number): Promise<void>;
398
- scheduleNextRun(options: {
399
- jobId: string;
400
- nextRunAt: Date;
401
- resetTries: boolean;
402
- priority: number;
403
- }): Promise<void>;
404
- deleteEventJob(jobId: string): Promise<void>;
405
- /**
406
- * Marks a job as having reached its maximum tries limit.
407
- * The job will remain in the database but won't be picked up for execution.
408
- */
409
- markJobAsMaxTriesReached(jobId: string): Promise<void>;
410
- extendLockTime(jobId: string, extraTime: number): Promise<void>;
411
- /**
412
- * Updates the lock time for a job to the specified duration from now.
413
- * Can be used to both extend or shorten the lock time.
414
- */
415
- updateLockTime(jobId: string, lockDuration: number): Promise<void>;
416
- unlockAllJobs(): Promise<number>;
417
- ensureJobRecord(job: JobDefinitionWithName): Promise<void>;
418
- scheduleJob(options: ScheduleJobRecordOptions): Promise<void>;
419
- scheduleJobs(jobs: ScheduleJobRecordOptions[]): Promise<ScheduleJobsResult>;
420
- }
421
-
422
- declare function Jobs(): (target: any, context: ClassDecoratorContext<any>) => void;
423
- declare function RecurrentJob(): (method: any, context: ClassFieldDecoratorContext | ClassMethodDecoratorContext) => any;
424
- declare function RecurrentJob(options: Omit<RecurrentJobDefinition, 'resolve' | 'type'>): (method: any, context: ClassMethodDecoratorContext) => any;
425
- declare function EventJob(): (method: any, context: ClassFieldDecoratorContext | ClassMethodDecoratorContext) => any;
426
- declare function EventJob(options: Omit<CreateEventJobOptions<any>, 'resolve'>): (method: any, context: ClassMethodDecoratorContext) => any;
427
- declare function getServiceJobs(target: any): {
428
- [key: string]: JobDefinition;
429
- };
430
-
431
- declare function createEventJob<TParamsSchema extends SchemaInAnyOrionForm>(options: CreateEventJobOptions<TParamsSchema>): EventJobDefinition<TParamsSchema>;
432
- declare function createRecurrentJob(options: CreateRecurrentJobOptions): RecurrentJobDefinition;
433
- /**
434
- * @deprecated Use `createEventJob` or `createRecurrentJob` instead.
435
- */
436
- declare const defineJob: (options: CreateJobOptions & {
437
- type: "event" | "recurrent";
438
- }) => JobDefinition;
439
-
1
+ import { StartWorkersConfig } from './types/StartConfig';
2
+ import { ScheduleJobOptions, ScheduleJobsOptions, ScheduleJobsResult } from './types/Events';
3
+ import { JobsHistoryRepo } from './repos/JobsHistoryRepo';
4
+ import { JobsRepo } from './repos/JobsRepo';
5
+ import { SchemaInAnyOrionForm } from '@orion-js/schema';
6
+ export * from './types';
7
+ export * from './service';
8
+ export * from './defineJob';
440
9
  declare const jobsHistoryRepo: JobsHistoryRepo;
441
10
  declare const jobsRepo: JobsRepo;
442
- declare const startWorkers: (config: StartWorkersConfig) => WorkersInstance;
11
+ declare const startWorkers: (config: StartWorkersConfig) => import("./types").WorkersInstance;
443
12
  /**
444
13
  * @deprecated Use the event job definition.schedule method instead.
445
14
  */
@@ -449,5 +18,4 @@ declare const scheduleJob: <TParamsSchema extends SchemaInAnyOrionForm = any>(op
449
18
  * @deprecated Use the event job definition.scheduleJobs method instead.
450
19
  */
451
20
  declare const scheduleJobs: <TParamsSchema extends SchemaInAnyOrionForm = any>(jobs: ScheduleJobsOptions<TParamsSchema>) => Promise<ScheduleJobsResult>;
452
-
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 };
21
+ export { startWorkers, scheduleJob, scheduleJobs, jobsHistoryRepo, jobsRepo };
package/dist/index.js CHANGED
@@ -124,10 +124,12 @@ var JobsRepo = class {
124
124
  {
125
125
  jobName: { $in: jobNames },
126
126
  nextRunAt: { $lte: /* @__PURE__ */ new Date() },
127
- $or: [{ lockedUntil: { $exists: false } }, { lockedUntil: { $lte: /* @__PURE__ */ new Date() } }],
128
- // Exclude jobs that have reached max tries. Using $ne handles backwards compatibility
129
- // since records without the status field will still match (undefined !== 'maxTriesReached')
130
- status: { $ne: "maxTriesReached" }
127
+ $and: [
128
+ { $or: [{ lockedUntil: { $exists: false } }, { lockedUntil: { $lte: /* @__PURE__ */ new Date() } }] },
129
+ // Exclude event jobs that have reached max tries. Recurrent jobs keep running even
130
+ // if old records still have this status from previous versions.
131
+ { $or: [{ type: { $ne: "event" } }, { status: { $ne: "maxTriesReached" } }] }
132
+ ]
131
133
  },
132
134
  {
133
135
  $set: { lockedUntil, lastRunAt: /* @__PURE__ */ new Date() },
@@ -180,12 +182,12 @@ var JobsRepo = class {
180
182
  await this.jobs.deleteOne({ _id: jobId, type: "event" });
181
183
  }
182
184
  /**
183
- * Marks a job as having reached its maximum tries limit.
185
+ * Marks an event job as having reached its maximum tries limit.
184
186
  * The job will remain in the database but won't be picked up for execution.
185
187
  */
186
188
  async markJobAsMaxTriesReached(jobId) {
187
189
  await this.jobs.updateOne(
188
- { _id: jobId },
190
+ { _id: jobId, type: "event" },
189
191
  {
190
192
  $set: { status: "maxTriesReached" },
191
193
  $unset: { lockedUntil: "" }
@@ -231,6 +233,9 @@ var JobsRepo = class {
231
233
  type: job.type,
232
234
  priority: job.priority
233
235
  },
236
+ $unset: {
237
+ status: ""
238
+ },
234
239
  $setOnInsert: {
235
240
  nextRunAt: /* @__PURE__ */ new Date()
236
241
  }
@@ -553,7 +558,7 @@ var Executor = class {
553
558
  return job;
554
559
  }
555
560
  /**
556
- * Determines the effective max tries for a job.
561
+ * Determines the effective max tries for an event job.
557
562
  * Job-specific maxTries takes precedence over the global maxTries from config.
558
563
  */
559
564
  getEffectiveMaxTries(job, globalMaxTries) {
@@ -561,7 +566,7 @@ var Executor = class {
561
566
  }
562
567
  /**
563
568
  * Handles when a job has reached its maximum retry attempts.
564
- * Marks the job in the database and invokes the onMaxTriesReached callback.
569
+ * Marks the job in the database and invokes the onMaxTriesReached callback when provided.
565
570
  */
566
571
  async handleMaxTriesReached(jobToRun, onMaxTriesReached) {
567
572
  const jobLogger = logger3.addMetadata({
@@ -572,6 +577,7 @@ var Executor = class {
572
577
  `Job "${jobToRun.name}" has exceeded max tries (${jobToRun.tries}). Marking as maxTriesReached.`
573
578
  );
574
579
  await this.jobsRepo.markJobAsMaxTriesReached(jobToRun.jobId);
580
+ if (!onMaxTriesReached) return;
575
581
  try {
576
582
  await onMaxTriesReached(jobToRun);
577
583
  } catch (callbackError) {
@@ -580,7 +586,7 @@ var Executor = class {
580
586
  });
581
587
  }
582
588
  }
583
- async onError(error, job, jobToRun, context, config) {
589
+ async onError(error, job, jobToRun, context) {
584
590
  const scheduleRecurrent = async () => {
585
591
  if (job.type === "recurrent") {
586
592
  await this.jobsRepo.scheduleNextRun({
@@ -661,10 +667,12 @@ var Executor = class {
661
667
  async executeJob(config, jobToRun, respawnWorker) {
662
668
  const job = this.getJobDefinition(jobToRun, config.jobs);
663
669
  if (!job) return;
664
- const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries);
665
- if (jobToRun.tries > effectiveMaxTries) {
666
- await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached);
667
- return;
670
+ if (job.type === "event") {
671
+ const effectiveMaxTries = this.getEffectiveMaxTries(job, config.maxTries);
672
+ if (typeof effectiveMaxTries === "number" && jobToRun.tries > effectiveMaxTries) {
673
+ await this.handleMaxTriesReached(jobToRun, config.onMaxTriesReached);
674
+ return;
675
+ }
668
676
  }
669
677
  const effectiveLockTime = this.getEffectiveLockTime(job, jobToRun);
670
678
  if (effectiveLockTime !== jobToRun.lockTime) {
@@ -733,7 +741,7 @@ var Executor = class {
733
741
  }).catch((saveError) => {
734
742
  context.logger.error("Error saving failed execution history", { error: saveError });
735
743
  });
736
- await this.onError(error, job, jobToRun, context, config);
744
+ await this.onError(error, job, jobToRun, context);
737
745
  }
738
746
  });
739
747
  } catch (error) {
@@ -920,7 +928,7 @@ var WorkerService = class {
920
928
  }
921
929
  /**
922
930
  * Starts the job workers with the provided configuration.
923
- * @param userConfig - Configuration for the workers. Required fields: jobs, maxTries, onMaxTriesReached
931
+ * @param userConfig - Configuration for the workers. Required field: jobs
924
932
  */
925
933
  startWorkers(userConfig) {
926
934
  const config = {
@@ -992,16 +1000,20 @@ function createEventJob(options) {
992
1000
  return jobDefinition;
993
1001
  }
994
1002
  function createRecurrentJob(options) {
995
- if ("cron" in options && options.cron && !options.timezone) {
1003
+ const recurrentOptions = {
1004
+ ...options
1005
+ };
1006
+ delete recurrentOptions.maxTries;
1007
+ if ("cron" in recurrentOptions && recurrentOptions.cron && !recurrentOptions.timezone) {
996
1008
  throw new Error("Cron recurrent jobs require a timezone");
997
1009
  }
998
- if ("cron" in options && options.cron) {
999
- CronExpressionParser2.parse(options.cron, { tz: options.timezone }).next();
1010
+ if ("cron" in recurrentOptions && recurrentOptions.cron) {
1011
+ CronExpressionParser2.parse(recurrentOptions.cron, { tz: recurrentOptions.timezone }).next();
1000
1012
  }
1001
- const runEvery = "runEvery" in options ? typeof options.runEvery === "string" ? parse(options.runEvery) : options.runEvery : void 0;
1013
+ const runEvery = "runEvery" in recurrentOptions ? typeof recurrentOptions.runEvery === "string" ? parse(recurrentOptions.runEvery) : recurrentOptions.runEvery : void 0;
1002
1014
  const jobDefinition = {
1003
- ...options,
1004
- priority: options.priority ?? 100,
1015
+ ...recurrentOptions,
1016
+ priority: recurrentOptions.priority ?? 100,
1005
1017
  type: "recurrent",
1006
1018
  runEvery
1007
1019
  };