@nicnocquee/dataqueue 1.24.0 → 1.26.0-beta.20260223195940
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 +44 -0
- package/ai/build-docs-content.ts +96 -0
- package/ai/build-llms-full.ts +42 -0
- package/ai/docs-content.json +278 -0
- package/ai/rules/advanced.md +132 -0
- package/ai/rules/basic.md +159 -0
- package/ai/rules/react-dashboard.md +83 -0
- package/ai/skills/dataqueue-advanced/SKILL.md +320 -0
- package/ai/skills/dataqueue-core/SKILL.md +234 -0
- package/ai/skills/dataqueue-react/SKILL.md +189 -0
- package/dist/cli.cjs +1149 -14
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +66 -1
- package/dist/cli.d.ts +66 -1
- package/dist/cli.js +1146 -13
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +4630 -928
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1033 -15
- package/dist/index.d.ts +1033 -15
- package/dist/index.js +4626 -929
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.cjs +186 -0
- package/dist/mcp-server.cjs.map +1 -0
- package/dist/mcp-server.d.cts +32 -0
- package/dist/mcp-server.d.ts +32 -0
- package/dist/mcp-server.js +175 -0
- package/dist/mcp-server.js.map +1 -0
- package/migrations/1751131910825_add_timeout_seconds_to_job_queue.sql +2 -2
- package/migrations/1751186053000_add_job_events_table.sql +12 -8
- package/migrations/1751984773000_add_tags_to_job_queue.sql +1 -1
- package/migrations/1765809419000_add_force_kill_on_timeout_to_job_queue.sql +1 -1
- package/migrations/1771100000000_add_idempotency_key_to_job_queue.sql +7 -0
- package/migrations/1781200000000_add_wait_support.sql +12 -0
- package/migrations/1781200000001_create_waitpoints_table.sql +18 -0
- package/migrations/1781200000002_add_performance_indexes.sql +34 -0
- package/migrations/1781200000003_add_progress_to_job_queue.sql +7 -0
- package/migrations/1781200000004_create_cron_schedules_table.sql +33 -0
- package/migrations/1781200000005_add_retry_config_to_job_queue.sql +17 -0
- package/package.json +40 -23
- package/src/backend.ts +328 -0
- package/src/backends/postgres.ts +2040 -0
- package/src/backends/redis-scripts.ts +865 -0
- package/src/backends/redis.test.ts +1906 -0
- package/src/backends/redis.ts +1792 -0
- package/src/cli.test.ts +82 -6
- package/src/cli.ts +73 -10
- package/src/cron.test.ts +126 -0
- package/src/cron.ts +40 -0
- package/src/db-util.ts +4 -2
- package/src/index.test.ts +688 -1
- package/src/index.ts +277 -39
- package/src/init-command.test.ts +449 -0
- package/src/init-command.ts +709 -0
- package/src/install-mcp-command.test.ts +216 -0
- package/src/install-mcp-command.ts +185 -0
- package/src/install-rules-command.test.ts +218 -0
- package/src/install-rules-command.ts +233 -0
- package/src/install-skills-command.test.ts +176 -0
- package/src/install-skills-command.ts +124 -0
- package/src/mcp-server.test.ts +162 -0
- package/src/mcp-server.ts +231 -0
- package/src/processor.test.ts +559 -18
- package/src/processor.ts +456 -49
- package/src/queue.test.ts +682 -6
- package/src/queue.ts +135 -944
- package/src/supervisor.test.ts +340 -0
- package/src/supervisor.ts +162 -0
- package/src/test-util.ts +32 -0
- package/src/types.ts +726 -17
- package/src/wait.test.ts +698 -0
- package/LICENSE +0 -21
package/src/index.ts
CHANGED
|
@@ -1,63 +1,160 @@
|
|
|
1
|
-
import {
|
|
2
|
-
addJob,
|
|
3
|
-
getJob,
|
|
4
|
-
getJobsByStatus,
|
|
5
|
-
retryJob,
|
|
6
|
-
cleanupOldJobs,
|
|
7
|
-
cancelJob,
|
|
8
|
-
cancelAllUpcomingJobs,
|
|
9
|
-
getAllJobs,
|
|
10
|
-
reclaimStuckJobs,
|
|
11
|
-
getJobEvents,
|
|
12
|
-
getJobsByTags,
|
|
13
|
-
getJobs,
|
|
14
|
-
editJob,
|
|
15
|
-
editAllPendingJobs,
|
|
16
|
-
} from './queue.js';
|
|
17
1
|
import { createProcessor } from './processor.js';
|
|
2
|
+
import { createSupervisor } from './supervisor.js';
|
|
18
3
|
import {
|
|
19
4
|
JobQueueConfig,
|
|
20
5
|
JobQueue,
|
|
21
6
|
JobOptions,
|
|
7
|
+
AddJobOptions,
|
|
22
8
|
ProcessorOptions,
|
|
9
|
+
SupervisorOptions,
|
|
23
10
|
JobHandlers,
|
|
24
11
|
JobType,
|
|
12
|
+
PostgresJobQueueConfig,
|
|
13
|
+
RedisJobQueueConfig,
|
|
14
|
+
CronScheduleOptions,
|
|
15
|
+
CronScheduleStatus,
|
|
16
|
+
EditCronScheduleOptions,
|
|
25
17
|
} from './types.js';
|
|
18
|
+
import { QueueBackend, CronScheduleInput } from './backend.js';
|
|
26
19
|
import { setLogContext } from './log-context.js';
|
|
27
20
|
import { createPool } from './db-util.js';
|
|
21
|
+
import { PostgresBackend } from './backends/postgres.js';
|
|
22
|
+
import { RedisBackend } from './backends/redis.js';
|
|
23
|
+
import { getNextCronOccurrence, validateCronExpression } from './cron.js';
|
|
28
24
|
|
|
29
25
|
/**
|
|
30
|
-
* Initialize the job queue system
|
|
26
|
+
* Initialize the job queue system.
|
|
27
|
+
*
|
|
28
|
+
* Defaults to PostgreSQL when `backend` is omitted.
|
|
29
|
+
* For PostgreSQL, provide either `databaseConfig` or `pool` (bring your own).
|
|
30
|
+
* For Redis, provide either `redisConfig` or `client` (bring your own).
|
|
31
31
|
*/
|
|
32
32
|
export const initJobQueue = <PayloadMap = any>(
|
|
33
33
|
config: JobQueueConfig,
|
|
34
34
|
): JobQueue<PayloadMap> => {
|
|
35
|
-
const
|
|
35
|
+
const backendType = config.backend ?? 'postgres';
|
|
36
|
+
setLogContext(config.verbose ?? false);
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
const pool = createPool(databaseConfig);
|
|
38
|
+
let backend: QueueBackend;
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
if (backendType === 'postgres') {
|
|
41
|
+
const pgConfig = config as PostgresJobQueueConfig;
|
|
42
|
+
if (pgConfig.pool) {
|
|
43
|
+
backend = new PostgresBackend(pgConfig.pool);
|
|
44
|
+
} else if (pgConfig.databaseConfig) {
|
|
45
|
+
const pool = createPool(pgConfig.databaseConfig);
|
|
46
|
+
backend = new PostgresBackend(pool);
|
|
47
|
+
} else {
|
|
48
|
+
throw new Error(
|
|
49
|
+
'PostgreSQL backend requires either "databaseConfig" or "pool" to be provided.',
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
} else if (backendType === 'redis') {
|
|
53
|
+
const redisConfig = config as RedisJobQueueConfig;
|
|
54
|
+
if (redisConfig.client) {
|
|
55
|
+
backend = new RedisBackend(
|
|
56
|
+
redisConfig.client as any,
|
|
57
|
+
redisConfig.keyPrefix,
|
|
58
|
+
);
|
|
59
|
+
} else if (redisConfig.redisConfig) {
|
|
60
|
+
backend = new RedisBackend(redisConfig.redisConfig);
|
|
61
|
+
} else {
|
|
62
|
+
throw new Error(
|
|
63
|
+
'Redis backend requires either "redisConfig" or "client" to be provided.',
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
throw new Error(`Unknown backend: ${backendType}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Enqueue due cron jobs. Shared by the public API and the processor hook.
|
|
72
|
+
*/
|
|
73
|
+
const enqueueDueCronJobsImpl = async (): Promise<number> => {
|
|
74
|
+
const dueSchedules = await backend.getDueCronSchedules();
|
|
75
|
+
let count = 0;
|
|
76
|
+
|
|
77
|
+
for (const schedule of dueSchedules) {
|
|
78
|
+
// Overlap check: skip if allowOverlap is false and last job is still active
|
|
79
|
+
if (!schedule.allowOverlap && schedule.lastJobId !== null) {
|
|
80
|
+
const lastJob = await backend.getJob(schedule.lastJobId);
|
|
81
|
+
if (
|
|
82
|
+
lastJob &&
|
|
83
|
+
(lastJob.status === 'pending' ||
|
|
84
|
+
lastJob.status === 'processing' ||
|
|
85
|
+
lastJob.status === 'waiting')
|
|
86
|
+
) {
|
|
87
|
+
// Still active — advance nextRunAt but don't enqueue
|
|
88
|
+
const nextRunAt = getNextCronOccurrence(
|
|
89
|
+
schedule.cronExpression,
|
|
90
|
+
schedule.timezone,
|
|
91
|
+
);
|
|
92
|
+
await backend.updateCronScheduleAfterEnqueue(
|
|
93
|
+
schedule.id,
|
|
94
|
+
new Date(),
|
|
95
|
+
schedule.lastJobId,
|
|
96
|
+
nextRunAt,
|
|
97
|
+
);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Enqueue a new job instance
|
|
103
|
+
const jobId = await backend.addJob<any, any>({
|
|
104
|
+
jobType: schedule.jobType,
|
|
105
|
+
payload: schedule.payload,
|
|
106
|
+
maxAttempts: schedule.maxAttempts,
|
|
107
|
+
priority: schedule.priority,
|
|
108
|
+
timeoutMs: schedule.timeoutMs ?? undefined,
|
|
109
|
+
forceKillOnTimeout: schedule.forceKillOnTimeout,
|
|
110
|
+
tags: schedule.tags,
|
|
111
|
+
retryDelay: schedule.retryDelay ?? undefined,
|
|
112
|
+
retryBackoff: schedule.retryBackoff ?? undefined,
|
|
113
|
+
retryDelayMax: schedule.retryDelayMax ?? undefined,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Advance to next occurrence
|
|
117
|
+
const nextRunAt = getNextCronOccurrence(
|
|
118
|
+
schedule.cronExpression,
|
|
119
|
+
schedule.timezone,
|
|
120
|
+
);
|
|
121
|
+
await backend.updateCronScheduleAfterEnqueue(
|
|
122
|
+
schedule.id,
|
|
123
|
+
new Date(),
|
|
124
|
+
jobId,
|
|
125
|
+
nextRunAt,
|
|
126
|
+
);
|
|
127
|
+
count++;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return count;
|
|
131
|
+
};
|
|
41
132
|
|
|
42
133
|
// Return the job queue API
|
|
43
134
|
return {
|
|
44
135
|
// Job queue operations
|
|
45
136
|
addJob: withLogContext(
|
|
46
|
-
(job: JobOptions<PayloadMap, any
|
|
137
|
+
(job: JobOptions<PayloadMap, any>, options?: AddJobOptions) =>
|
|
138
|
+
backend.addJob<PayloadMap, any>(job, options),
|
|
139
|
+
config.verbose ?? false,
|
|
140
|
+
),
|
|
141
|
+
addJobs: withLogContext(
|
|
142
|
+
(jobs: JobOptions<PayloadMap, any>[], options?: AddJobOptions) =>
|
|
143
|
+
backend.addJobs<PayloadMap, any>(jobs, options),
|
|
47
144
|
config.verbose ?? false,
|
|
48
145
|
),
|
|
49
146
|
getJob: withLogContext(
|
|
50
|
-
(id: number) => getJob<PayloadMap, any>(
|
|
147
|
+
(id: number) => backend.getJob<PayloadMap, any>(id),
|
|
51
148
|
config.verbose ?? false,
|
|
52
149
|
),
|
|
53
150
|
getJobsByStatus: withLogContext(
|
|
54
151
|
(status: string, limit?: number, offset?: number) =>
|
|
55
|
-
getJobsByStatus<PayloadMap, any>(
|
|
152
|
+
backend.getJobsByStatus<PayloadMap, any>(status, limit, offset),
|
|
56
153
|
config.verbose ?? false,
|
|
57
154
|
),
|
|
58
155
|
getAllJobs: withLogContext(
|
|
59
156
|
(limit?: number, offset?: number) =>
|
|
60
|
-
getAllJobs<PayloadMap, any>(
|
|
157
|
+
backend.getAllJobs<PayloadMap, any>(limit, offset),
|
|
61
158
|
config.verbose ?? false,
|
|
62
159
|
),
|
|
63
160
|
getJobs: withLogContext(
|
|
@@ -72,20 +169,23 @@ export const initJobQueue = <PayloadMap = any>(
|
|
|
72
169
|
},
|
|
73
170
|
limit?: number,
|
|
74
171
|
offset?: number,
|
|
75
|
-
) => getJobs<PayloadMap, any>(
|
|
172
|
+
) => backend.getJobs<PayloadMap, any>(filters, limit, offset),
|
|
76
173
|
config.verbose ?? false,
|
|
77
174
|
),
|
|
78
|
-
retryJob: (jobId: number) => retryJob(
|
|
79
|
-
cleanupOldJobs: (daysToKeep?: number) =>
|
|
175
|
+
retryJob: (jobId: number) => backend.retryJob(jobId),
|
|
176
|
+
cleanupOldJobs: (daysToKeep?: number, batchSize?: number) =>
|
|
177
|
+
backend.cleanupOldJobs(daysToKeep, batchSize),
|
|
178
|
+
cleanupOldJobEvents: (daysToKeep?: number, batchSize?: number) =>
|
|
179
|
+
backend.cleanupOldJobEvents(daysToKeep, batchSize),
|
|
80
180
|
cancelJob: withLogContext(
|
|
81
|
-
(jobId: number) => cancelJob(
|
|
181
|
+
(jobId: number) => backend.cancelJob(jobId),
|
|
82
182
|
config.verbose ?? false,
|
|
83
183
|
),
|
|
84
184
|
editJob: withLogContext(
|
|
85
185
|
<T extends JobType<PayloadMap>>(
|
|
86
186
|
jobId: number,
|
|
87
187
|
updates: import('./types.js').EditJobOptions<PayloadMap, T>,
|
|
88
|
-
) => editJob
|
|
188
|
+
) => backend.editJob(jobId, updates as import('./backend.js').JobUpdates),
|
|
89
189
|
config.verbose ?? false,
|
|
90
190
|
),
|
|
91
191
|
editAllPendingJobs: withLogContext(
|
|
@@ -104,7 +204,11 @@ export const initJobQueue = <PayloadMap = any>(
|
|
|
104
204
|
}
|
|
105
205
|
| undefined,
|
|
106
206
|
updates: import('./types.js').EditJobOptions<PayloadMap, T>,
|
|
107
|
-
) =>
|
|
207
|
+
) =>
|
|
208
|
+
backend.editAllPendingJobs(
|
|
209
|
+
filters,
|
|
210
|
+
updates as import('./backend.js').JobUpdates,
|
|
211
|
+
),
|
|
108
212
|
config.verbose ?? false,
|
|
109
213
|
),
|
|
110
214
|
cancelAllUpcomingJobs: withLogContext(
|
|
@@ -115,32 +219,163 @@ export const initJobQueue = <PayloadMap = any>(
|
|
|
115
219
|
| Date
|
|
116
220
|
| { gt?: Date; gte?: Date; lt?: Date; lte?: Date; eq?: Date };
|
|
117
221
|
tags?: { values: string[]; mode?: import('./types.js').TagQueryMode };
|
|
118
|
-
}) => cancelAllUpcomingJobs(
|
|
222
|
+
}) => backend.cancelAllUpcomingJobs(filters),
|
|
119
223
|
config.verbose ?? false,
|
|
120
224
|
),
|
|
121
225
|
reclaimStuckJobs: withLogContext(
|
|
122
226
|
(maxProcessingTimeMinutes?: number) =>
|
|
123
|
-
reclaimStuckJobs(
|
|
227
|
+
backend.reclaimStuckJobs(maxProcessingTimeMinutes),
|
|
124
228
|
config.verbose ?? false,
|
|
125
229
|
),
|
|
126
230
|
getJobsByTags: withLogContext(
|
|
127
231
|
(tags: string[], mode = 'all', limit?: number, offset?: number) =>
|
|
128
|
-
getJobsByTags<PayloadMap, any>(
|
|
232
|
+
backend.getJobsByTags<PayloadMap, any>(tags, mode, limit, offset),
|
|
129
233
|
config.verbose ?? false,
|
|
130
234
|
),
|
|
131
235
|
|
|
132
|
-
// Job processing
|
|
236
|
+
// Job processing — automatically enqueues due cron jobs before each batch
|
|
133
237
|
createProcessor: (
|
|
134
238
|
handlers: JobHandlers<PayloadMap>,
|
|
135
239
|
options?: ProcessorOptions,
|
|
136
|
-
) =>
|
|
137
|
-
|
|
138
|
-
|
|
240
|
+
) =>
|
|
241
|
+
createProcessor<PayloadMap>(backend, handlers, options, async () => {
|
|
242
|
+
await enqueueDueCronJobsImpl();
|
|
243
|
+
}),
|
|
244
|
+
|
|
245
|
+
// Background supervisor — automated maintenance
|
|
246
|
+
createSupervisor: (options?: SupervisorOptions) =>
|
|
247
|
+
createSupervisor(backend, options),
|
|
248
|
+
|
|
139
249
|
// Job events
|
|
140
250
|
getJobEvents: withLogContext(
|
|
141
|
-
(jobId: number) => getJobEvents(
|
|
251
|
+
(jobId: number) => backend.getJobEvents(jobId),
|
|
252
|
+
config.verbose ?? false,
|
|
253
|
+
),
|
|
254
|
+
|
|
255
|
+
// Wait / Token support (works with all backends)
|
|
256
|
+
createToken: withLogContext(
|
|
257
|
+
(options?: import('./types.js').CreateTokenOptions) =>
|
|
258
|
+
backend.createWaitpoint(null, options),
|
|
259
|
+
config.verbose ?? false,
|
|
260
|
+
),
|
|
261
|
+
completeToken: withLogContext(
|
|
262
|
+
(tokenId: string, data?: any) => backend.completeWaitpoint(tokenId, data),
|
|
263
|
+
config.verbose ?? false,
|
|
264
|
+
),
|
|
265
|
+
getToken: withLogContext(
|
|
266
|
+
(tokenId: string) => backend.getWaitpoint(tokenId),
|
|
267
|
+
config.verbose ?? false,
|
|
268
|
+
),
|
|
269
|
+
expireTimedOutTokens: withLogContext(
|
|
270
|
+
() => backend.expireTimedOutWaitpoints(),
|
|
142
271
|
config.verbose ?? false,
|
|
143
272
|
),
|
|
273
|
+
|
|
274
|
+
// Cron schedule operations
|
|
275
|
+
addCronJob: withLogContext(
|
|
276
|
+
<T extends JobType<PayloadMap>>(
|
|
277
|
+
options: CronScheduleOptions<PayloadMap, T>,
|
|
278
|
+
) => {
|
|
279
|
+
if (!validateCronExpression(options.cronExpression)) {
|
|
280
|
+
return Promise.reject(
|
|
281
|
+
new Error(`Invalid cron expression: "${options.cronExpression}"`),
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
const nextRunAt = getNextCronOccurrence(
|
|
285
|
+
options.cronExpression,
|
|
286
|
+
options.timezone ?? 'UTC',
|
|
287
|
+
);
|
|
288
|
+
const input: CronScheduleInput = {
|
|
289
|
+
scheduleName: options.scheduleName,
|
|
290
|
+
cronExpression: options.cronExpression,
|
|
291
|
+
jobType: options.jobType as string,
|
|
292
|
+
payload: options.payload,
|
|
293
|
+
maxAttempts: options.maxAttempts ?? 3,
|
|
294
|
+
priority: options.priority ?? 0,
|
|
295
|
+
timeoutMs: options.timeoutMs ?? null,
|
|
296
|
+
forceKillOnTimeout: options.forceKillOnTimeout ?? false,
|
|
297
|
+
tags: options.tags,
|
|
298
|
+
timezone: options.timezone ?? 'UTC',
|
|
299
|
+
allowOverlap: options.allowOverlap ?? false,
|
|
300
|
+
nextRunAt,
|
|
301
|
+
retryDelay: options.retryDelay ?? null,
|
|
302
|
+
retryBackoff: options.retryBackoff ?? null,
|
|
303
|
+
retryDelayMax: options.retryDelayMax ?? null,
|
|
304
|
+
};
|
|
305
|
+
return backend.addCronSchedule(input);
|
|
306
|
+
},
|
|
307
|
+
config.verbose ?? false,
|
|
308
|
+
),
|
|
309
|
+
getCronJob: withLogContext(
|
|
310
|
+
(id: number) => backend.getCronSchedule(id),
|
|
311
|
+
config.verbose ?? false,
|
|
312
|
+
),
|
|
313
|
+
getCronJobByName: withLogContext(
|
|
314
|
+
(name: string) => backend.getCronScheduleByName(name),
|
|
315
|
+
config.verbose ?? false,
|
|
316
|
+
),
|
|
317
|
+
listCronJobs: withLogContext(
|
|
318
|
+
(status?: CronScheduleStatus) => backend.listCronSchedules(status),
|
|
319
|
+
config.verbose ?? false,
|
|
320
|
+
),
|
|
321
|
+
removeCronJob: withLogContext(
|
|
322
|
+
(id: number) => backend.removeCronSchedule(id),
|
|
323
|
+
config.verbose ?? false,
|
|
324
|
+
),
|
|
325
|
+
pauseCronJob: withLogContext(
|
|
326
|
+
(id: number) => backend.pauseCronSchedule(id),
|
|
327
|
+
config.verbose ?? false,
|
|
328
|
+
),
|
|
329
|
+
resumeCronJob: withLogContext(
|
|
330
|
+
(id: number) => backend.resumeCronSchedule(id),
|
|
331
|
+
config.verbose ?? false,
|
|
332
|
+
),
|
|
333
|
+
editCronJob: withLogContext(
|
|
334
|
+
async (id: number, updates: EditCronScheduleOptions) => {
|
|
335
|
+
if (
|
|
336
|
+
updates.cronExpression !== undefined &&
|
|
337
|
+
!validateCronExpression(updates.cronExpression)
|
|
338
|
+
) {
|
|
339
|
+
throw new Error(
|
|
340
|
+
`Invalid cron expression: "${updates.cronExpression}"`,
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
let nextRunAt: Date | null | undefined;
|
|
344
|
+
if (
|
|
345
|
+
updates.cronExpression !== undefined ||
|
|
346
|
+
updates.timezone !== undefined
|
|
347
|
+
) {
|
|
348
|
+
const existing = await backend.getCronSchedule(id);
|
|
349
|
+
const expr = updates.cronExpression ?? existing?.cronExpression ?? '';
|
|
350
|
+
const tz = updates.timezone ?? existing?.timezone ?? 'UTC';
|
|
351
|
+
nextRunAt = getNextCronOccurrence(expr, tz);
|
|
352
|
+
}
|
|
353
|
+
await backend.editCronSchedule(id, updates, nextRunAt);
|
|
354
|
+
},
|
|
355
|
+
config.verbose ?? false,
|
|
356
|
+
),
|
|
357
|
+
enqueueDueCronJobs: withLogContext(
|
|
358
|
+
() => enqueueDueCronJobsImpl(),
|
|
359
|
+
config.verbose ?? false,
|
|
360
|
+
),
|
|
361
|
+
|
|
362
|
+
// Advanced access
|
|
363
|
+
getPool: () => {
|
|
364
|
+
if (!(backend instanceof PostgresBackend)) {
|
|
365
|
+
throw new Error(
|
|
366
|
+
'getPool() is only available with the PostgreSQL backend.',
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
return backend.getPool();
|
|
370
|
+
},
|
|
371
|
+
getRedisClient: () => {
|
|
372
|
+
if (backendType !== 'redis') {
|
|
373
|
+
throw new Error(
|
|
374
|
+
'getRedisClient() is only available with the Redis backend.',
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
return (backend as RedisBackend).getClient();
|
|
378
|
+
},
|
|
144
379
|
};
|
|
145
380
|
};
|
|
146
381
|
|
|
@@ -152,7 +387,10 @@ const withLogContext =
|
|
|
152
387
|
};
|
|
153
388
|
|
|
154
389
|
export * from './types.js';
|
|
390
|
+
export { QueueBackend, CronScheduleInput } from './backend.js';
|
|
391
|
+
export { PostgresBackend } from './backends/postgres.js';
|
|
155
392
|
export {
|
|
156
393
|
validateHandlerSerializable,
|
|
157
394
|
testHandlerSerialization,
|
|
158
395
|
} from './handler-validation.js';
|
|
396
|
+
export { getNextCronOccurrence, validateCronExpression } from './cron.js';
|