silent-cronx 1.0.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/LICENSE +21 -0
- package/README.md +314 -0
- package/dist/index.cjs +1169 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +321 -0
- package/dist/index.d.ts +321 -0
- package/dist/index.js +1138 -0
- package/dist/index.js.map +1 -0
- package/dist/workers/workerRunner.cjs +29 -0
- package/dist/workers/workerRunner.cjs.map +1 -0
- package/dist/workers/workerRunner.d.cts +2 -0
- package/dist/workers/workerRunner.d.ts +2 -0
- package/dist/workers/workerRunner.js +27 -0
- package/dist/workers/workerRunner.js.map +1 -0
- package/package.json +43 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
type RetryBackoff = "fixed" | "linear" | "exponential";
|
|
2
|
+
type RetryConfig = {
|
|
3
|
+
attempts: number;
|
|
4
|
+
delayMs?: number;
|
|
5
|
+
backoff?: RetryBackoff;
|
|
6
|
+
shouldRetry?: (error: unknown) => boolean;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type JobStatus = "pending" | "scheduled" | "running" | "success" | "failed" | "cancelled" | "paused" | "timeout";
|
|
10
|
+
type SerializedError = {
|
|
11
|
+
name: string;
|
|
12
|
+
message: string;
|
|
13
|
+
stack?: string;
|
|
14
|
+
};
|
|
15
|
+
type JobTask<TPayload = unknown, TResult = unknown> = (context: {
|
|
16
|
+
jobId: string;
|
|
17
|
+
name: string;
|
|
18
|
+
payload: TPayload;
|
|
19
|
+
attempt: number;
|
|
20
|
+
signal: AbortSignal;
|
|
21
|
+
createdAt: Date;
|
|
22
|
+
startedAt: Date;
|
|
23
|
+
}) => Promise<TResult> | TResult;
|
|
24
|
+
type ScheduleJobOptions<TPayload = unknown> = {
|
|
25
|
+
cron: string;
|
|
26
|
+
payload?: TPayload;
|
|
27
|
+
timezone?: string;
|
|
28
|
+
enabled?: boolean;
|
|
29
|
+
preventOverlap?: boolean;
|
|
30
|
+
timeout?: number;
|
|
31
|
+
retry?: RetryConfig;
|
|
32
|
+
priority?: number;
|
|
33
|
+
task: JobTask<TPayload>;
|
|
34
|
+
};
|
|
35
|
+
type DelayJobOptions<TPayload = unknown, TResult = unknown> = {
|
|
36
|
+
delayMs: number;
|
|
37
|
+
payload?: TPayload;
|
|
38
|
+
timeout?: number;
|
|
39
|
+
retry?: RetryConfig;
|
|
40
|
+
priority?: number;
|
|
41
|
+
task: JobTask<TPayload, TResult>;
|
|
42
|
+
};
|
|
43
|
+
type EveryJobOptions<TPayload = unknown, TResult = unknown> = {
|
|
44
|
+
intervalMs: number;
|
|
45
|
+
payload?: TPayload;
|
|
46
|
+
enabled?: boolean;
|
|
47
|
+
preventOverlap?: boolean;
|
|
48
|
+
timeout?: number;
|
|
49
|
+
retry?: RetryConfig;
|
|
50
|
+
priority?: number;
|
|
51
|
+
task: JobTask<TPayload, TResult>;
|
|
52
|
+
};
|
|
53
|
+
type RunNowOptions<TPayload = unknown, TResult = unknown> = {
|
|
54
|
+
payload?: TPayload;
|
|
55
|
+
timeout?: number;
|
|
56
|
+
retry?: RetryConfig;
|
|
57
|
+
priority?: number;
|
|
58
|
+
task: JobTask<TPayload, TResult>;
|
|
59
|
+
};
|
|
60
|
+
type WorkerModuleReference = {
|
|
61
|
+
path: string | URL;
|
|
62
|
+
exportName?: string;
|
|
63
|
+
};
|
|
64
|
+
type WorkerJobOptions<TPayload = unknown> = {
|
|
65
|
+
payload?: TPayload;
|
|
66
|
+
timeout?: number;
|
|
67
|
+
retry?: RetryConfig;
|
|
68
|
+
priority?: number;
|
|
69
|
+
worker: WorkerModuleReference | JobTask<TPayload>;
|
|
70
|
+
};
|
|
71
|
+
type JobResult<TResult = unknown> = {
|
|
72
|
+
jobId: string;
|
|
73
|
+
name: string;
|
|
74
|
+
status: JobStatus;
|
|
75
|
+
result?: TResult;
|
|
76
|
+
error?: SerializedError;
|
|
77
|
+
attempt: number;
|
|
78
|
+
durationMs: number;
|
|
79
|
+
startedAt?: string;
|
|
80
|
+
finishedAt?: string;
|
|
81
|
+
};
|
|
82
|
+
type JobKind = "cron" | "delay" | "every" | "runNow" | "worker" | "queue";
|
|
83
|
+
type JobRecord<TPayload = unknown, TResult = unknown> = {
|
|
84
|
+
id: string;
|
|
85
|
+
name: string;
|
|
86
|
+
kind: JobKind;
|
|
87
|
+
status: JobStatus;
|
|
88
|
+
payload?: TPayload;
|
|
89
|
+
priority: number;
|
|
90
|
+
attempts: number;
|
|
91
|
+
maxAttempts: number;
|
|
92
|
+
createdAt: string;
|
|
93
|
+
updatedAt: string;
|
|
94
|
+
startedAt?: string;
|
|
95
|
+
finishedAt?: string;
|
|
96
|
+
lastRunAt?: string;
|
|
97
|
+
nextRunAt?: string;
|
|
98
|
+
result?: TResult;
|
|
99
|
+
error?: SerializedError;
|
|
100
|
+
successCount: number;
|
|
101
|
+
failureCount: number;
|
|
102
|
+
queueName?: string;
|
|
103
|
+
metadata?: Record<string, unknown>;
|
|
104
|
+
};
|
|
105
|
+
type JobFilter = {
|
|
106
|
+
status?: JobStatus;
|
|
107
|
+
name?: string;
|
|
108
|
+
kind?: JobKind;
|
|
109
|
+
queueName?: string;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
interface StorageAdapter {
|
|
113
|
+
saveJob(job: JobRecord): Promise<void>;
|
|
114
|
+
updateJob(jobId: string, patch: Partial<JobRecord>): Promise<void>;
|
|
115
|
+
getJob(jobId: string): Promise<JobRecord | null>;
|
|
116
|
+
listJobs(filter?: JobFilter): Promise<JobRecord[]>;
|
|
117
|
+
deleteJob(jobId: string): Promise<void>;
|
|
118
|
+
acquireLock(lockKey: string, ttlMs: number): Promise<boolean>;
|
|
119
|
+
releaseLock(lockKey: string): Promise<void>;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
type SilentCronXLogger = {
|
|
123
|
+
info?: (...args: unknown[]) => void;
|
|
124
|
+
warn?: (...args: unknown[]) => void;
|
|
125
|
+
error?: (...args: unknown[]) => void;
|
|
126
|
+
debug?: (...args: unknown[]) => void;
|
|
127
|
+
};
|
|
128
|
+
type SilentCronXConfig = {
|
|
129
|
+
timezone?: string;
|
|
130
|
+
maxWorkers?: number;
|
|
131
|
+
maxConcurrency?: number;
|
|
132
|
+
defaultTimeout?: number;
|
|
133
|
+
preventOverlapping?: boolean;
|
|
134
|
+
lockTimeout?: number;
|
|
135
|
+
maxPayloadBytes?: number;
|
|
136
|
+
logger?: SilentCronXLogger;
|
|
137
|
+
storage?: "memory" | StorageAdapter;
|
|
138
|
+
debug?: boolean;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
type SilentCronXEventMap = {
|
|
142
|
+
"scheduler:started": {
|
|
143
|
+
running: true;
|
|
144
|
+
at: string;
|
|
145
|
+
};
|
|
146
|
+
"scheduler:stopped": {
|
|
147
|
+
running: false;
|
|
148
|
+
at: string;
|
|
149
|
+
};
|
|
150
|
+
"scheduler:shutdown": {
|
|
151
|
+
at: string;
|
|
152
|
+
};
|
|
153
|
+
"job:scheduled": {
|
|
154
|
+
jobId: string;
|
|
155
|
+
name: string;
|
|
156
|
+
nextRunAt?: string;
|
|
157
|
+
};
|
|
158
|
+
"job:started": {
|
|
159
|
+
jobId: string;
|
|
160
|
+
name: string;
|
|
161
|
+
attempt: number;
|
|
162
|
+
};
|
|
163
|
+
"job:success": JobResult;
|
|
164
|
+
"job:failed": JobResult;
|
|
165
|
+
"job:timeout": JobResult;
|
|
166
|
+
"job:cancelled": {
|
|
167
|
+
jobId: string;
|
|
168
|
+
name: string;
|
|
169
|
+
};
|
|
170
|
+
"job:paused": {
|
|
171
|
+
jobId: string;
|
|
172
|
+
name: string;
|
|
173
|
+
};
|
|
174
|
+
"job:resumed": {
|
|
175
|
+
jobId: string;
|
|
176
|
+
name: string;
|
|
177
|
+
};
|
|
178
|
+
"job:retry": {
|
|
179
|
+
jobId: string;
|
|
180
|
+
name: string;
|
|
181
|
+
attempt: number;
|
|
182
|
+
delayMs: number;
|
|
183
|
+
};
|
|
184
|
+
"queue:created": {
|
|
185
|
+
queueName: string;
|
|
186
|
+
concurrency: number;
|
|
187
|
+
};
|
|
188
|
+
"queue:drain": {
|
|
189
|
+
queueName: string;
|
|
190
|
+
};
|
|
191
|
+
"error": {
|
|
192
|
+
error: unknown;
|
|
193
|
+
jobId?: string;
|
|
194
|
+
name?: string;
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
type SilentCronXEventName = keyof SilentCronXEventMap;
|
|
198
|
+
type SilentCronXEventHandler<TName extends SilentCronXEventName> = (event: SilentCronXEventMap[TName]) => void;
|
|
199
|
+
type StatusSnapshot = {
|
|
200
|
+
jobId: string;
|
|
201
|
+
name: string;
|
|
202
|
+
status: JobStatus;
|
|
203
|
+
attempt: number;
|
|
204
|
+
nextRunAt?: string;
|
|
205
|
+
lastRunAt?: string;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
type QueueOptions<TPayload = unknown, TResult = unknown> = {
|
|
209
|
+
concurrency?: number;
|
|
210
|
+
retry?: RetryConfig;
|
|
211
|
+
timeout?: number;
|
|
212
|
+
maxSize?: number;
|
|
213
|
+
rateLimit?: {
|
|
214
|
+
limit: number;
|
|
215
|
+
intervalMs: number;
|
|
216
|
+
};
|
|
217
|
+
processor?: JobTask<TPayload, TResult>;
|
|
218
|
+
};
|
|
219
|
+
type AddQueueJobOptions<TPayload = unknown, TResult = unknown> = {
|
|
220
|
+
id?: string;
|
|
221
|
+
name: string;
|
|
222
|
+
payload?: TPayload;
|
|
223
|
+
priority?: number;
|
|
224
|
+
timeout?: number;
|
|
225
|
+
retry?: RetryConfig;
|
|
226
|
+
task?: JobTask<TPayload, TResult>;
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
type SilentCronXHealth = {
|
|
230
|
+
running: boolean;
|
|
231
|
+
scheduledJobs: number;
|
|
232
|
+
runningJobs: number;
|
|
233
|
+
queuedJobs: number;
|
|
234
|
+
workers: {
|
|
235
|
+
max: number;
|
|
236
|
+
busy: number;
|
|
237
|
+
idle: number;
|
|
238
|
+
};
|
|
239
|
+
memory: {
|
|
240
|
+
storage: string;
|
|
241
|
+
};
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
declare class SilentCronX {
|
|
245
|
+
private readonly config;
|
|
246
|
+
private readonly storage;
|
|
247
|
+
private readonly eventBus;
|
|
248
|
+
private readonly runner;
|
|
249
|
+
private readonly workerPool;
|
|
250
|
+
private readonly lockManager;
|
|
251
|
+
private readonly queueManager;
|
|
252
|
+
private readonly logger;
|
|
253
|
+
private readonly entries;
|
|
254
|
+
private readonly controllers;
|
|
255
|
+
private running;
|
|
256
|
+
constructor(config?: SilentCronXConfig);
|
|
257
|
+
schedule<TPayload = unknown>(name: string, options: ScheduleJobOptions<TPayload>): Promise<string>;
|
|
258
|
+
delay<TPayload = unknown, TResult = unknown>(name: string, options: DelayJobOptions<TPayload, TResult>): Promise<string>;
|
|
259
|
+
every<TPayload = unknown, TResult = unknown>(name: string, options: EveryJobOptions<TPayload, TResult>): Promise<string>;
|
|
260
|
+
runNow<TPayload = unknown, TResult = unknown>(name: string, options: RunNowOptions<TPayload, TResult>): Promise<JobResult<TResult>>;
|
|
261
|
+
runWorker<TPayload = unknown, TResult = unknown>(name: string, options: WorkerJobOptions<TPayload>): Promise<JobResult<TResult>>;
|
|
262
|
+
queue<TPayload = unknown, TResult = unknown>(name: string, options?: QueueOptions<TPayload, TResult>): void;
|
|
263
|
+
addJob<TPayload = unknown, TResult = unknown>(queueName: string, job: AddQueueJobOptions<TPayload, TResult>): Promise<string>;
|
|
264
|
+
cancel(jobId: string): Promise<void>;
|
|
265
|
+
pause(jobId: string): Promise<void>;
|
|
266
|
+
resume(jobId: string): Promise<void>;
|
|
267
|
+
getStatus(jobId: string): Promise<StatusSnapshot | null>;
|
|
268
|
+
getJobs(): Promise<JobRecord[]>;
|
|
269
|
+
start(): void;
|
|
270
|
+
stop(): void;
|
|
271
|
+
shutdown(): Promise<void>;
|
|
272
|
+
on<TName extends SilentCronXEventName>(eventName: TName, handler: SilentCronXEventHandler<TName>): void;
|
|
273
|
+
off<TName extends SilentCronXEventName>(eventName: TName, handler: SilentCronXEventHandler<TName>): void;
|
|
274
|
+
getHealth(): Promise<SilentCronXHealth>;
|
|
275
|
+
private executeJob;
|
|
276
|
+
private armEntry;
|
|
277
|
+
private armCron;
|
|
278
|
+
private armDelay;
|
|
279
|
+
private armEvery;
|
|
280
|
+
private clearTimer;
|
|
281
|
+
private createRecord;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
declare function createSilentCronX(config?: SilentCronXConfig): SilentCronX;
|
|
285
|
+
|
|
286
|
+
declare class MemoryStorageAdapter implements StorageAdapter {
|
|
287
|
+
private readonly jobs;
|
|
288
|
+
private readonly locks;
|
|
289
|
+
saveJob(job: JobRecord): Promise<void>;
|
|
290
|
+
updateJob(jobId: string, patch: Partial<JobRecord>): Promise<void>;
|
|
291
|
+
getJob(jobId: string): Promise<JobRecord | null>;
|
|
292
|
+
listJobs(filter?: JobFilter): Promise<JobRecord[]>;
|
|
293
|
+
deleteJob(jobId: string): Promise<void>;
|
|
294
|
+
acquireLock(lockKey: string, ttlMs: number): Promise<boolean>;
|
|
295
|
+
releaseLock(lockKey: string): Promise<void>;
|
|
296
|
+
private cleanupExpiredLocks;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
declare class RedisStorageAdapter implements StorageAdapter {
|
|
300
|
+
constructor();
|
|
301
|
+
saveJob(_job: JobRecord): Promise<void>;
|
|
302
|
+
updateJob(_jobId: string, _patch: Partial<JobRecord>): Promise<void>;
|
|
303
|
+
getJob(_jobId: string): Promise<JobRecord | null>;
|
|
304
|
+
listJobs(_filter?: JobFilter): Promise<JobRecord[]>;
|
|
305
|
+
deleteJob(_jobId: string): Promise<void>;
|
|
306
|
+
acquireLock(_lockKey: string, _ttlMs: number): Promise<boolean>;
|
|
307
|
+
releaseLock(_lockKey: string): Promise<void>;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
declare class PostgresStorageAdapter implements StorageAdapter {
|
|
311
|
+
constructor();
|
|
312
|
+
saveJob(_job: JobRecord): Promise<void>;
|
|
313
|
+
updateJob(_jobId: string, _patch: Partial<JobRecord>): Promise<void>;
|
|
314
|
+
getJob(_jobId: string): Promise<JobRecord | null>;
|
|
315
|
+
listJobs(_filter?: JobFilter): Promise<JobRecord[]>;
|
|
316
|
+
deleteJob(_jobId: string): Promise<void>;
|
|
317
|
+
acquireLock(_lockKey: string, _ttlMs: number): Promise<boolean>;
|
|
318
|
+
releaseLock(_lockKey: string): Promise<void>;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export { type AddQueueJobOptions, type DelayJobOptions, type EveryJobOptions, type JobFilter, type JobKind, type JobRecord, type JobResult, type JobStatus, type JobTask, MemoryStorageAdapter, PostgresStorageAdapter, type QueueOptions, RedisStorageAdapter, type RetryBackoff, type RetryConfig, type RunNowOptions, type ScheduleJobOptions, type SerializedError, SilentCronX, type SilentCronXConfig, type SilentCronXEventHandler, type SilentCronXEventMap, type SilentCronXEventName, type SilentCronXHealth, type SilentCronXLogger, type StatusSnapshot, type StorageAdapter, type WorkerJobOptions, type WorkerModuleReference, createSilentCronX };
|