@sqlane/core 0.1.0 → 0.1.2
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/README.md +10 -0
- package/package.json +20 -5
- package/src/create_sqlane.js +1 -0
- package/src/runner.js +137 -22
- package/src/store/mysql_final.js +23 -9
- package/src/store/postgres_final.js +27 -17
- package/src/store/store.js +7 -2
- package/types/adapters/mysql2.d.ts +13 -0
- package/types/adapters/pg.d.ts +16 -0
- package/types/backoff.d.ts +8 -0
- package/types/create_sqlane.d.ts +8 -0
- package/types/defaults.d.ts +18 -0
- package/types/define_job.d.ts +6 -0
- package/types/duration.d.ts +7 -0
- package/types/enqueue.d.ts +50 -0
- package/types/error_json.d.ts +21 -0
- package/types/errors.d.ts +129 -0
- package/types/hint_channel.d.ts +31 -0
- package/types/index.d.ts +72 -0
- package/types/migrations.d.ts +22 -0
- package/types/mutex_keys.d.ts +9 -0
- package/types/new_job.d.ts +40 -0
- package/types/payload.d.ts +10 -0
- package/types/registry.d.ts +72 -0
- package/types/runner.d.ts +92 -0
- package/types/schema/mysql.d.ts +10 -0
- package/types/schema/postgres.d.ts +10 -0
- package/types/store/mysql_enqueue.d.ts +9 -0
- package/types/store/mysql_final.d.ts +135 -0
- package/types/store/mysql_worker.d.ts +51 -0
- package/types/store/postgres_enqueue.d.ts +9 -0
- package/types/store/postgres_final.d.ts +135 -0
- package/types/store/postgres_worker.d.ts +45 -0
- package/types/store/store.d.ts +221 -0
- package/types/transient_error.d.ts +6 -0
- package/types/types.d.ts +651 -0
- package/types/validate.d.ts +76 -0
package/types/types.d.ts
ADDED
|
@@ -0,0 +1,651 @@
|
|
|
1
|
+
export type Duration = string | number;
|
|
2
|
+
export type Jsonable<T> = T extends string | number | boolean | null ? T : T extends undefined | bigint | symbol | Function | Date | RegExp | Map<any, any> | Set<any> ? never : T extends readonly (infer U)[] ? readonly Jsonable<U>[] : T extends object ? {
|
|
3
|
+
[K in keyof T]: Jsonable<T[K]>;
|
|
4
|
+
} : never;
|
|
5
|
+
export type ExponentialBackoff = {
|
|
6
|
+
/**
|
|
7
|
+
* `delay × 2^(attempt − 1)`, at most `maxDelay`.
|
|
8
|
+
*/
|
|
9
|
+
type: 'exponential';
|
|
10
|
+
delay: Duration;
|
|
11
|
+
maxDelay?: Duration;
|
|
12
|
+
/**
|
|
13
|
+
* 0–1: the delay is `delay × (1 − jitter × random())`. Default: 0.2.
|
|
14
|
+
*/
|
|
15
|
+
jitter?: number;
|
|
16
|
+
};
|
|
17
|
+
export type FixedBackoff = {
|
|
18
|
+
type: 'fixed';
|
|
19
|
+
delay: Duration;
|
|
20
|
+
/**
|
|
21
|
+
* 0–1. Default: 0.2.
|
|
22
|
+
*/
|
|
23
|
+
jitter?: number;
|
|
24
|
+
};
|
|
25
|
+
export type Backoff = ExponentialBackoff | FixedBackoff;
|
|
26
|
+
export type Retention = {
|
|
27
|
+
/**
|
|
28
|
+
* Default: `'1h'`.
|
|
29
|
+
*/
|
|
30
|
+
completed?: Duration;
|
|
31
|
+
/**
|
|
32
|
+
* Default: `'30d'`.
|
|
33
|
+
*/
|
|
34
|
+
failed?: Duration;
|
|
35
|
+
};
|
|
36
|
+
export type JobOptions = {
|
|
37
|
+
/**
|
|
38
|
+
* Matches `^[a-z][a-z0-9_.-]{0,127}$`.
|
|
39
|
+
*/
|
|
40
|
+
name: string;
|
|
41
|
+
/**
|
|
42
|
+
* Default: 3.
|
|
43
|
+
*/
|
|
44
|
+
maxAttempts?: number;
|
|
45
|
+
/**
|
|
46
|
+
* Default: 2.
|
|
47
|
+
*/
|
|
48
|
+
maxStalls?: number;
|
|
49
|
+
backoff?: Backoff;
|
|
50
|
+
retention?: Retention;
|
|
51
|
+
/**
|
|
52
|
+
* No default. A job with mutex keys needs one.
|
|
53
|
+
*/
|
|
54
|
+
timeout?: Duration;
|
|
55
|
+
/**
|
|
56
|
+
* Sync, from the payload only.
|
|
57
|
+
*/
|
|
58
|
+
mutexKeys?: (payload: any) => readonly string[];
|
|
59
|
+
/**
|
|
60
|
+
* Added when a job fails for good.
|
|
61
|
+
*/
|
|
62
|
+
failureJob?: string | JobDefinition;
|
|
63
|
+
};
|
|
64
|
+
export type JobDefinition = Readonly<JobOptions>;
|
|
65
|
+
export type EnqueueBaseOptions = {
|
|
66
|
+
/**
|
|
67
|
+
* 1–120 printable ASCII characters. Dedupe: a job with this id is added once while its row
|
|
68
|
+
* exists.
|
|
69
|
+
*/
|
|
70
|
+
jobId?: string;
|
|
71
|
+
maxAttempts?: number;
|
|
72
|
+
maxStalls?: number;
|
|
73
|
+
retention?: Retention;
|
|
74
|
+
failureJob?: string | JobDefinition;
|
|
75
|
+
/**
|
|
76
|
+
* Replace the keys of the definition; `[]` clears them.
|
|
77
|
+
*/
|
|
78
|
+
mutexKeys?: readonly string[];
|
|
79
|
+
};
|
|
80
|
+
export type EnqueueOptions = EnqueueBaseOptions & ({
|
|
81
|
+
delay?: Duration;
|
|
82
|
+
runAt?: never;
|
|
83
|
+
} | {
|
|
84
|
+
runAt: Date;
|
|
85
|
+
delay?: never;
|
|
86
|
+
});
|
|
87
|
+
export type EnqueueResult = {
|
|
88
|
+
/**
|
|
89
|
+
* `<job_name>:<jobId>`, or a new ULID without a `jobId`.
|
|
90
|
+
*/
|
|
91
|
+
id: string;
|
|
92
|
+
/**
|
|
93
|
+
* False: a job with this `jobId` exists already, nothing was added.
|
|
94
|
+
*/
|
|
95
|
+
created: boolean;
|
|
96
|
+
};
|
|
97
|
+
export type EnqueueItem<P> = {
|
|
98
|
+
payload: P;
|
|
99
|
+
options?: EnqueueOptions;
|
|
100
|
+
};
|
|
101
|
+
export type JobInfo = {
|
|
102
|
+
id: string;
|
|
103
|
+
name: string;
|
|
104
|
+
/**
|
|
105
|
+
* 1 for the first run.
|
|
106
|
+
*/
|
|
107
|
+
attempt: number;
|
|
108
|
+
maxAttempts: number;
|
|
109
|
+
enqueuedAt: Date;
|
|
110
|
+
mutexKeys: readonly string[];
|
|
111
|
+
};
|
|
112
|
+
export type HandlerContext = {
|
|
113
|
+
/**
|
|
114
|
+
* As JSON gives it back.
|
|
115
|
+
*/
|
|
116
|
+
payload: any;
|
|
117
|
+
job: JobInfo;
|
|
118
|
+
/**
|
|
119
|
+
* Aborted with a `JobTimeoutError`, a `LeaseLostError` or a `ShutdownError`.
|
|
120
|
+
*/
|
|
121
|
+
signal: AbortSignal;
|
|
122
|
+
};
|
|
123
|
+
export type Handler = (context: HandlerContext) => unknown;
|
|
124
|
+
export type HandleOptions<L extends string> = {
|
|
125
|
+
timeout?: Duration;
|
|
126
|
+
} & ({
|
|
127
|
+
concurrency?: number;
|
|
128
|
+
lane?: never;
|
|
129
|
+
} | {
|
|
130
|
+
lane: L;
|
|
131
|
+
concurrency?: never;
|
|
132
|
+
});
|
|
133
|
+
export type LaneOptions = {
|
|
134
|
+
/**
|
|
135
|
+
* The handlers of the lane that run at the same time in one process.
|
|
136
|
+
*/
|
|
137
|
+
concurrency: number;
|
|
138
|
+
};
|
|
139
|
+
export type JobDefaults = {
|
|
140
|
+
maxAttempts?: number;
|
|
141
|
+
maxStalls?: number;
|
|
142
|
+
backoff?: Backoff;
|
|
143
|
+
retention?: Retention;
|
|
144
|
+
timeout?: Duration;
|
|
145
|
+
};
|
|
146
|
+
export type Hint = {
|
|
147
|
+
publish: (channel: string, message: string) => Promise<void>;
|
|
148
|
+
/**
|
|
149
|
+
* Resolves to the unsubscribe function.
|
|
150
|
+
*/
|
|
151
|
+
subscribe: (channel: string, onMessage: (message: string) => void) => Promise<() => Promise<void>>;
|
|
152
|
+
};
|
|
153
|
+
export type LogFn = (object: object, message?: string) => void;
|
|
154
|
+
export type Logger = {
|
|
155
|
+
debug: LogFn;
|
|
156
|
+
info: LogFn;
|
|
157
|
+
warn: LogFn;
|
|
158
|
+
error: LogFn;
|
|
159
|
+
};
|
|
160
|
+
export type JobEventBase = {
|
|
161
|
+
jobId: string;
|
|
162
|
+
jobName: string;
|
|
163
|
+
attempt: number;
|
|
164
|
+
};
|
|
165
|
+
export type SqlaneEvent = (JobEventBase & ({
|
|
166
|
+
type: 'claimed';
|
|
167
|
+
} | {
|
|
168
|
+
type: 'completed';
|
|
169
|
+
durationMs: number;
|
|
170
|
+
} | {
|
|
171
|
+
type: 'retried';
|
|
172
|
+
durationMs: number;
|
|
173
|
+
delayMs: number;
|
|
174
|
+
error: unknown;
|
|
175
|
+
} | {
|
|
176
|
+
type: 'failed';
|
|
177
|
+
durationMs: number;
|
|
178
|
+
error: unknown;
|
|
179
|
+
} | {
|
|
180
|
+
type: 'timed_out';
|
|
181
|
+
durationMs: number;
|
|
182
|
+
} | {
|
|
183
|
+
type: 'stalled';
|
|
184
|
+
} | {
|
|
185
|
+
type: 'released';
|
|
186
|
+
} | {
|
|
187
|
+
type: 'lease_lost';
|
|
188
|
+
} | {
|
|
189
|
+
type: 'failure_job_not_added';
|
|
190
|
+
failureJob: string;
|
|
191
|
+
error: unknown;
|
|
192
|
+
})) | {
|
|
193
|
+
type: 'error';
|
|
194
|
+
operation: string;
|
|
195
|
+
error: unknown;
|
|
196
|
+
};
|
|
197
|
+
export type Adapter<C> = {
|
|
198
|
+
dialect: 'mysql' | 'postgres';
|
|
199
|
+
/**
|
|
200
|
+
* Used by sqlane: wraps a connection given to `enqueue`.
|
|
201
|
+
*/
|
|
202
|
+
wrap: (connection: C) => Executor;
|
|
203
|
+
/**
|
|
204
|
+
* Used by sqlane: the queue's own pool.
|
|
205
|
+
*/
|
|
206
|
+
queue: Executor;
|
|
207
|
+
/**
|
|
208
|
+
* Used by sqlane: runs func on
|
|
209
|
+
* one connection of the queue's pool, then releases it.
|
|
210
|
+
*/
|
|
211
|
+
withConnection: <T>(func: (executor: Executor) => Promise<T>) => Promise<T>;
|
|
212
|
+
/**
|
|
213
|
+
* Used by sqlane: runs func
|
|
214
|
+
* in a `READ COMMITTED` transaction on a connection of the queue's pool.
|
|
215
|
+
*/
|
|
216
|
+
queueTransaction: <T>(func: (executor: Executor) => Promise<T>) => Promise<T>;
|
|
217
|
+
/**
|
|
218
|
+
* Used by sqlane:
|
|
219
|
+
* a pool → func in a transaction of its own; a connection or a client → func on it, in the caller's transaction.
|
|
220
|
+
*/
|
|
221
|
+
inTransaction: <T>(connection: C, func: (executor: Executor) => Promise<T>) => Promise<T>;
|
|
222
|
+
/**
|
|
223
|
+
* PostgreSQL: hints by LISTEN/NOTIFY.
|
|
224
|
+
*/
|
|
225
|
+
notify?: boolean;
|
|
226
|
+
/**
|
|
227
|
+
* Used by
|
|
228
|
+
* sqlane, with `notify`: LISTEN on a connection of its own; resolves to the unlisten function.
|
|
229
|
+
*/
|
|
230
|
+
listen?: (channel: string, onMessage: (message: string) => void) => Promise<() => Promise<void>>;
|
|
231
|
+
};
|
|
232
|
+
export type Executor = {
|
|
233
|
+
query: (sql: string, params: readonly unknown[]) => Promise<readonly Record<string, unknown>[]>;
|
|
234
|
+
/**
|
|
235
|
+
* Runs an INSERT, UPDATE or DELETE:
|
|
236
|
+
* the number of rows it changed.
|
|
237
|
+
*/
|
|
238
|
+
run: (sql: string, params: readonly unknown[]) => Promise<number>;
|
|
239
|
+
};
|
|
240
|
+
export type SqlaneOptions<C, L extends string> = {
|
|
241
|
+
adapter: Adapter<C>;
|
|
242
|
+
/**
|
|
243
|
+
* The definitions known by name.
|
|
244
|
+
*/
|
|
245
|
+
jobs?: readonly JobDefinition[];
|
|
246
|
+
/**
|
|
247
|
+
* The handlers that run at the same time in this process. Default: 10.
|
|
248
|
+
*/
|
|
249
|
+
concurrency?: number;
|
|
250
|
+
/**
|
|
251
|
+
* Limits shared by several job names.
|
|
252
|
+
*/
|
|
253
|
+
lanes?: Record<L, LaneOptions>;
|
|
254
|
+
defaults?: JobDefaults;
|
|
255
|
+
/**
|
|
256
|
+
* Default: `'allow'`. `'reject'`: `enqueue` of a name that is not in
|
|
257
|
+
* `jobs` and not handled throws an `UnknownJobError`.
|
|
258
|
+
*/
|
|
259
|
+
unknownJobs?: 'allow' | 'reject';
|
|
260
|
+
/**
|
|
261
|
+
* Default: null: polling only.
|
|
262
|
+
*/
|
|
263
|
+
hint?: Hint | null;
|
|
264
|
+
/**
|
|
265
|
+
* Default: no logs.
|
|
266
|
+
*/
|
|
267
|
+
logger?: Logger;
|
|
268
|
+
onEvent?: (event: SqlaneEvent) => void;
|
|
269
|
+
/**
|
|
270
|
+
* Default: `'sqlane_'`.
|
|
271
|
+
*/
|
|
272
|
+
tablePrefix?: string;
|
|
273
|
+
/**
|
|
274
|
+
* Default: `'5s'`.
|
|
275
|
+
*/
|
|
276
|
+
pollInterval?: Duration;
|
|
277
|
+
/**
|
|
278
|
+
* Default: 256 KiB.
|
|
279
|
+
*/
|
|
280
|
+
maxPayloadBytes?: number;
|
|
281
|
+
/**
|
|
282
|
+
* Built-in deletion of the expired jobs. Default: true.
|
|
283
|
+
*/
|
|
284
|
+
cleanup?: boolean;
|
|
285
|
+
};
|
|
286
|
+
export type DrainOptions = {
|
|
287
|
+
/**
|
|
288
|
+
* Default: `'10s'`.
|
|
289
|
+
*/
|
|
290
|
+
timeout?: Duration;
|
|
291
|
+
/**
|
|
292
|
+
* Also runs the delayed jobs and the retries in backoff at once.
|
|
293
|
+
*/
|
|
294
|
+
includeDelayed?: boolean;
|
|
295
|
+
};
|
|
296
|
+
export type DrainResult = {
|
|
297
|
+
completed: number;
|
|
298
|
+
/**
|
|
299
|
+
* Failed attempts that were retried.
|
|
300
|
+
*/
|
|
301
|
+
retried: number;
|
|
302
|
+
/**
|
|
303
|
+
* Jobs that failed for good.
|
|
304
|
+
*/
|
|
305
|
+
failed: number;
|
|
306
|
+
};
|
|
307
|
+
export type CloseOptions = {
|
|
308
|
+
/**
|
|
309
|
+
* From the call. Default: `'30s'`.
|
|
310
|
+
*/
|
|
311
|
+
deadline?: Duration;
|
|
312
|
+
/**
|
|
313
|
+
* Default: `'release'`.
|
|
314
|
+
*/
|
|
315
|
+
mode?: 'release' | 'abandon';
|
|
316
|
+
/**
|
|
317
|
+
* From the call: the latest time the process exits. Default: the deadline plus one
|
|
318
|
+
* lease.
|
|
319
|
+
*/
|
|
320
|
+
exitsBy?: Duration;
|
|
321
|
+
};
|
|
322
|
+
export type MigrateOptions = {
|
|
323
|
+
/**
|
|
324
|
+
* Default: `'10m'`.
|
|
325
|
+
*/
|
|
326
|
+
lockTimeout?: Duration;
|
|
327
|
+
};
|
|
328
|
+
export type JobStats = {
|
|
329
|
+
name: string;
|
|
330
|
+
pending: number;
|
|
331
|
+
due: number;
|
|
332
|
+
running: number;
|
|
333
|
+
/**
|
|
334
|
+
* Timed out, the handler has not settled.
|
|
335
|
+
*/
|
|
336
|
+
stuck: number;
|
|
337
|
+
failed: number;
|
|
338
|
+
oldestDueAgeMs: number | null;
|
|
339
|
+
};
|
|
340
|
+
export type FailedJobPayload = {
|
|
341
|
+
job: {
|
|
342
|
+
id: string;
|
|
343
|
+
name: string;
|
|
344
|
+
payload: any;
|
|
345
|
+
attempt: number;
|
|
346
|
+
maxAttempts: number;
|
|
347
|
+
};
|
|
348
|
+
error: {
|
|
349
|
+
name: string;
|
|
350
|
+
message: string;
|
|
351
|
+
stack?: string;
|
|
352
|
+
};
|
|
353
|
+
};
|
|
354
|
+
export type Sqlane<C, L extends string> = {
|
|
355
|
+
/**
|
|
356
|
+
* Adds a job with the caller's connection: it must be in a transaction (or a
|
|
357
|
+
* pool: then sqlane opens its own transaction).
|
|
358
|
+
*/
|
|
359
|
+
enqueue: <P>(connection: C, job: JobDefinition | string, payload: P & NoInfer<Jsonable<P>>, options?: EnqueueOptions) => Promise<EnqueueResult>;
|
|
360
|
+
/**
|
|
361
|
+
* The results are in the order of the items.
|
|
362
|
+
*/
|
|
363
|
+
enqueueMany: <P>(connection: C, job: JobDefinition | string, items: readonly (EnqueueItem<P> & NoInfer<EnqueueItem<Jsonable<P>>>)[]) => Promise<EnqueueResult[]>;
|
|
364
|
+
handle: (job: JobDefinition | string, handler: Handler, options?: HandleOptions<L>) => void;
|
|
365
|
+
start: () => Promise<void>;
|
|
366
|
+
/**
|
|
367
|
+
* For tests: runs the due jobs of the handled
|
|
368
|
+
* names until none is left, without `start()`.
|
|
369
|
+
*/
|
|
370
|
+
drain: (options?: DrainOptions) => Promise<DrainResult>;
|
|
371
|
+
close: (options?: CloseOptions) => Promise<void>;
|
|
372
|
+
/**
|
|
373
|
+
* Applies the missing migrations:
|
|
374
|
+
* their ids.
|
|
375
|
+
*/
|
|
376
|
+
migrate: (options?: MigrateOptions) => Promise<{
|
|
377
|
+
applied: string[];
|
|
378
|
+
}>;
|
|
379
|
+
getStats: () => Promise<JobStats[]>;
|
|
380
|
+
/**
|
|
381
|
+
* Low level: probes this name now.
|
|
382
|
+
*/
|
|
383
|
+
wake: (jobName: string) => void;
|
|
384
|
+
};
|
|
385
|
+
export type Migration = {
|
|
386
|
+
id: string;
|
|
387
|
+
statements: readonly string[];
|
|
388
|
+
};
|
|
389
|
+
/**
|
|
390
|
+
* A duration: milliseconds, or a string of parse-duration (`'500ms'`, `'5s'`, `'4m30s'`, `'1h'`, `'2 days'`).
|
|
391
|
+
* @typedef {string | number} Duration
|
|
392
|
+
*/
|
|
393
|
+
/**
|
|
394
|
+
* The JSON form of T: T itself if it is JSON, else a type that T does not match. Optional fields and interfaces pass;
|
|
395
|
+
* a `Date`, a `Map`, a `Set`, a function, a `bigint` or a class instance with methods does not.
|
|
396
|
+
* @template T
|
|
397
|
+
* @typedef {T extends string | number | boolean | null ? T
|
|
398
|
+
* : T extends undefined | bigint | symbol | Function | Date | RegExp | Map<any, any> | Set<any> ? never
|
|
399
|
+
* : T extends readonly (infer U)[] ? readonly Jsonable<U>[]
|
|
400
|
+
* : T extends object ? { [K in keyof T]: Jsonable<T[K]> }
|
|
401
|
+
* : never} Jsonable
|
|
402
|
+
*/
|
|
403
|
+
/**
|
|
404
|
+
* @typedef {object} ExponentialBackoff
|
|
405
|
+
* @property {'exponential'} type `delay × 2^(attempt − 1)`, at most `maxDelay`.
|
|
406
|
+
* @property {Duration} delay
|
|
407
|
+
* @property {Duration} [maxDelay]
|
|
408
|
+
* @property {number} [jitter] 0–1: the delay is `delay × (1 − jitter × random())`. Default: 0.2.
|
|
409
|
+
*/
|
|
410
|
+
/**
|
|
411
|
+
* @typedef {object} FixedBackoff
|
|
412
|
+
* @property {'fixed'} type
|
|
413
|
+
* @property {Duration} delay
|
|
414
|
+
* @property {number} [jitter] 0–1. Default: 0.2.
|
|
415
|
+
*/
|
|
416
|
+
/** @typedef {ExponentialBackoff | FixedBackoff} Backoff */
|
|
417
|
+
/**
|
|
418
|
+
* How long a finished job is kept. It is also the dedupe window of its `jobId`.
|
|
419
|
+
* @typedef {object} Retention
|
|
420
|
+
* @property {Duration} [completed] Default: `'1h'`.
|
|
421
|
+
* @property {Duration} [failed] Default: `'30d'`.
|
|
422
|
+
*/
|
|
423
|
+
/**
|
|
424
|
+
* The options of a job name, shared by its producers and workers. A definition overrides the instance `defaults`.
|
|
425
|
+
* @typedef {object} JobOptions
|
|
426
|
+
* @property {string} name Matches `^[a-z][a-z0-9_.-]{0,127}$`.
|
|
427
|
+
* @property {number} [maxAttempts] Default: 3.
|
|
428
|
+
* @property {number} [maxStalls] Default: 2.
|
|
429
|
+
* @property {Backoff} [backoff]
|
|
430
|
+
* @property {Retention} [retention]
|
|
431
|
+
* @property {Duration} [timeout] No default. A job with mutex keys needs one.
|
|
432
|
+
* @property {(payload: any) => readonly string[]} [mutexKeys] Sync, from the payload only.
|
|
433
|
+
* @property {string | JobDefinition} [failureJob] Added when a job fails for good.
|
|
434
|
+
*/
|
|
435
|
+
/**
|
|
436
|
+
* The result of `defineJob()`. Frozen.
|
|
437
|
+
* @typedef {Readonly<JobOptions>} JobDefinition
|
|
438
|
+
*/
|
|
439
|
+
/**
|
|
440
|
+
* @typedef {object} EnqueueBaseOptions
|
|
441
|
+
* @property {string} [jobId] 1–120 printable ASCII characters. Dedupe: a job with this id is added once while its row
|
|
442
|
+
* exists.
|
|
443
|
+
* @property {number} [maxAttempts]
|
|
444
|
+
* @property {number} [maxStalls]
|
|
445
|
+
* @property {Retention} [retention]
|
|
446
|
+
* @property {string | JobDefinition} [failureJob]
|
|
447
|
+
* @property {readonly string[]} [mutexKeys] Replace the keys of the definition; `[]` clears them.
|
|
448
|
+
*/
|
|
449
|
+
/**
|
|
450
|
+
* The options of an enqueue: `delay` or `runAt`, not both.
|
|
451
|
+
* @typedef {EnqueueBaseOptions & ({ delay?: Duration, runAt?: never } | { runAt: Date, delay?: never })}
|
|
452
|
+
* EnqueueOptions
|
|
453
|
+
*/
|
|
454
|
+
/**
|
|
455
|
+
* @typedef {object} EnqueueResult
|
|
456
|
+
* @property {string} id `<job_name>:<jobId>`, or a new ULID without a `jobId`.
|
|
457
|
+
* @property {boolean} created False: a job with this `jobId` exists already, nothing was added.
|
|
458
|
+
*/
|
|
459
|
+
/**
|
|
460
|
+
* @template P
|
|
461
|
+
* @typedef {object} EnqueueItem
|
|
462
|
+
* @property {P} payload
|
|
463
|
+
* @property {EnqueueOptions} [options]
|
|
464
|
+
*/
|
|
465
|
+
/**
|
|
466
|
+
* @typedef {object} JobInfo
|
|
467
|
+
* @property {string} id
|
|
468
|
+
* @property {string} name
|
|
469
|
+
* @property {number} attempt 1 for the first run.
|
|
470
|
+
* @property {number} maxAttempts
|
|
471
|
+
* @property {Date} enqueuedAt
|
|
472
|
+
* @property {readonly string[]} mutexKeys
|
|
473
|
+
*/
|
|
474
|
+
/**
|
|
475
|
+
* @typedef {object} HandlerContext
|
|
476
|
+
* @property {any} payload As JSON gives it back.
|
|
477
|
+
* @property {JobInfo} job
|
|
478
|
+
* @property {AbortSignal} signal Aborted with a `JobTimeoutError`, a `LeaseLostError` or a `ShutdownError`.
|
|
479
|
+
*/
|
|
480
|
+
/**
|
|
481
|
+
* Runs a job. Its return value is ignored.
|
|
482
|
+
* @typedef {(context: HandlerContext) => unknown} Handler
|
|
483
|
+
*/
|
|
484
|
+
/**
|
|
485
|
+
* A private lane (`concurrency`) or a shared lane of `lanes` (`lane`), not both.
|
|
486
|
+
* @template {string} L
|
|
487
|
+
* @typedef {{ timeout?: Duration } & (
|
|
488
|
+
* { concurrency?: number, lane?: never } | { lane: L, concurrency?: never }
|
|
489
|
+
* )} HandleOptions
|
|
490
|
+
*/
|
|
491
|
+
/**
|
|
492
|
+
* @typedef {object} LaneOptions
|
|
493
|
+
* @property {number} concurrency The handlers of the lane that run at the same time in one process.
|
|
494
|
+
*/
|
|
495
|
+
/**
|
|
496
|
+
* The instance defaults; a definition overrides them.
|
|
497
|
+
* @typedef {object} JobDefaults
|
|
498
|
+
* @property {number} [maxAttempts]
|
|
499
|
+
* @property {number} [maxStalls]
|
|
500
|
+
* @property {Backoff} [backoff]
|
|
501
|
+
* @property {Retention} [retention]
|
|
502
|
+
* @property {Duration} [timeout]
|
|
503
|
+
*/
|
|
504
|
+
/**
|
|
505
|
+
* A pub/sub that wakes the other processes. Only an optimization: a lost message delays a job until the next poll.
|
|
506
|
+
* @typedef {object} Hint
|
|
507
|
+
* @property {(channel: string, message: string) => Promise<void>} publish
|
|
508
|
+
* @property {(channel: string, onMessage: (message: string) => void) => Promise<() => Promise<void>>} subscribe
|
|
509
|
+
* Resolves to the unsubscribe function.
|
|
510
|
+
*/
|
|
511
|
+
/**
|
|
512
|
+
* @typedef {(object: object, message?: string) => void} LogFn
|
|
513
|
+
*/
|
|
514
|
+
/**
|
|
515
|
+
* A pino-compatible logger.
|
|
516
|
+
* @typedef {object} Logger
|
|
517
|
+
* @property {LogFn} debug
|
|
518
|
+
* @property {LogFn} info
|
|
519
|
+
* @property {LogFn} warn
|
|
520
|
+
* @property {LogFn} error
|
|
521
|
+
*/
|
|
522
|
+
/**
|
|
523
|
+
* @typedef {object} JobEventBase
|
|
524
|
+
* @property {string} jobId
|
|
525
|
+
* @property {string} jobName
|
|
526
|
+
* @property {number} attempt
|
|
527
|
+
*/
|
|
528
|
+
/**
|
|
529
|
+
* An event of the job lifecycle, by `type`.
|
|
530
|
+
* @typedef {(JobEventBase & (
|
|
531
|
+
* | { type: 'claimed' }
|
|
532
|
+
* | { type: 'completed', durationMs: number }
|
|
533
|
+
* | { type: 'retried', durationMs: number, delayMs: number, error: unknown }
|
|
534
|
+
* | { type: 'failed', durationMs: number, error: unknown }
|
|
535
|
+
* | { type: 'timed_out', durationMs: number }
|
|
536
|
+
* | { type: 'stalled' }
|
|
537
|
+
* | { type: 'released' }
|
|
538
|
+
* | { type: 'lease_lost' }
|
|
539
|
+
* | { type: 'failure_job_not_added', failureJob: string, error: unknown }
|
|
540
|
+
* )) | { type: 'error', operation: string, error: unknown }} SqlaneEvent
|
|
541
|
+
*/
|
|
542
|
+
/**
|
|
543
|
+
* The connections that `enqueue` accepts (C), and the queue's own pool. Made by `mysql2Adapter()` or `pgAdapter()`.
|
|
544
|
+
* @template C
|
|
545
|
+
* @typedef {object} Adapter
|
|
546
|
+
* @property {'mysql' | 'postgres'} dialect
|
|
547
|
+
* @property {(connection: C) => Executor} wrap Used by sqlane: wraps a connection given to `enqueue`.
|
|
548
|
+
* @property {Executor} queue Used by sqlane: the queue's own pool.
|
|
549
|
+
* @property {<T>(func: (executor: Executor) => Promise<T>) => Promise<T>} withConnection Used by sqlane: runs func on
|
|
550
|
+
* one connection of the queue's pool, then releases it.
|
|
551
|
+
* @property {<T>(func: (executor: Executor) => Promise<T>) => Promise<T>} queueTransaction Used by sqlane: runs func
|
|
552
|
+
* in a `READ COMMITTED` transaction on a connection of the queue's pool.
|
|
553
|
+
* @property {<T>(connection: C, func: (executor: Executor) => Promise<T>) => Promise<T>} inTransaction Used by sqlane:
|
|
554
|
+
* a pool → func in a transaction of its own; a connection or a client → func on it, in the caller's transaction.
|
|
555
|
+
* @property {boolean} [notify] PostgreSQL: hints by LISTEN/NOTIFY.
|
|
556
|
+
* @property {(channel: string, onMessage: (message: string) => void) => Promise<() => Promise<void>>} [listen] Used by
|
|
557
|
+
* sqlane, with `notify`: LISTEN on a connection of its own; resolves to the unlisten function.
|
|
558
|
+
*/
|
|
559
|
+
/**
|
|
560
|
+
* Runs SQL. Used by sqlane, through an adapter.
|
|
561
|
+
* @typedef {object} Executor
|
|
562
|
+
* @property {(sql: string, params: readonly unknown[]) => Promise<readonly Record<string, unknown>[]>} query
|
|
563
|
+
* @property {(sql: string, params: readonly unknown[]) => Promise<number>} run Runs an INSERT, UPDATE or DELETE:
|
|
564
|
+
* the number of rows it changed.
|
|
565
|
+
*/
|
|
566
|
+
/**
|
|
567
|
+
* @template C
|
|
568
|
+
* @template {string} L
|
|
569
|
+
* @typedef {object} SqlaneOptions
|
|
570
|
+
* @property {Adapter<C>} adapter
|
|
571
|
+
* @property {readonly JobDefinition[]} [jobs] The definitions known by name.
|
|
572
|
+
* @property {number} [concurrency] The handlers that run at the same time in this process. Default: 10.
|
|
573
|
+
* @property {Record<L, LaneOptions>} [lanes] Limits shared by several job names.
|
|
574
|
+
* @property {JobDefaults} [defaults]
|
|
575
|
+
* @property {'allow' | 'reject'} [unknownJobs] Default: `'allow'`. `'reject'`: `enqueue` of a name that is not in
|
|
576
|
+
* `jobs` and not handled throws an `UnknownJobError`.
|
|
577
|
+
* @property {Hint | null} [hint] Default: null: polling only.
|
|
578
|
+
* @property {Logger} [logger] Default: no logs.
|
|
579
|
+
* @property {(event: SqlaneEvent) => void} [onEvent]
|
|
580
|
+
* @property {string} [tablePrefix] Default: `'sqlane_'`.
|
|
581
|
+
* @property {Duration} [pollInterval] Default: `'5s'`.
|
|
582
|
+
* @property {number} [maxPayloadBytes] Default: 256 KiB.
|
|
583
|
+
* @property {boolean} [cleanup] Built-in deletion of the expired jobs. Default: true.
|
|
584
|
+
*/
|
|
585
|
+
/**
|
|
586
|
+
* @typedef {object} DrainOptions
|
|
587
|
+
* @property {Duration} [timeout] Default: `'10s'`.
|
|
588
|
+
* @property {boolean} [includeDelayed] Also runs the delayed jobs and the retries in backoff at once.
|
|
589
|
+
*/
|
|
590
|
+
/**
|
|
591
|
+
* @typedef {object} DrainResult
|
|
592
|
+
* @property {number} completed
|
|
593
|
+
* @property {number} retried Failed attempts that were retried.
|
|
594
|
+
* @property {number} failed Jobs that failed for good.
|
|
595
|
+
*/
|
|
596
|
+
/**
|
|
597
|
+
* @typedef {object} CloseOptions
|
|
598
|
+
* @property {Duration} [deadline] From the call. Default: `'30s'`.
|
|
599
|
+
* @property {'release' | 'abandon'} [mode] Default: `'release'`.
|
|
600
|
+
* @property {Duration} [exitsBy] From the call: the latest time the process exits. Default: the deadline plus one
|
|
601
|
+
* lease.
|
|
602
|
+
*/
|
|
603
|
+
/**
|
|
604
|
+
* @typedef {object} MigrateOptions
|
|
605
|
+
* @property {Duration} [lockTimeout] Default: `'10m'`.
|
|
606
|
+
*/
|
|
607
|
+
/**
|
|
608
|
+
* @typedef {object} JobStats
|
|
609
|
+
* @property {string} name
|
|
610
|
+
* @property {number} pending
|
|
611
|
+
* @property {number} due
|
|
612
|
+
* @property {number} running
|
|
613
|
+
* @property {number} stuck Timed out, the handler has not settled.
|
|
614
|
+
* @property {number} failed
|
|
615
|
+
* @property {number | null} oldestDueAgeMs
|
|
616
|
+
*/
|
|
617
|
+
/**
|
|
618
|
+
* The payload of a failure job.
|
|
619
|
+
* @typedef {object} FailedJobPayload
|
|
620
|
+
* @property {{ id: string, name: string, payload: any, attempt: number, maxAttempts: number }} job
|
|
621
|
+
* @property {{ name: string, message: string, stack?: string }} error
|
|
622
|
+
*/
|
|
623
|
+
/**
|
|
624
|
+
* @template C The connections that `enqueue` accepts.
|
|
625
|
+
* @template {string} L The lane names.
|
|
626
|
+
* @typedef {object} Sqlane
|
|
627
|
+
* @property {<P>(
|
|
628
|
+
* connection: C, job: JobDefinition | string, payload: P & NoInfer<Jsonable<P>>, options?: EnqueueOptions,
|
|
629
|
+
* ) => Promise<EnqueueResult>} enqueue Adds a job with the caller's connection: it must be in a transaction (or a
|
|
630
|
+
* pool: then sqlane opens its own transaction).
|
|
631
|
+
* @property {<P>(
|
|
632
|
+
* connection: C,
|
|
633
|
+
* job: JobDefinition | string,
|
|
634
|
+
* items: readonly (EnqueueItem<P> & NoInfer<EnqueueItem<Jsonable<P>>>)[],
|
|
635
|
+
* ) => Promise<EnqueueResult[]>} enqueueMany The results are in the order of the items.
|
|
636
|
+
* @property {(job: JobDefinition | string, handler: Handler, options?: HandleOptions<L>) => void} handle
|
|
637
|
+
* @property {() => Promise<void>} start
|
|
638
|
+
* @property {(options?: DrainOptions) => Promise<DrainResult>} drain For tests: runs the due jobs of the handled
|
|
639
|
+
* names until none is left, without `start()`.
|
|
640
|
+
* @property {(options?: CloseOptions) => Promise<void>} close
|
|
641
|
+
* @property {(options?: MigrateOptions) => Promise<{ applied: string[] }>} migrate Applies the missing migrations:
|
|
642
|
+
* their ids.
|
|
643
|
+
* @property {() => Promise<JobStats[]>} getStats
|
|
644
|
+
* @property {(jobName: string) => void} wake Low level: probes this name now.
|
|
645
|
+
*/
|
|
646
|
+
/**
|
|
647
|
+
* @typedef {object} Migration
|
|
648
|
+
* @property {string} id
|
|
649
|
+
* @property {readonly string[]} statements
|
|
650
|
+
*/
|
|
651
|
+
export {};
|