@orion-js/dogs 4.3.6 → 4.5.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.
@@ -0,0 +1,10 @@
1
+ import { SchemaInAnyOrionForm } from '@orion-js/schema';
2
+ import { CreateEventJobOptions, CreateJobOptions, CreateRecurrentJobOptions, EventJobDefinition, JobDefinition, RecurrentJobDefinition } from '../types/JobsDefinition';
3
+ export declare function createEventJob<TParamsSchema extends SchemaInAnyOrionForm>(options: CreateEventJobOptions<TParamsSchema>): EventJobDefinition<TParamsSchema>;
4
+ export declare function createRecurrentJob(options: CreateRecurrentJobOptions): RecurrentJobDefinition;
5
+ /**
6
+ * @deprecated Use `createEventJob` or `createRecurrentJob` instead.
7
+ */
8
+ export declare const defineJob: (options: CreateJobOptions & {
9
+ type: 'event' | 'recurrent';
10
+ }) => JobDefinition;
package/dist/index.d.ts CHANGED
@@ -1,345 +1,14 @@
1
- import { SchemaInAnyOrionForm, Blackbox, InferSchemaType } from '@orion-js/schema';
2
- import { OrionLogger } from '@orion-js/logger';
3
- import { Collection, MongoDB } from '@orion-js/mongodb';
4
-
5
- /**
6
- * Base type for schedule params that varies based on schema presence
7
- */
8
- type ScheduleJobParamsType<TParamsSchema extends SchemaInAnyOrionForm> = TParamsSchema extends undefined ? {
9
- params?: Blackbox;
10
- } : {
11
- params: InferSchemaType<TParamsSchema>;
12
- };
13
- /**
14
- * Common options shared by all schedule job variants (without name)
15
- */
16
- type ScheduleJobCommonOptions = {
17
- priority?: number;
18
- uniqueIdentifier?: string;
19
- };
20
- /**
21
- * Schedule options without name - used by job definition's schedule method.
22
- * This is a distributive type that properly handles runIn/runAt variants.
23
- */
24
- type ScheduleJobOptionsWithoutName<TParamsSchema extends SchemaInAnyOrionForm = any> = (ScheduleJobCommonOptions & ScheduleJobParamsType<TParamsSchema> & {
25
- runIn: number;
26
- }) | (ScheduleJobCommonOptions & ScheduleJobParamsType<TParamsSchema> & {
27
- runAt: Date;
28
- }) | (ScheduleJobCommonOptions & ScheduleJobParamsType<TParamsSchema>);
29
- /**
30
- * Full schedule options including job name - used by direct scheduleJob calls
31
- */
32
- type ScheduleJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = ScheduleJobOptionsWithoutName<TParamsSchema> & {
33
- name: string;
34
- };
35
- /**
36
- * Legacy type aliases for backwards compatibility
37
- */
38
- type ScheduleJobOptionsBase<TParamsSchema extends SchemaInAnyOrionForm> = {
39
- name: string;
40
- priority?: number;
41
- uniqueIdentifier?: string;
42
- } & ScheduleJobParamsType<TParamsSchema>;
43
- type ScheduleJobOptionsRunIn<TParamsSchema extends SchemaInAnyOrionForm> = ScheduleJobOptionsBase<TParamsSchema> & {
44
- runIn: number;
45
- };
46
- type ScheduleJobOptionsRunAt<TParamsSchema extends SchemaInAnyOrionForm> = ScheduleJobOptionsBase<TParamsSchema> & {
47
- runAt: Date;
48
- };
49
- interface ScheduleJobRecordOptions {
50
- name: string;
51
- params: Blackbox;
52
- nextRunAt: Date;
53
- priority: number;
54
- uniqueIdentifier?: string;
55
- }
56
- type ScheduleJobsOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = ScheduleJobOptions<TParamsSchema>[];
57
- interface ScheduleJobsResult {
58
- scheduledCount: number;
59
- skippedCount: number;
60
- errors: Array<{
61
- index: number;
62
- error: Error;
63
- job: ScheduleJobOptions;
64
- }>;
65
- }
66
-
67
- declare const HistoryRecordSchema: any;
68
- type HistoryRecord = InferSchemaType<typeof HistoryRecordSchema>;
69
-
70
- /**
71
- * Enum representing the status of a job record.
72
- * - 'pending': Job is active and can be executed (default for existing records)
73
- * - 'maxTriesReached': Event job has exhausted all retry attempts and won't be executed
74
- */
75
- declare const JobStatusEnum: any;
76
- declare const JobRecordSchema: any;
77
- type JobRecord = InferSchemaType<typeof JobRecordSchema>;
78
-
79
- interface JobToRun {
80
- jobId: string;
81
- executionId: string;
82
- name: string;
83
- type: 'event' | 'recurrent';
84
- params: Blackbox;
85
- tries: number;
86
- lockTime: number;
87
- priority: number;
88
- uniqueIdentifier?: string;
89
- wasStale?: boolean;
90
- }
91
- interface ExecutionContext {
92
- record: JobToRun;
93
- definition: JobDefinition;
94
- tries: number;
95
- logger: OrionLogger;
96
- extendLockTime: (extraTime: number) => Promise<void>;
97
- clearStaleTimeout: () => void;
98
- }
99
- interface WorkerInstance {
100
- running: boolean;
101
- workerIndex: number;
102
- stop: () => Promise<void>;
103
- respawn: () => Promise<void>;
104
- promise?: Promise<any>;
105
- }
106
- interface WorkersInstance {
107
- running: boolean;
108
- workersCount: number;
109
- workers: WorkerInstance[];
110
- runningJobsByName: Map<string, number>;
111
- jobAcquisitionLock: Promise<void>;
112
- /**
113
- * Stop all workers and wait for them to finish
114
- */
115
- stop: () => Promise<void>;
116
- }
117
-
118
- interface JobRetryResultBase {
119
- action: 'retry' | 'dismiss';
120
- }
121
- type JobRetryResultRunIn = JobRetryResultBase & {
122
- runIn: number;
123
- };
124
- type JobRetryResultRunAt = JobRetryResultBase & {
125
- runAt: Date;
126
- };
127
- type JobRetryResult = JobRetryResultRunIn | JobRetryResultRunAt | JobRetryResultBase;
128
- interface BaseJobDefinition {
129
- /**
130
- * Called if the job fails.
131
- */
132
- onError?: (error: Error, params: Blackbox, context: ExecutionContext) => Promise<JobRetryResult>;
133
- /**
134
- * Called if the job locktime is expired. The job will be executed again.
135
- */
136
- onStale?: (params: Blackbox, context: ExecutionContext) => Promise<void>;
137
- /**
138
- * Save the executions of the job time in milliseconds. Default is 1 week. Set to 0 to disable.
139
- */
140
- saveExecutionsFor?: number;
141
- /**
142
- * The name of the job.
143
- * This is set automatically when the job is passed to startWorkers.
144
- */
145
- jobName?: string;
146
- /**
147
- * Time in milliseconds to lock this specific job for execution.
148
- * Overrides the defaultLockTime set in startWorkers config.
149
- * If not set, the defaultLockTime from config will be used.
150
- */
151
- lockTime?: number;
152
- }
153
- interface RecurrentJobDefinition extends BaseJobDefinition {
154
- /**
155
- * Type of the job.
156
- */
157
- type: 'recurrent';
158
- /**
159
- * A function executed after each execution that returns the date of the next run.
160
- */
161
- getNextRun?: () => Date;
162
- /**
163
- * Run every x milliseconds. This will be ignored if getNextRun is defined.
164
- */
165
- runEvery?: number;
166
- /**
167
- * Cron expression used to calculate the next run. Requires timezone.
168
- */
169
- cron?: string;
170
- /**
171
- * IANA timezone used to calculate cron-based schedules.
172
- */
173
- timezone?: string;
174
- /**
175
- * The priority of the job. Higher is more priority. Default is 100.
176
- */
177
- priority?: number;
178
- /**
179
- * The function to execute when the job is executed.
180
- */
181
- resolve: (_: any, context: ExecutionContext) => Promise<Blackbox | void>;
182
- }
183
- interface EventJobDefinition<TParamsSchema extends SchemaInAnyOrionForm = any> extends BaseJobDefinition {
184
- /**
185
- * Type of the job.
186
- */
187
- type: 'event';
188
- /**
189
- * Maximum number of tries for this specific event job before it is marked as 'maxTriesReached'.
190
- * Overrides the global maxTries set in startWorkers config.
191
- * If not set, the global maxTries from config will be used.
192
- */
193
- maxTries?: number;
194
- /**
195
- * Schedule of the job. Supports optional runIn (milliseconds) or runAt (Date) for delayed execution.
196
- */
197
- schedule: (options: ScheduleJobOptionsWithoutName<TParamsSchema>) => Promise<void>;
198
- /**
199
- * Schedule multiple jobs at once. Each job supports optional runIn or runAt for delayed execution.
200
- */
201
- scheduleJobs: (jobs: Array<ScheduleJobOptionsWithoutName<TParamsSchema>>) => Promise<ScheduleJobsResult>;
202
- /**
203
- * The schema of the params of the job.
204
- */
205
- params?: TParamsSchema;
206
- /**
207
- * Maximum number of executions of this job that can run in parallel on the same server.
208
- * If not set, the job can use all available workers on the current server.
209
- */
210
- maxParallelExecutionsPerServer?: number;
211
- /**
212
- * The function to execute when the job is executed.
213
- */
214
- resolve: (params: InferSchemaType<TParamsSchema>, context: ExecutionContext) => Promise<any>;
215
- }
216
- type CreateEventJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = Omit<EventJobDefinition<TParamsSchema>, 'type' | 'schedule' | 'scheduleJobs'>;
217
- type CreateRecurrentJobBaseOptions = Omit<RecurrentJobDefinition, 'type' | 'runEvery' | 'cron' | 'timezone'>;
218
- type CreateRecurrentJobRunEveryOptions = CreateRecurrentJobBaseOptions & {
219
- /**
220
- * Run every x milliseconds.
221
- * Accepts https://github.com/jkroso/parse-duration strings.
222
- */
223
- runEvery: number | string;
224
- cron?: never;
225
- timezone?: string;
226
- };
227
- type CreateRecurrentJobCronOptions = CreateRecurrentJobBaseOptions & {
228
- /**
229
- * Cron expression used to calculate the next run.
230
- */
231
- cron: string;
232
- /**
233
- * IANA timezone used to calculate cron-based schedules.
234
- */
235
- timezone: string;
236
- runEvery?: never;
237
- };
238
- type CreateRecurrentJobOptions = CreateRecurrentJobRunEveryOptions | CreateRecurrentJobCronOptions;
239
- type CreateJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = CreateEventJobOptions<TParamsSchema> | CreateRecurrentJobOptions;
240
- type JobDefinition<TParamsSchema extends SchemaInAnyOrionForm = any> = RecurrentJobDefinition | EventJobDefinition<TParamsSchema>;
241
- type JobDefinitionWithName<TParamsSchema extends SchemaInAnyOrionForm = any> = JobDefinition<TParamsSchema> & {
242
- name: string;
243
- };
244
- interface JobsDefinition {
245
- [jobName: string]: JobDefinition;
246
- }
247
-
248
- type LogLevels = 'debug' | 'info' | 'warn' | 'error' | 'none';
249
- interface StartWorkersConfig {
250
- /**
251
- * Object map of the jobs that this workers will execute
252
- */
253
- jobs: JobsDefinition;
254
- /**
255
- * Maximum number of tries for an event job before it is marked as 'maxTriesReached'.
256
- * This is a global default that can be overridden per event job definition.
257
- */
258
- maxTries?: number;
259
- /**
260
- * Callback invoked when an event job reaches its maximum tries limit.
261
- * Use this to notify administrators (e.g., send an email alert).
262
- * The job will remain in the database with status 'maxTriesReached'.
263
- */
264
- onMaxTriesReached?: (job: JobToRun) => Promise<void>;
265
- /**
266
- * Time in milliseconds to wait between each look without results for a job
267
- * to run at the database. Default is 3000.
268
- */
269
- pollInterval?: number;
270
- /**
271
- * Time in milliseconds to wait too look for a job after a job execution. Default is 100.
272
- */
273
- cooldownPeriod?: number;
274
- /**
275
- * Number of workers to start. Default is 1.
276
- */
277
- workersCount?: number;
278
- /**
279
- * Default time in milliseconds to lock a job for execution. Default is 30000 (30 seconds).
280
- * If a job is locked for longer than this time, it will be considered as failed.
281
- * This is to prevent a job from being executed multiple times at the same time.
282
- * You can extend this time inside a job by calling extendLockTime from context.
283
- * Individual jobs can override this value by setting their own lockTime.
284
- */
285
- defaultLockTime?: number;
286
- }
287
-
288
- declare class JobsHistoryRepo {
289
- history: Collection<HistoryRecord>;
290
- saveExecution(record: MongoDB.WithoutId<HistoryRecord>): Promise<void>;
291
- getExecutions(jobName: string, limit?: number, skip?: number): Promise<HistoryRecord[]>;
292
- }
293
-
294
- declare class JobsRepo {
295
- jobs: Collection<JobRecord>;
296
- getJobAndLock(jobNames: string[], lockTime: number): Promise<JobToRun>;
297
- setJobRecordPriority(jobId: string, priority: number): Promise<void>;
298
- scheduleNextRun(options: {
299
- jobId: string;
300
- nextRunAt: Date;
301
- resetTries: boolean;
302
- priority: number;
303
- }): Promise<void>;
304
- deleteEventJob(jobId: string): Promise<void>;
305
- /**
306
- * Marks an event job as having reached its maximum tries limit.
307
- * The job will remain in the database but won't be picked up for execution.
308
- */
309
- markJobAsMaxTriesReached(jobId: string): Promise<void>;
310
- extendLockTime(jobId: string, extraTime: number): Promise<void>;
311
- /**
312
- * Updates the lock time for a job to the specified duration from now.
313
- * Can be used to both extend or shorten the lock time.
314
- */
315
- updateLockTime(jobId: string, lockDuration: number): Promise<void>;
316
- unlockAllJobs(): Promise<number>;
317
- ensureJobRecord(job: JobDefinitionWithName): Promise<void>;
318
- scheduleJob(options: ScheduleJobRecordOptions): Promise<void>;
319
- scheduleJobs(jobs: ScheduleJobRecordOptions[]): Promise<ScheduleJobsResult>;
320
- }
321
-
322
- declare function Jobs(): (target: any, context: ClassDecoratorContext<any>) => void;
323
- declare function RecurrentJob(): (method: any, context: ClassFieldDecoratorContext | ClassMethodDecoratorContext) => any;
324
- declare function RecurrentJob(options: Omit<RecurrentJobDefinition, 'resolve' | 'type'>): (method: any, context: ClassMethodDecoratorContext) => any;
325
- declare function EventJob(): (method: any, context: ClassFieldDecoratorContext | ClassMethodDecoratorContext) => any;
326
- declare function EventJob(options: Omit<CreateEventJobOptions<any>, 'resolve'>): (method: any, context: ClassMethodDecoratorContext) => any;
327
- declare function getServiceJobs(target: any): {
328
- [key: string]: JobDefinition;
329
- };
330
-
331
- declare function createEventJob<TParamsSchema extends SchemaInAnyOrionForm>(options: CreateEventJobOptions<TParamsSchema>): EventJobDefinition<TParamsSchema>;
332
- declare function createRecurrentJob(options: CreateRecurrentJobOptions): RecurrentJobDefinition;
333
- /**
334
- * @deprecated Use `createEventJob` or `createRecurrentJob` instead.
335
- */
336
- declare const defineJob: (options: CreateJobOptions & {
337
- type: "event" | "recurrent";
338
- }) => JobDefinition;
339
-
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';
340
9
  declare const jobsHistoryRepo: JobsHistoryRepo;
341
10
  declare const jobsRepo: JobsRepo;
342
- declare const startWorkers: (config: StartWorkersConfig) => WorkersInstance;
11
+ declare const startWorkers: (config: StartWorkersConfig) => import("./types").WorkersInstance;
343
12
  /**
344
13
  * @deprecated Use the event job definition.schedule method instead.
345
14
  */
@@ -349,5 +18,4 @@ declare const scheduleJob: <TParamsSchema extends SchemaInAnyOrionForm = any>(op
349
18
  * @deprecated Use the event job definition.scheduleJobs method instead.
350
19
  */
351
20
  declare const scheduleJobs: <TParamsSchema extends SchemaInAnyOrionForm = any>(jobs: ScheduleJobsOptions<TParamsSchema>) => Promise<ScheduleJobsResult>;
352
-
353
- 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 };
@@ -0,0 +1,7 @@
1
+ import { Collection, MongoDB } from '@orion-js/mongodb';
2
+ import { HistoryRecord } from '../types/HistoryRecord';
3
+ export declare class JobsHistoryRepo {
4
+ history: Collection<HistoryRecord>;
5
+ saveExecution(record: MongoDB.WithoutId<HistoryRecord>): Promise<void>;
6
+ getExecutions(jobName: string, limit?: number, skip?: number): Promise<HistoryRecord[]>;
7
+ }
@@ -0,0 +1,32 @@
1
+ import { Collection } from '@orion-js/mongodb';
2
+ import { ScheduleJobRecordOptions, ScheduleJobsResult } from '../types/Events';
3
+ import { JobRecord } from '../types/JobRecord';
4
+ import { JobDefinitionWithName } from '../types/JobsDefinition';
5
+ import { JobToRun } from '../types/Worker';
6
+ export declare class JobsRepo {
7
+ jobs: Collection<JobRecord>;
8
+ getJobAndLock(jobNames: string[], lockTime: number): Promise<JobToRun>;
9
+ setJobRecordPriority(jobId: string, priority: number): Promise<void>;
10
+ scheduleNextRun(options: {
11
+ jobId: string;
12
+ nextRunAt: Date;
13
+ resetTries: boolean;
14
+ priority: number;
15
+ }): Promise<void>;
16
+ deleteEventJob(jobId: string): Promise<void>;
17
+ /**
18
+ * Marks an event job as having reached its maximum tries limit.
19
+ * The job will remain in the database but won't be picked up for execution.
20
+ */
21
+ markJobAsMaxTriesReached(jobId: string): Promise<void>;
22
+ extendLockTime(jobId: string, extraTime: number): Promise<void>;
23
+ /**
24
+ * Updates the lock time for a job to the specified duration from now.
25
+ * Can be used to both extend or shorten the lock time.
26
+ */
27
+ updateLockTime(jobId: string, lockDuration: number): Promise<void>;
28
+ unlockAllJobs(): Promise<number>;
29
+ ensureJobRecord(job: JobDefinitionWithName): Promise<void>;
30
+ scheduleJob(options: ScheduleJobRecordOptions): Promise<void>;
31
+ scheduleJobs(jobs: ScheduleJobRecordOptions[]): Promise<ScheduleJobsResult>;
32
+ }
@@ -0,0 +1,9 @@
1
+ import type { CreateEventJobOptions, JobDefinition, RecurrentJobDefinition } from '../types';
2
+ export declare function Jobs(): (target: any, context: ClassDecoratorContext<any>) => void;
3
+ export declare function RecurrentJob(): (method: any, context: ClassFieldDecoratorContext | ClassMethodDecoratorContext) => any;
4
+ export declare function RecurrentJob(options: Omit<RecurrentJobDefinition, 'resolve' | 'type'>): (method: any, context: ClassMethodDecoratorContext) => any;
5
+ export declare function EventJob(): (method: any, context: ClassFieldDecoratorContext | ClassMethodDecoratorContext) => any;
6
+ export declare function EventJob(options: Omit<CreateEventJobOptions<any>, 'resolve'>): (method: any, context: ClassMethodDecoratorContext) => any;
7
+ export declare function getServiceJobs(target: any): {
8
+ [key: string]: JobDefinition;
9
+ };
@@ -0,0 +1,6 @@
1
+ import { ScheduleJobOptions, ScheduleJobsOptions, ScheduleJobsResult } from '../types/Events';
2
+ export declare class EventsService {
3
+ private jobsRepo;
4
+ scheduleJob(options: ScheduleJobOptions): Promise<void>;
5
+ scheduleJobs(jobs: ScheduleJobsOptions): Promise<ScheduleJobsResult>;
6
+ }
@@ -0,0 +1,43 @@
1
+ import { Blackbox } from '@orion-js/schema';
2
+ import { EventJobDefinition, JobDefinition, JobsDefinition } from '../types/JobsDefinition';
3
+ import { ExecutionContext, JobToRun } from '../types/Worker';
4
+ /**
5
+ * Configuration for job execution including max tries settings.
6
+ */
7
+ export interface ExecuteJobConfig {
8
+ jobs: JobsDefinition;
9
+ maxTries?: number;
10
+ onMaxTriesReached?: (job: JobToRun) => Promise<void>;
11
+ }
12
+ export declare class Executor {
13
+ private readonly jobsRepo;
14
+ private readonly jobsHistoryRepo;
15
+ /**
16
+ * Determines the effective lock time for a job execution.
17
+ * Job-specific lockTime takes precedence over the default lockTime from config.
18
+ */
19
+ getEffectiveLockTime(job: JobDefinition, jobToRun: JobToRun): number;
20
+ getContext(job: JobDefinition, jobToRun: JobToRun, onStale: Function): ExecutionContext;
21
+ getJobDefinition(jobToRun: JobToRun, jobs: JobsDefinition): JobDefinition<any>;
22
+ /**
23
+ * Determines the effective max tries for an event job.
24
+ * Job-specific maxTries takes precedence over the global maxTries from config.
25
+ */
26
+ getEffectiveMaxTries(job: EventJobDefinition, globalMaxTries?: number): number | undefined;
27
+ /**
28
+ * Handles when a job has reached its maximum retry attempts.
29
+ * Marks the job in the database and invokes the onMaxTriesReached callback when provided.
30
+ */
31
+ handleMaxTriesReached(jobToRun: JobToRun, onMaxTriesReached?: (job: JobToRun) => Promise<void>): Promise<void>;
32
+ onError(error: unknown, job: JobDefinition, jobToRun: JobToRun, context: ExecutionContext): Promise<void>;
33
+ saveExecution(options: {
34
+ startedAt: Date;
35
+ status: 'stale' | 'error' | 'success';
36
+ errorMessage?: string;
37
+ result?: Blackbox;
38
+ job: JobDefinition;
39
+ jobToRun: JobToRun;
40
+ }): Promise<void>;
41
+ afterExecutionSuccess(job: JobDefinition, jobToRun: JobToRun, context: ExecutionContext): Promise<void>;
42
+ executeJob(config: ExecuteJobConfig, jobToRun: JobToRun, respawnWorker: () => void): Promise<void>;
43
+ }
@@ -0,0 +1,26 @@
1
+ import { JobDefinitionWithName, JobsDefinition } from '../types/JobsDefinition';
2
+ import { StartWorkersConfig } from '../types/StartConfig';
3
+ import { JobToRun, WorkerInstance, WorkersInstance } from '../types/Worker';
4
+ import { ExecuteJobConfig } from './Executor';
5
+ export declare class WorkerService {
6
+ private jobsRepo;
7
+ private executor;
8
+ getJobNames(jobs: JobsDefinition): string[];
9
+ getJobs(jobs: JobsDefinition): JobDefinitionWithName[];
10
+ getAvailableJobNames(config: StartWorkersConfig, workersInstance: WorkersInstance, jobNames: string[]): string[];
11
+ reserveJobExecution(workersInstance: WorkersInstance, jobName: string): void;
12
+ releaseJobExecution(workersInstance: WorkersInstance, jobName: string): void;
13
+ withJobAcquisitionLock<T>(workersInstance: WorkersInstance, callback: () => Promise<T>): Promise<T>;
14
+ getJobAndReserveExecution(config: StartWorkersConfig, workersInstance: WorkersInstance, jobNames: string[]): Promise<JobToRun | undefined>;
15
+ runWorkerLoop(config: StartWorkersConfig, workersInstance: WorkersInstance, workerInstance: WorkerInstance, jobNames: string[], executeConfig: ExecuteJobConfig): Promise<boolean>;
16
+ startWorker(config: StartWorkersConfig, workersInstance: WorkersInstance, workerInstance: WorkerInstance): Promise<void>;
17
+ createWorkersInstanceDefinition(config: StartWorkersConfig): WorkersInstance;
18
+ ensureRecords(config: StartWorkersConfig): Promise<void>;
19
+ startANewWorker(config: StartWorkersConfig, workersInstance: WorkersInstance, workerIndex?: number): Promise<void>;
20
+ runWorkers(config: StartWorkersConfig, workersInstance: WorkersInstance): Promise<void>;
21
+ /**
22
+ * Starts the job workers with the provided configuration.
23
+ * @param userConfig - Configuration for the workers. Required field: jobs
24
+ */
25
+ startWorkers(userConfig: StartWorkersConfig): WorkersInstance;
26
+ }
@@ -0,0 +1,12 @@
1
+ export type Options = {
2
+ getNextRun?: () => Date;
3
+ runIn?: number;
4
+ runEvery?: number;
5
+ runAt?: Date;
6
+ cron?: string;
7
+ timezone?: string;
8
+ currentDate?: Date | string | number;
9
+ } & {
10
+ [key: string]: any;
11
+ };
12
+ export declare const getNextRunDate: (options: Options) => Date;
@@ -0,0 +1,63 @@
1
+ import { Blackbox, InferSchemaType, SchemaInAnyOrionForm } from '@orion-js/schema';
2
+ /**
3
+ * Base type for schedule params that varies based on schema presence
4
+ */
5
+ type ScheduleJobParamsType<TParamsSchema extends SchemaInAnyOrionForm> = TParamsSchema extends undefined ? {
6
+ params?: Blackbox;
7
+ } : {
8
+ params: InferSchemaType<TParamsSchema>;
9
+ };
10
+ /**
11
+ * Common options shared by all schedule job variants (without name)
12
+ */
13
+ type ScheduleJobCommonOptions = {
14
+ priority?: number;
15
+ uniqueIdentifier?: string;
16
+ };
17
+ /**
18
+ * Schedule options without name - used by job definition's schedule method.
19
+ * This is a distributive type that properly handles runIn/runAt variants.
20
+ */
21
+ export type ScheduleJobOptionsWithoutName<TParamsSchema extends SchemaInAnyOrionForm = any> = (ScheduleJobCommonOptions & ScheduleJobParamsType<TParamsSchema> & {
22
+ runIn: number;
23
+ }) | (ScheduleJobCommonOptions & ScheduleJobParamsType<TParamsSchema> & {
24
+ runAt: Date;
25
+ }) | (ScheduleJobCommonOptions & ScheduleJobParamsType<TParamsSchema>);
26
+ /**
27
+ * Full schedule options including job name - used by direct scheduleJob calls
28
+ */
29
+ export type ScheduleJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = ScheduleJobOptionsWithoutName<TParamsSchema> & {
30
+ name: string;
31
+ };
32
+ /**
33
+ * Legacy type aliases for backwards compatibility
34
+ */
35
+ export type ScheduleJobOptionsBase<TParamsSchema extends SchemaInAnyOrionForm> = {
36
+ name: string;
37
+ priority?: number;
38
+ uniqueIdentifier?: string;
39
+ } & ScheduleJobParamsType<TParamsSchema>;
40
+ export type ScheduleJobOptionsRunIn<TParamsSchema extends SchemaInAnyOrionForm> = ScheduleJobOptionsBase<TParamsSchema> & {
41
+ runIn: number;
42
+ };
43
+ export type ScheduleJobOptionsRunAt<TParamsSchema extends SchemaInAnyOrionForm> = ScheduleJobOptionsBase<TParamsSchema> & {
44
+ runAt: Date;
45
+ };
46
+ export interface ScheduleJobRecordOptions {
47
+ name: string;
48
+ params: Blackbox;
49
+ nextRunAt: Date;
50
+ priority: number;
51
+ uniqueIdentifier?: string;
52
+ }
53
+ export type ScheduleJobsOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = ScheduleJobOptions<TParamsSchema>[];
54
+ export interface ScheduleJobsResult {
55
+ scheduledCount: number;
56
+ skippedCount: number;
57
+ errors: Array<{
58
+ index: number;
59
+ error: Error;
60
+ job: ScheduleJobOptions;
61
+ }>;
62
+ }
63
+ export {};
@@ -0,0 +1,58 @@
1
+ import { InferSchemaType } from '@orion-js/schema';
2
+ export declare const HistoryRecordSchema: {
3
+ _id: {
4
+ type: "string";
5
+ };
6
+ jobId: {
7
+ type: "string";
8
+ };
9
+ executionId: {
10
+ type: "string";
11
+ };
12
+ jobName: {
13
+ type: "string";
14
+ };
15
+ type: {
16
+ type: "string";
17
+ };
18
+ priority: {
19
+ type: "number";
20
+ };
21
+ tries: {
22
+ type: "number";
23
+ };
24
+ uniqueIdentifier: {
25
+ type: "string";
26
+ optional: true;
27
+ };
28
+ startedAt: {
29
+ type: "date";
30
+ };
31
+ endedAt: {
32
+ type: "date";
33
+ };
34
+ duration: {
35
+ type: "number";
36
+ };
37
+ expiresAt: {
38
+ type: "date";
39
+ optional: true;
40
+ };
41
+ status: {
42
+ type: "string";
43
+ enum: string[];
44
+ };
45
+ errorMessage: {
46
+ type: "string";
47
+ optional: true;
48
+ };
49
+ params: {
50
+ type: "blackbox";
51
+ optional: true;
52
+ };
53
+ result: {
54
+ type: "any";
55
+ optional: true;
56
+ };
57
+ };
58
+ export type HistoryRecord = InferSchemaType<typeof HistoryRecordSchema>;
@@ -0,0 +1,53 @@
1
+ import { InferSchemaType } from '@orion-js/schema';
2
+ /**
3
+ * Enum representing the status of a job record.
4
+ * - 'pending': Job is active and can be executed (default for existing records)
5
+ * - 'maxTriesReached': Event job has exhausted all retry attempts and won't be executed
6
+ */
7
+ export declare const JobStatusEnum: import("@orion-js/schema").FieldType<"maxTriesReached" | "pending">;
8
+ export declare const JobRecordSchema: {
9
+ _id: {
10
+ type: "string";
11
+ };
12
+ jobName: {
13
+ type: "string";
14
+ };
15
+ type: {
16
+ type: import("@orion-js/schema").FieldType<"event" | "recurrent">;
17
+ };
18
+ priority: {
19
+ type: "number";
20
+ };
21
+ uniqueIdentifier: {
22
+ type: "string";
23
+ optional: true;
24
+ };
25
+ nextRunAt: {
26
+ type: "date";
27
+ };
28
+ lastRunAt: {
29
+ type: "date";
30
+ optional: true;
31
+ };
32
+ lockedUntil: {
33
+ type: "date";
34
+ optional: true;
35
+ };
36
+ tries: {
37
+ type: "number";
38
+ optional: true;
39
+ };
40
+ params: {
41
+ type: "blackbox";
42
+ optional: true;
43
+ };
44
+ /**
45
+ * Status of the job. Optional for backwards compatibility with existing records.
46
+ * Records without this field are treated as 'pending'.
47
+ */
48
+ status: {
49
+ type: import("@orion-js/schema").FieldType<"maxTriesReached" | "pending">;
50
+ optional: true;
51
+ };
52
+ };
53
+ export type JobRecord = InferSchemaType<typeof JobRecordSchema>;
@@ -0,0 +1,133 @@
1
+ import { Blackbox, InferSchemaType, SchemaInAnyOrionForm } from '@orion-js/schema';
2
+ import { ScheduleJobOptionsWithoutName, ScheduleJobsResult } from './Events';
3
+ import { ExecutionContext } from './Worker';
4
+ export interface JobRetryResultBase {
5
+ action: 'retry' | 'dismiss';
6
+ }
7
+ export type JobRetryResultRunIn = JobRetryResultBase & {
8
+ runIn: number;
9
+ };
10
+ export type JobRetryResultRunAt = JobRetryResultBase & {
11
+ runAt: Date;
12
+ };
13
+ export type JobRetryResult = JobRetryResultRunIn | JobRetryResultRunAt | JobRetryResultBase;
14
+ export interface BaseJobDefinition {
15
+ /**
16
+ * Called if the job fails.
17
+ */
18
+ onError?: (error: Error, params: Blackbox, context: ExecutionContext) => Promise<JobRetryResult>;
19
+ /**
20
+ * Called if the job locktime is expired. The job will be executed again.
21
+ */
22
+ onStale?: (params: Blackbox, context: ExecutionContext) => Promise<void>;
23
+ /**
24
+ * Save the executions of the job time in milliseconds. Default is 1 week. Set to 0 to disable.
25
+ */
26
+ saveExecutionsFor?: number;
27
+ /**
28
+ * The name of the job.
29
+ * This is set automatically when the job is passed to startWorkers.
30
+ */
31
+ jobName?: string;
32
+ /**
33
+ * Time in milliseconds to lock this specific job for execution.
34
+ * Overrides the defaultLockTime set in startWorkers config.
35
+ * If not set, the defaultLockTime from config will be used.
36
+ */
37
+ lockTime?: number;
38
+ }
39
+ export interface RecurrentJobDefinition extends BaseJobDefinition {
40
+ /**
41
+ * Type of the job.
42
+ */
43
+ type: 'recurrent';
44
+ /**
45
+ * A function executed after each execution that returns the date of the next run.
46
+ */
47
+ getNextRun?: () => Date;
48
+ /**
49
+ * Run every x milliseconds. This will be ignored if getNextRun is defined.
50
+ */
51
+ runEvery?: number;
52
+ /**
53
+ * Cron expression used to calculate the next run. Requires timezone.
54
+ */
55
+ cron?: string;
56
+ /**
57
+ * IANA timezone used to calculate cron-based schedules.
58
+ */
59
+ timezone?: string;
60
+ /**
61
+ * The priority of the job. Higher is more priority. Default is 100.
62
+ */
63
+ priority?: number;
64
+ /**
65
+ * The function to execute when the job is executed.
66
+ */
67
+ resolve: (_: any, context: ExecutionContext) => Promise<Blackbox | void>;
68
+ }
69
+ export interface EventJobDefinition<TParamsSchema extends SchemaInAnyOrionForm = any> extends BaseJobDefinition {
70
+ /**
71
+ * Type of the job.
72
+ */
73
+ type: 'event';
74
+ /**
75
+ * Maximum number of tries for this specific event job before it is marked as 'maxTriesReached'.
76
+ * Overrides the global maxTries set in startWorkers config.
77
+ * If not set, the global maxTries from config will be used.
78
+ */
79
+ maxTries?: number;
80
+ /**
81
+ * Schedule of the job. Supports optional runIn (milliseconds) or runAt (Date) for delayed execution.
82
+ */
83
+ schedule: (options: ScheduleJobOptionsWithoutName<TParamsSchema>) => Promise<void>;
84
+ /**
85
+ * Schedule multiple jobs at once. Each job supports optional runIn or runAt for delayed execution.
86
+ */
87
+ scheduleJobs: (jobs: Array<ScheduleJobOptionsWithoutName<TParamsSchema>>) => Promise<ScheduleJobsResult>;
88
+ /**
89
+ * The schema of the params of the job.
90
+ */
91
+ params?: TParamsSchema;
92
+ /**
93
+ * Maximum number of executions of this job that can run in parallel on the same server.
94
+ * If not set, the job can use all available workers on the current server.
95
+ */
96
+ maxParallelExecutionsPerServer?: number;
97
+ /**
98
+ * The function to execute when the job is executed.
99
+ */
100
+ resolve: (params: InferSchemaType<TParamsSchema>, context: ExecutionContext) => Promise<any>;
101
+ }
102
+ export type CreateEventJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = Omit<EventJobDefinition<TParamsSchema>, 'type' | 'schedule' | 'scheduleJobs'>;
103
+ type CreateRecurrentJobBaseOptions = Omit<RecurrentJobDefinition, 'type' | 'runEvery' | 'cron' | 'timezone'>;
104
+ export type CreateRecurrentJobRunEveryOptions = CreateRecurrentJobBaseOptions & {
105
+ /**
106
+ * Run every x milliseconds.
107
+ * Accepts https://github.com/jkroso/parse-duration strings.
108
+ */
109
+ runEvery: number | string;
110
+ cron?: never;
111
+ timezone?: string;
112
+ };
113
+ export type CreateRecurrentJobCronOptions = CreateRecurrentJobBaseOptions & {
114
+ /**
115
+ * Cron expression used to calculate the next run.
116
+ */
117
+ cron: string;
118
+ /**
119
+ * IANA timezone used to calculate cron-based schedules.
120
+ */
121
+ timezone: string;
122
+ runEvery?: never;
123
+ };
124
+ export type CreateRecurrentJobOptions = CreateRecurrentJobRunEveryOptions | CreateRecurrentJobCronOptions;
125
+ export type CreateJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = CreateEventJobOptions<TParamsSchema> | CreateRecurrentJobOptions;
126
+ export type JobDefinition<TParamsSchema extends SchemaInAnyOrionForm = any> = RecurrentJobDefinition | EventJobDefinition<TParamsSchema>;
127
+ export type JobDefinitionWithName<TParamsSchema extends SchemaInAnyOrionForm = any> = JobDefinition<TParamsSchema> & {
128
+ name: string;
129
+ };
130
+ export interface JobsDefinition {
131
+ [jobName: string]: JobDefinition;
132
+ }
133
+ export {};
@@ -0,0 +1,41 @@
1
+ import { JobsDefinition } from './JobsDefinition';
2
+ import { JobToRun } from './Worker';
3
+ export type LogLevels = 'debug' | 'info' | 'warn' | 'error' | 'none';
4
+ export interface StartWorkersConfig {
5
+ /**
6
+ * Object map of the jobs that this workers will execute
7
+ */
8
+ jobs: JobsDefinition;
9
+ /**
10
+ * Maximum number of tries for an event job before it is marked as 'maxTriesReached'.
11
+ * This is a global default that can be overridden per event job definition.
12
+ */
13
+ maxTries?: number;
14
+ /**
15
+ * Callback invoked when an event job reaches its maximum tries limit.
16
+ * Use this to notify administrators (e.g., send an email alert).
17
+ * The job will remain in the database with status 'maxTriesReached'.
18
+ */
19
+ onMaxTriesReached?: (job: JobToRun) => Promise<void>;
20
+ /**
21
+ * Time in milliseconds to wait between each look without results for a job
22
+ * to run at the database. Default is 3000.
23
+ */
24
+ pollInterval?: number;
25
+ /**
26
+ * Time in milliseconds to wait too look for a job after a job execution. Default is 100.
27
+ */
28
+ cooldownPeriod?: number;
29
+ /**
30
+ * Number of workers to start. Default is 1.
31
+ */
32
+ workersCount?: number;
33
+ /**
34
+ * Default time in milliseconds to lock a job for execution. Default is 30000 (30 seconds).
35
+ * If a job is locked for longer than this time, it will be considered as failed.
36
+ * This is to prevent a job from being executed multiple times at the same time.
37
+ * You can extend this time inside a job by calling extendLockTime from context.
38
+ * Individual jobs can override this value by setting their own lockTime.
39
+ */
40
+ defaultLockTime?: number;
41
+ }
@@ -0,0 +1,41 @@
1
+ import { OrionLogger } from '@orion-js/logger';
2
+ import { Blackbox } from '@orion-js/schema';
3
+ import { JobDefinition } from './JobsDefinition';
4
+ export interface JobToRun {
5
+ jobId: string;
6
+ executionId: string;
7
+ name: string;
8
+ type: 'event' | 'recurrent';
9
+ params: Blackbox;
10
+ tries: number;
11
+ lockTime: number;
12
+ priority: number;
13
+ uniqueIdentifier?: string;
14
+ wasStale?: boolean;
15
+ }
16
+ export interface ExecutionContext {
17
+ record: JobToRun;
18
+ definition: JobDefinition;
19
+ tries: number;
20
+ logger: OrionLogger;
21
+ extendLockTime: (extraTime: number) => Promise<void>;
22
+ clearStaleTimeout: () => void;
23
+ }
24
+ export interface WorkerInstance {
25
+ running: boolean;
26
+ workerIndex: number;
27
+ stop: () => Promise<void>;
28
+ respawn: () => Promise<void>;
29
+ promise?: Promise<any>;
30
+ }
31
+ export interface WorkersInstance {
32
+ running: boolean;
33
+ workersCount: number;
34
+ workers: WorkerInstance[];
35
+ runningJobsByName: Map<string, number>;
36
+ jobAcquisitionLock: Promise<void>;
37
+ /**
38
+ * Stop all workers and wait for them to finish
39
+ */
40
+ stop: () => Promise<void>;
41
+ }
@@ -0,0 +1,6 @@
1
+ export * from './Events';
2
+ export * from './HistoryRecord';
3
+ export * from './JobRecord';
4
+ export * from './JobsDefinition';
5
+ export * from './StartConfig';
6
+ export * from './Worker';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orion-js/dogs",
3
- "version": "4.3.6",
3
+ "version": "4.5.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -17,25 +17,25 @@
17
17
  "license": "MIT",
18
18
  "dependencies": {
19
19
  "@opentelemetry/api": "^1.9.0",
20
- "@orion-js/helpers": "4.3.1",
21
- "@orion-js/schema": "4.3.1",
22
- "@orion-js/services": "4.3.1",
23
- "@orion-js/typed-model": "4.3.1",
20
+ "@orion-js/helpers": "4.5.0",
21
+ "@orion-js/schema": "4.5.0",
22
+ "@orion-js/services": "4.5.0",
23
+ "@orion-js/typed-model": "4.5.0",
24
24
  "cron-parser": "^5.5.0",
25
25
  "dataloader": "2.2.2",
26
26
  "dot-object": "^2.1.5",
27
27
  "parse-duration": "^2.1.3"
28
28
  },
29
29
  "peerDependencies": {
30
- "@orion-js/logger": "4.3.1",
31
- "@orion-js/mongodb": "4.3.1"
30
+ "@orion-js/logger": "4.5.0",
31
+ "@orion-js/mongodb": "4.5.0"
32
32
  },
33
33
  "devDependencies": {
34
- "@orion-js/logger": "4.3.1",
35
- "@orion-js/mongodb": "4.3.1",
34
+ "@orion-js/logger": "4.5.0",
35
+ "@orion-js/mongodb": "4.5.0",
36
36
  "mongodb-memory-server": "^10.1.4",
37
37
  "tsup": "^8.0.1",
38
- "typescript": "^5.4.5"
38
+ "typescript": "^7.0.2"
39
39
  },
40
40
  "publishConfig": {
41
41
  "access": "public"
@@ -44,7 +44,7 @@
44
44
  "scripts": {
45
45
  "test": "bun test",
46
46
  "clean": "rm -rf ./dist",
47
- "build": "tsup",
47
+ "build": "tsup && bun run ../../scripts/emit-declarations.ts",
48
48
  "dev": "tsup --watch"
49
49
  }
50
50
  }
package/dist/index.d.cts DELETED
@@ -1,353 +0,0 @@
1
- import { SchemaInAnyOrionForm, Blackbox, InferSchemaType } from '@orion-js/schema';
2
- import { OrionLogger } from '@orion-js/logger';
3
- import { Collection, MongoDB } from '@orion-js/mongodb';
4
-
5
- /**
6
- * Base type for schedule params that varies based on schema presence
7
- */
8
- type ScheduleJobParamsType<TParamsSchema extends SchemaInAnyOrionForm> = TParamsSchema extends undefined ? {
9
- params?: Blackbox;
10
- } : {
11
- params: InferSchemaType<TParamsSchema>;
12
- };
13
- /**
14
- * Common options shared by all schedule job variants (without name)
15
- */
16
- type ScheduleJobCommonOptions = {
17
- priority?: number;
18
- uniqueIdentifier?: string;
19
- };
20
- /**
21
- * Schedule options without name - used by job definition's schedule method.
22
- * This is a distributive type that properly handles runIn/runAt variants.
23
- */
24
- type ScheduleJobOptionsWithoutName<TParamsSchema extends SchemaInAnyOrionForm = any> = (ScheduleJobCommonOptions & ScheduleJobParamsType<TParamsSchema> & {
25
- runIn: number;
26
- }) | (ScheduleJobCommonOptions & ScheduleJobParamsType<TParamsSchema> & {
27
- runAt: Date;
28
- }) | (ScheduleJobCommonOptions & ScheduleJobParamsType<TParamsSchema>);
29
- /**
30
- * Full schedule options including job name - used by direct scheduleJob calls
31
- */
32
- type ScheduleJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = ScheduleJobOptionsWithoutName<TParamsSchema> & {
33
- name: string;
34
- };
35
- /**
36
- * Legacy type aliases for backwards compatibility
37
- */
38
- type ScheduleJobOptionsBase<TParamsSchema extends SchemaInAnyOrionForm> = {
39
- name: string;
40
- priority?: number;
41
- uniqueIdentifier?: string;
42
- } & ScheduleJobParamsType<TParamsSchema>;
43
- type ScheduleJobOptionsRunIn<TParamsSchema extends SchemaInAnyOrionForm> = ScheduleJobOptionsBase<TParamsSchema> & {
44
- runIn: number;
45
- };
46
- type ScheduleJobOptionsRunAt<TParamsSchema extends SchemaInAnyOrionForm> = ScheduleJobOptionsBase<TParamsSchema> & {
47
- runAt: Date;
48
- };
49
- interface ScheduleJobRecordOptions {
50
- name: string;
51
- params: Blackbox;
52
- nextRunAt: Date;
53
- priority: number;
54
- uniqueIdentifier?: string;
55
- }
56
- type ScheduleJobsOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = ScheduleJobOptions<TParamsSchema>[];
57
- interface ScheduleJobsResult {
58
- scheduledCount: number;
59
- skippedCount: number;
60
- errors: Array<{
61
- index: number;
62
- error: Error;
63
- job: ScheduleJobOptions;
64
- }>;
65
- }
66
-
67
- declare const HistoryRecordSchema: any;
68
- type HistoryRecord = InferSchemaType<typeof HistoryRecordSchema>;
69
-
70
- /**
71
- * Enum representing the status of a job record.
72
- * - 'pending': Job is active and can be executed (default for existing records)
73
- * - 'maxTriesReached': Event job has exhausted all retry attempts and won't be executed
74
- */
75
- declare const JobStatusEnum: any;
76
- declare const JobRecordSchema: any;
77
- type JobRecord = InferSchemaType<typeof JobRecordSchema>;
78
-
79
- interface JobToRun {
80
- jobId: string;
81
- executionId: string;
82
- name: string;
83
- type: 'event' | 'recurrent';
84
- params: Blackbox;
85
- tries: number;
86
- lockTime: number;
87
- priority: number;
88
- uniqueIdentifier?: string;
89
- wasStale?: boolean;
90
- }
91
- interface ExecutionContext {
92
- record: JobToRun;
93
- definition: JobDefinition;
94
- tries: number;
95
- logger: OrionLogger;
96
- extendLockTime: (extraTime: number) => Promise<void>;
97
- clearStaleTimeout: () => void;
98
- }
99
- interface WorkerInstance {
100
- running: boolean;
101
- workerIndex: number;
102
- stop: () => Promise<void>;
103
- respawn: () => Promise<void>;
104
- promise?: Promise<any>;
105
- }
106
- interface WorkersInstance {
107
- running: boolean;
108
- workersCount: number;
109
- workers: WorkerInstance[];
110
- runningJobsByName: Map<string, number>;
111
- jobAcquisitionLock: Promise<void>;
112
- /**
113
- * Stop all workers and wait for them to finish
114
- */
115
- stop: () => Promise<void>;
116
- }
117
-
118
- interface JobRetryResultBase {
119
- action: 'retry' | 'dismiss';
120
- }
121
- type JobRetryResultRunIn = JobRetryResultBase & {
122
- runIn: number;
123
- };
124
- type JobRetryResultRunAt = JobRetryResultBase & {
125
- runAt: Date;
126
- };
127
- type JobRetryResult = JobRetryResultRunIn | JobRetryResultRunAt | JobRetryResultBase;
128
- interface BaseJobDefinition {
129
- /**
130
- * Called if the job fails.
131
- */
132
- onError?: (error: Error, params: Blackbox, context: ExecutionContext) => Promise<JobRetryResult>;
133
- /**
134
- * Called if the job locktime is expired. The job will be executed again.
135
- */
136
- onStale?: (params: Blackbox, context: ExecutionContext) => Promise<void>;
137
- /**
138
- * Save the executions of the job time in milliseconds. Default is 1 week. Set to 0 to disable.
139
- */
140
- saveExecutionsFor?: number;
141
- /**
142
- * The name of the job.
143
- * This is set automatically when the job is passed to startWorkers.
144
- */
145
- jobName?: string;
146
- /**
147
- * Time in milliseconds to lock this specific job for execution.
148
- * Overrides the defaultLockTime set in startWorkers config.
149
- * If not set, the defaultLockTime from config will be used.
150
- */
151
- lockTime?: number;
152
- }
153
- interface RecurrentJobDefinition extends BaseJobDefinition {
154
- /**
155
- * Type of the job.
156
- */
157
- type: 'recurrent';
158
- /**
159
- * A function executed after each execution that returns the date of the next run.
160
- */
161
- getNextRun?: () => Date;
162
- /**
163
- * Run every x milliseconds. This will be ignored if getNextRun is defined.
164
- */
165
- runEvery?: number;
166
- /**
167
- * Cron expression used to calculate the next run. Requires timezone.
168
- */
169
- cron?: string;
170
- /**
171
- * IANA timezone used to calculate cron-based schedules.
172
- */
173
- timezone?: string;
174
- /**
175
- * The priority of the job. Higher is more priority. Default is 100.
176
- */
177
- priority?: number;
178
- /**
179
- * The function to execute when the job is executed.
180
- */
181
- resolve: (_: any, context: ExecutionContext) => Promise<Blackbox | void>;
182
- }
183
- interface EventJobDefinition<TParamsSchema extends SchemaInAnyOrionForm = any> extends BaseJobDefinition {
184
- /**
185
- * Type of the job.
186
- */
187
- type: 'event';
188
- /**
189
- * Maximum number of tries for this specific event job before it is marked as 'maxTriesReached'.
190
- * Overrides the global maxTries set in startWorkers config.
191
- * If not set, the global maxTries from config will be used.
192
- */
193
- maxTries?: number;
194
- /**
195
- * Schedule of the job. Supports optional runIn (milliseconds) or runAt (Date) for delayed execution.
196
- */
197
- schedule: (options: ScheduleJobOptionsWithoutName<TParamsSchema>) => Promise<void>;
198
- /**
199
- * Schedule multiple jobs at once. Each job supports optional runIn or runAt for delayed execution.
200
- */
201
- scheduleJobs: (jobs: Array<ScheduleJobOptionsWithoutName<TParamsSchema>>) => Promise<ScheduleJobsResult>;
202
- /**
203
- * The schema of the params of the job.
204
- */
205
- params?: TParamsSchema;
206
- /**
207
- * Maximum number of executions of this job that can run in parallel on the same server.
208
- * If not set, the job can use all available workers on the current server.
209
- */
210
- maxParallelExecutionsPerServer?: number;
211
- /**
212
- * The function to execute when the job is executed.
213
- */
214
- resolve: (params: InferSchemaType<TParamsSchema>, context: ExecutionContext) => Promise<any>;
215
- }
216
- type CreateEventJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = Omit<EventJobDefinition<TParamsSchema>, 'type' | 'schedule' | 'scheduleJobs'>;
217
- type CreateRecurrentJobBaseOptions = Omit<RecurrentJobDefinition, 'type' | 'runEvery' | 'cron' | 'timezone'>;
218
- type CreateRecurrentJobRunEveryOptions = CreateRecurrentJobBaseOptions & {
219
- /**
220
- * Run every x milliseconds.
221
- * Accepts https://github.com/jkroso/parse-duration strings.
222
- */
223
- runEvery: number | string;
224
- cron?: never;
225
- timezone?: string;
226
- };
227
- type CreateRecurrentJobCronOptions = CreateRecurrentJobBaseOptions & {
228
- /**
229
- * Cron expression used to calculate the next run.
230
- */
231
- cron: string;
232
- /**
233
- * IANA timezone used to calculate cron-based schedules.
234
- */
235
- timezone: string;
236
- runEvery?: never;
237
- };
238
- type CreateRecurrentJobOptions = CreateRecurrentJobRunEveryOptions | CreateRecurrentJobCronOptions;
239
- type CreateJobOptions<TParamsSchema extends SchemaInAnyOrionForm = any> = CreateEventJobOptions<TParamsSchema> | CreateRecurrentJobOptions;
240
- type JobDefinition<TParamsSchema extends SchemaInAnyOrionForm = any> = RecurrentJobDefinition | EventJobDefinition<TParamsSchema>;
241
- type JobDefinitionWithName<TParamsSchema extends SchemaInAnyOrionForm = any> = JobDefinition<TParamsSchema> & {
242
- name: string;
243
- };
244
- interface JobsDefinition {
245
- [jobName: string]: JobDefinition;
246
- }
247
-
248
- type LogLevels = 'debug' | 'info' | 'warn' | 'error' | 'none';
249
- interface StartWorkersConfig {
250
- /**
251
- * Object map of the jobs that this workers will execute
252
- */
253
- jobs: JobsDefinition;
254
- /**
255
- * Maximum number of tries for an event job before it is marked as 'maxTriesReached'.
256
- * This is a global default that can be overridden per event job definition.
257
- */
258
- maxTries?: number;
259
- /**
260
- * Callback invoked when an event job reaches its maximum tries limit.
261
- * Use this to notify administrators (e.g., send an email alert).
262
- * The job will remain in the database with status 'maxTriesReached'.
263
- */
264
- onMaxTriesReached?: (job: JobToRun) => Promise<void>;
265
- /**
266
- * Time in milliseconds to wait between each look without results for a job
267
- * to run at the database. Default is 3000.
268
- */
269
- pollInterval?: number;
270
- /**
271
- * Time in milliseconds to wait too look for a job after a job execution. Default is 100.
272
- */
273
- cooldownPeriod?: number;
274
- /**
275
- * Number of workers to start. Default is 1.
276
- */
277
- workersCount?: number;
278
- /**
279
- * Default time in milliseconds to lock a job for execution. Default is 30000 (30 seconds).
280
- * If a job is locked for longer than this time, it will be considered as failed.
281
- * This is to prevent a job from being executed multiple times at the same time.
282
- * You can extend this time inside a job by calling extendLockTime from context.
283
- * Individual jobs can override this value by setting their own lockTime.
284
- */
285
- defaultLockTime?: number;
286
- }
287
-
288
- declare class JobsHistoryRepo {
289
- history: Collection<HistoryRecord>;
290
- saveExecution(record: MongoDB.WithoutId<HistoryRecord>): Promise<void>;
291
- getExecutions(jobName: string, limit?: number, skip?: number): Promise<HistoryRecord[]>;
292
- }
293
-
294
- declare class JobsRepo {
295
- jobs: Collection<JobRecord>;
296
- getJobAndLock(jobNames: string[], lockTime: number): Promise<JobToRun>;
297
- setJobRecordPriority(jobId: string, priority: number): Promise<void>;
298
- scheduleNextRun(options: {
299
- jobId: string;
300
- nextRunAt: Date;
301
- resetTries: boolean;
302
- priority: number;
303
- }): Promise<void>;
304
- deleteEventJob(jobId: string): Promise<void>;
305
- /**
306
- * Marks an event job as having reached its maximum tries limit.
307
- * The job will remain in the database but won't be picked up for execution.
308
- */
309
- markJobAsMaxTriesReached(jobId: string): Promise<void>;
310
- extendLockTime(jobId: string, extraTime: number): Promise<void>;
311
- /**
312
- * Updates the lock time for a job to the specified duration from now.
313
- * Can be used to both extend or shorten the lock time.
314
- */
315
- updateLockTime(jobId: string, lockDuration: number): Promise<void>;
316
- unlockAllJobs(): Promise<number>;
317
- ensureJobRecord(job: JobDefinitionWithName): Promise<void>;
318
- scheduleJob(options: ScheduleJobRecordOptions): Promise<void>;
319
- scheduleJobs(jobs: ScheduleJobRecordOptions[]): Promise<ScheduleJobsResult>;
320
- }
321
-
322
- declare function Jobs(): (target: any, context: ClassDecoratorContext<any>) => void;
323
- declare function RecurrentJob(): (method: any, context: ClassFieldDecoratorContext | ClassMethodDecoratorContext) => any;
324
- declare function RecurrentJob(options: Omit<RecurrentJobDefinition, 'resolve' | 'type'>): (method: any, context: ClassMethodDecoratorContext) => any;
325
- declare function EventJob(): (method: any, context: ClassFieldDecoratorContext | ClassMethodDecoratorContext) => any;
326
- declare function EventJob(options: Omit<CreateEventJobOptions<any>, 'resolve'>): (method: any, context: ClassMethodDecoratorContext) => any;
327
- declare function getServiceJobs(target: any): {
328
- [key: string]: JobDefinition;
329
- };
330
-
331
- declare function createEventJob<TParamsSchema extends SchemaInAnyOrionForm>(options: CreateEventJobOptions<TParamsSchema>): EventJobDefinition<TParamsSchema>;
332
- declare function createRecurrentJob(options: CreateRecurrentJobOptions): RecurrentJobDefinition;
333
- /**
334
- * @deprecated Use `createEventJob` or `createRecurrentJob` instead.
335
- */
336
- declare const defineJob: (options: CreateJobOptions & {
337
- type: "event" | "recurrent";
338
- }) => JobDefinition;
339
-
340
- declare const jobsHistoryRepo: JobsHistoryRepo;
341
- declare const jobsRepo: JobsRepo;
342
- declare const startWorkers: (config: StartWorkersConfig) => WorkersInstance;
343
- /**
344
- * @deprecated Use the event job definition.schedule method instead.
345
- */
346
- declare const scheduleJob: <TParamsSchema extends SchemaInAnyOrionForm = any>(options: ScheduleJobOptions<TParamsSchema>) => Promise<void>;
347
- /**
348
- * Schedule multiple jobs at once for better performance.
349
- * @deprecated Use the event job definition.scheduleJobs method instead.
350
- */
351
- declare const scheduleJobs: <TParamsSchema extends SchemaInAnyOrionForm = any>(jobs: ScheduleJobsOptions<TParamsSchema>) => Promise<ScheduleJobsResult>;
352
-
353
- 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 };