@keystrokehq/scheduler 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,66 +1,10 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_contract = require("./contract-C5JvbyQ-.cjs");
3
3
  let _keystrokehq_database = require("@keystrokehq/database");
4
- let _keystrokehq_trigger = require("@keystrokehq/trigger");
5
4
  let node_events = require("node:events");
5
+ let _keystrokehq_trigger = require("@keystrokehq/trigger");
6
6
  let pg_boss = require("pg-boss");
7
7
  let node_crypto = require("node:crypto");
8
- //#region src/schedule-ticker.ts
9
- function enqueueTriggerJob(jobQueue, row, scheduledAt) {
10
- const input = {
11
- kind: "trigger",
12
- targetId: row.attachmentSlug,
13
- runId: crypto.randomUUID(),
14
- trigger: row.kind,
15
- payload: {},
16
- projectId: row.projectId
17
- };
18
- if (scheduledAt) input.scheduledAt = scheduledAt;
19
- return jobQueue.enqueue(input);
20
- }
21
- async function claimDue(scope, asOf, resolveNextRunAt, limit) {
22
- if (scope === "organization") return (0, _keystrokehq_database.claimDueTriggerSchedulesForOrg)(asOf, resolveNextRunAt, limit);
23
- return (0, _keystrokehq_database.claimDueTriggerSchedules)(asOf, resolveNextRunAt, limit).then((rows) => rows.map((row) => ({
24
- ...row,
25
- projectId: (0, _keystrokehq_database.getProjectScopeId)()
26
- })));
27
- }
28
- function createScheduleTicker(ctx) {
29
- const pollIntervalMs = ctx.pollIntervalMs ?? 1e3;
30
- const batchSize = ctx.batchSize ?? 10;
31
- async function fireDueSchedules(asOf = /* @__PURE__ */ new Date()) {
32
- const claimed = await claimDue(ctx.scope ?? "project", asOf, (schedule) => (0, _keystrokehq_trigger.nextTriggerRunAt)(schedule, asOf), batchSize);
33
- for (const row of claimed) await enqueueTriggerJob(ctx.jobQueue, row, asOf);
34
- return claimed.length;
35
- }
36
- async function startScheduleTicker(options = {}) {
37
- const intervalMs = options.pollIntervalMs ?? pollIntervalMs;
38
- const limit = options.batchSize ?? batchSize;
39
- const scope = options.scope ?? ctx.scope ?? "project";
40
- let running = true;
41
- const loop = async () => {
42
- while (running) {
43
- try {
44
- const claimed = await claimDue(scope, /* @__PURE__ */ new Date(), (schedule) => (0, _keystrokehq_trigger.nextTriggerRunAt)(schedule, /* @__PURE__ */ new Date()), limit);
45
- for (const row of claimed) await enqueueTriggerJob(ctx.jobQueue, row);
46
- } catch {}
47
- await sleep$1(intervalMs);
48
- }
49
- };
50
- loop();
51
- return async () => {
52
- running = false;
53
- };
54
- }
55
- return {
56
- fireDueSchedules,
57
- startScheduleTicker
58
- };
59
- }
60
- function sleep$1(ms) {
61
- return new Promise((resolve) => setTimeout(resolve, ms));
62
- }
63
- //#endregion
64
8
  //#region src/cancel-channel.ts
65
9
  /** In-process cancel pub/sub for single-process queues (memory, db polling). */
66
10
  function createInProcessCancelChannel() {
@@ -113,7 +57,7 @@ function createDatabaseJobQueue() {
113
57
  while (running) try {
114
58
  const job = await (0, _keystrokehq_database.claimNextJob)(workerId);
115
59
  if (!job) {
116
- await sleep(pollIntervalMs);
60
+ await sleep$1(pollIntervalMs);
117
61
  continue;
118
62
  }
119
63
  try {
@@ -127,7 +71,7 @@ function createDatabaseJobQueue() {
127
71
  }
128
72
  }
129
73
  } catch {
130
- await sleep(pollIntervalMs);
74
+ await sleep$1(pollIntervalMs);
131
75
  }
132
76
  };
133
77
  loop();
@@ -140,10 +84,135 @@ function createDatabaseJobQueue() {
140
84
  subscribeCancel: (handler) => cancelChannel.subscribeCancel(handler)
141
85
  };
142
86
  }
87
+ function sleep$1(ms) {
88
+ return new Promise((resolve) => setTimeout(resolve, ms));
89
+ }
90
+ //#endregion
91
+ //#region src/schedule-ticker.ts
92
+ function enqueueTriggerJob(jobQueue, row, scheduledAt) {
93
+ const input = {
94
+ kind: "trigger",
95
+ targetId: row.slug,
96
+ runId: crypto.randomUUID(),
97
+ trigger: row.kind,
98
+ payload: {},
99
+ projectId: row.projectId
100
+ };
101
+ if (scheduledAt) input.scheduledAt = scheduledAt;
102
+ return jobQueue.enqueue(input);
103
+ }
104
+ async function claimDue(scope, asOf, resolveNextRunAt, limit) {
105
+ if (scope === "organization") return (0, _keystrokehq_database.claimDueTriggersForOrg)(asOf, resolveNextRunAt, limit);
106
+ return (0, _keystrokehq_database.claimDueTriggers)(asOf, resolveNextRunAt, limit).then((rows) => rows.map((row) => ({
107
+ ...row,
108
+ projectId: (0, _keystrokehq_database.getProjectScopeId)()
109
+ })));
110
+ }
111
+ function createScheduleTicker(ctx) {
112
+ const pollIntervalMs = ctx.pollIntervalMs ?? 1e3;
113
+ const batchSize = ctx.batchSize ?? 10;
114
+ async function fireDueSchedules(asOf = /* @__PURE__ */ new Date()) {
115
+ const claimed = await claimDue(ctx.scope ?? "project", asOf, (schedule) => (0, _keystrokehq_trigger.nextTriggerRunAt)(schedule, asOf), batchSize);
116
+ for (const row of claimed) {
117
+ if (row.kind !== "cron" && row.kind !== "poll") continue;
118
+ await enqueueTriggerJob(ctx.jobQueue, {
119
+ slug: row.slug,
120
+ kind: row.kind,
121
+ projectId: row.projectId
122
+ }, asOf);
123
+ }
124
+ return claimed.length;
125
+ }
126
+ async function startScheduleTicker(options = {}) {
127
+ const intervalMs = options.pollIntervalMs ?? pollIntervalMs;
128
+ const limit = options.batchSize ?? batchSize;
129
+ const scope = options.scope ?? ctx.scope ?? "project";
130
+ let running = true;
131
+ const loop = async () => {
132
+ while (running) {
133
+ try {
134
+ const claimed = await claimDue(scope, /* @__PURE__ */ new Date(), (schedule) => (0, _keystrokehq_trigger.nextTriggerRunAt)(schedule, /* @__PURE__ */ new Date()), limit);
135
+ for (const row of claimed) {
136
+ if (row.kind !== "cron" && row.kind !== "poll") continue;
137
+ await enqueueTriggerJob(ctx.jobQueue, {
138
+ slug: row.slug,
139
+ kind: row.kind,
140
+ projectId: row.projectId
141
+ });
142
+ }
143
+ } catch {}
144
+ await sleep(intervalMs);
145
+ }
146
+ };
147
+ loop();
148
+ return async () => {
149
+ running = false;
150
+ };
151
+ }
152
+ return {
153
+ fireDueSchedules,
154
+ startScheduleTicker
155
+ };
156
+ }
143
157
  function sleep(ms) {
144
158
  return new Promise((resolve) => setTimeout(resolve, ms));
145
159
  }
146
160
  //#endregion
161
+ //#region src/resolve-schedule.ts
162
+ function resolveTriggerSchedule(triggerSlug, schedule, overrides) {
163
+ return (0, _keystrokehq_trigger.resolveCronSchedule)(triggerSlug, schedule, {
164
+ cronScheduleOverride: overrides?.global,
165
+ attachmentScheduleOverrides: overrides?.byTrigger
166
+ });
167
+ }
168
+ //#endregion
169
+ //#region src/sync-trigger-schedules.ts
170
+ async function syncTriggerSchedules(options) {
171
+ const now = /* @__PURE__ */ new Date();
172
+ const projectSlugs = options.schedules.map((schedule) => schedule.triggerSlug);
173
+ const ephemeralSlugs = await (0, _keystrokehq_database.selectActiveEphemeralScheduledTriggerSlugs)();
174
+ const slugs = [...projectSlugs, ...ephemeralSlugs];
175
+ if (slugs.length === 0) {
176
+ await (0, _keystrokehq_database.disableAllTriggerSchedules)(now);
177
+ return;
178
+ }
179
+ await (0, _keystrokehq_database.disableTriggerSchedulesNotInSlugs)(slugs, now);
180
+ for (const spec of options.schedules) {
181
+ const schedule = resolveTriggerSchedule(spec.triggerSlug, spec.schedule, options.scheduleOverrides);
182
+ const existing = await (0, _keystrokehq_database.selectTriggerBySlug)(spec.triggerSlug);
183
+ if (!existing) continue;
184
+ const nextRunAt = !(existing.schedule !== schedule) && existing.enabled === 1 ? existing.nextRunAt : (0, _keystrokehq_trigger.nextTriggerRunAt)(schedule, now);
185
+ const enabled = (await (0, _keystrokehq_database.listExecutableAttachmentsByTriggerIds)([existing.id])).length > 0;
186
+ await (0, _keystrokehq_database.upsertTriggerScheduleFields)({
187
+ triggerSlug: spec.triggerSlug,
188
+ schedule,
189
+ nextRunAt: nextRunAt ?? now,
190
+ enabled,
191
+ updatedAt: now
192
+ });
193
+ }
194
+ }
195
+ //#endregion
196
+ //#region src/database-trigger-scheduler.ts
197
+ /** Postgres poll loop — default trigger scheduler for pg-boss, polling, and memory paths. */
198
+ function createDatabaseTriggerScheduler(options) {
199
+ const ticker = createScheduleTicker({
200
+ jobQueue: options.jobQueue,
201
+ scope: options.scope,
202
+ pollIntervalMs: options.pollIntervalMs,
203
+ batchSize: options.batchSize
204
+ });
205
+ return {
206
+ sync: (syncOptions) => syncTriggerSchedules(syncOptions),
207
+ start: (startOptions) => ticker.startScheduleTicker(startOptions),
208
+ fireDue: (asOf) => ticker.fireDueSchedules(asOf),
209
+ async remove(triggerSlug) {
210
+ await (0, _keystrokehq_database.setTriggerScheduleEnabled)(triggerSlug, false, /* @__PURE__ */ new Date());
211
+ },
212
+ async upsert(_spec) {}
213
+ };
214
+ }
215
+ //#endregion
147
216
  //#region src/pg-boss-client.ts
148
217
  let boss;
149
218
  function resolveDatabaseUrl(url) {
@@ -206,6 +275,8 @@ function buildPgBossJobQueue(boss, options) {
206
275
  const queueName = options.queueName ?? "keystroke";
207
276
  const cancelChannel = (0, _keystrokehq_database.createPostgresCancelChannel)(options.connectionString, pgCancelChannelName(options.cancelScope ?? "platform", options.cancelScope === "organization" ? options.organizationId : options.projectId));
208
277
  return {
278
+ boss,
279
+ queueName,
209
280
  async enqueue(input) {
210
281
  const jobId = await boss.send(queueName, {
211
282
  ...input,
@@ -288,10 +359,132 @@ async function createSharedPgBossJobQueue(boss, options) {
288
359
  });
289
360
  }
290
361
  //#endregion
362
+ //#region src/pg-boss-trigger-scheduler.ts
363
+ /**
364
+ * pg-boss schedule key for one trigger. Mirrors {@link bullmqTriggerSchedulerId}
365
+ * so the firing backend is interchangeable: `trigger-<projectId>-<slug>`. pg-boss
366
+ * keys allow hyphens, so colons (legal in ids) are swapped for `-`.
367
+ */
368
+ function pgBossTriggerScheduleKey(spec) {
369
+ return `trigger-${(spec.projectId ?? (0, _keystrokehq_database.getProjectScopeId)()).replaceAll(":", "-")}-${spec.triggerSlug.replaceAll(":", "-")}`;
370
+ }
371
+ /** Key prefix scoping reconcile cleanup to the active project (org queues are shared). */
372
+ function pgBossTriggerScheduleKeyPrefix(projectId) {
373
+ return `trigger-${(projectId ?? (0, _keystrokehq_database.getProjectScopeId)()).replaceAll(":", "-")}-`;
374
+ }
375
+ function triggerJobData(spec) {
376
+ return {
377
+ kind: "trigger",
378
+ targetId: spec.triggerSlug,
379
+ runId: "",
380
+ trigger: spec.kind,
381
+ payload: {},
382
+ projectId: spec.projectId ?? (0, _keystrokehq_database.getProjectScopeId)()
383
+ };
384
+ }
385
+ function rowToSpec(row) {
386
+ if (row.kind !== "cron" && row.kind !== "poll") return;
387
+ if (!row.schedule) return;
388
+ return {
389
+ triggerSlug: row.slug,
390
+ kind: row.kind,
391
+ schedule: row.schedule,
392
+ projectId: row.projectId
393
+ };
394
+ }
395
+ /**
396
+ * Trigger scheduler backed by pg-boss native cron scheduling. Mirrors
397
+ * {@link createBullmqTriggerScheduler}: `boss.schedule` registers a recurring job
398
+ * onto the project/org queue (no per-second DB poll), and reconcile keeps the
399
+ * `pgboss.schedule` table in sync with the `triggers` table (source of truth).
400
+ *
401
+ * Granularity: pg-boss cron is minute-level (it checks schedules every ~30s and
402
+ * dedupes per minute), so sub-minute schedules effectively fire at most once per
403
+ * minute — unlike the DB ticker's 1s loop.
404
+ */
405
+ function createPgBossTriggerScheduler(_ctx, queue) {
406
+ async function upsertScheduler(spec, overrides) {
407
+ const schedule = resolveTriggerSchedule(spec.triggerSlug, spec.schedule, overrides);
408
+ const key = pgBossTriggerScheduleKey(spec);
409
+ await queue.boss.schedule(queue.queueName, schedule, triggerJobData({
410
+ ...spec,
411
+ schedule
412
+ }), { key });
413
+ }
414
+ async function reconcileFromDatabase(overrides) {
415
+ const projectPrefix = pgBossTriggerScheduleKeyPrefix();
416
+ const rows = await (0, _keystrokehq_database.listEnabledScheduledTriggers)();
417
+ const expectedKeys = /* @__PURE__ */ new Set();
418
+ const failures = [];
419
+ for (const row of rows) {
420
+ const spec = rowToSpec(row);
421
+ if (!spec) continue;
422
+ expectedKeys.add(pgBossTriggerScheduleKey(spec));
423
+ try {
424
+ await upsertScheduler(spec, overrides);
425
+ } catch (error) {
426
+ failures.push({
427
+ triggerSlug: spec.triggerSlug,
428
+ error
429
+ });
430
+ console.error(`[pg-boss-trigger-scheduler] failed to schedule ${spec.triggerSlug}`, error);
431
+ }
432
+ }
433
+ const schedules = await queue.boss.getSchedules(queue.queueName);
434
+ for (const schedule of schedules) {
435
+ const key = schedule.key;
436
+ if (!key || !key.startsWith(projectPrefix)) continue;
437
+ if (!expectedKeys.has(key)) try {
438
+ await queue.boss.unschedule(queue.queueName, key);
439
+ } catch (error) {
440
+ failures.push({
441
+ triggerSlug: key,
442
+ error
443
+ });
444
+ console.error(`[pg-boss-trigger-scheduler] failed to unschedule stale ${key}`, error);
445
+ }
446
+ }
447
+ if (failures.length > 0) throw new Error(`pg-boss trigger scheduler reconcile failed for ${failures.length} trigger(s)`);
448
+ }
449
+ return {
450
+ async sync(syncOptions) {
451
+ await syncTriggerSchedules(syncOptions);
452
+ await reconcileFromDatabase(syncOptions.scheduleOverrides);
453
+ },
454
+ async start(_options) {
455
+ return async () => void 0;
456
+ },
457
+ fireDue: async () => 0,
458
+ upsert: upsertScheduler,
459
+ async remove(triggerSlug, projectId) {
460
+ await queue.boss.unschedule(queue.queueName, pgBossTriggerScheduleKey({
461
+ triggerSlug,
462
+ projectId
463
+ }));
464
+ }
465
+ };
466
+ }
467
+ //#endregion
291
468
  //#region src/plugin.ts
292
469
  function resolveUrl(ctx) {
293
470
  return ctx.url ?? (0, _keystrokehq_database.resolveProjectDatabaseUrlFromEnv)(process.env) ?? _keystrokehq_database.DEFAULT_DATABASE_URL;
294
471
  }
472
+ /** DB poll-loop trigger scheduler — used by the SQLite/self-host polling backend. */
473
+ function createPollingTriggerScheduler(ctx, queue) {
474
+ const scope = ctx.scope === "organization" ? "organization" : "project";
475
+ return Promise.resolve(createDatabaseTriggerScheduler({
476
+ jobQueue: queue,
477
+ scope
478
+ }));
479
+ }
480
+ function isPgBossJobQueue(queue) {
481
+ return "boss" in queue && "queueName" in queue;
482
+ }
483
+ /** Native pg-boss cron scheduler; falls back to the DB ticker if the queue isn't pg-boss. */
484
+ function createPgBossTriggerSchedulerForPlugin(ctx, queue) {
485
+ if (!isPgBossJobQueue(queue)) return createPollingTriggerScheduler(ctx, queue);
486
+ return Promise.resolve(createPgBossTriggerScheduler(ctx, queue));
487
+ }
295
488
  /** Postgres pg-boss backend. Platform scope shares one queue; org scope gets one queue per org. */
296
489
  function pgBossSchedulerPlugin() {
297
490
  return require_contract.defineSchedulerPlugin({
@@ -318,7 +511,8 @@ function pgBossSchedulerPlugin() {
318
511
  queueName: pgBossProjectQueueName(projectId),
319
512
  projectId
320
513
  });
321
- }
514
+ },
515
+ createTriggerScheduler: createPgBossTriggerSchedulerForPlugin
322
516
  });
323
517
  }
324
518
  /** DB-table queue (Drizzle `jobs`), for SQLite / self-host. */
@@ -327,7 +521,8 @@ function pollingSchedulerPlugin() {
327
521
  name: "polling",
328
522
  async createJobQueue() {
329
523
  return createDatabaseJobQueue();
330
- }
524
+ },
525
+ createTriggerScheduler: createPollingTriggerScheduler
331
526
  });
332
527
  }
333
528
  /** Auto-selects pg-boss (postgres) or polling (sqlite) by dialect. */
@@ -337,45 +532,14 @@ function defaultSchedulerPlugin() {
337
532
  async createJobQueue(ctx) {
338
533
  if ((0, _keystrokehq_database.inferDialect)(resolveUrl(ctx), ctx.dialect) === "postgres") return pgBossSchedulerPlugin().createJobQueue(ctx);
339
534
  return pollingSchedulerPlugin().createJobQueue(ctx);
535
+ },
536
+ async createTriggerScheduler(ctx, queue) {
537
+ if ((0, _keystrokehq_database.inferDialect)(resolveUrl(ctx), ctx.dialect) === "postgres") return pgBossSchedulerPlugin().createTriggerScheduler(ctx, queue);
538
+ return pollingSchedulerPlugin().createTriggerScheduler(ctx, queue);
340
539
  }
341
540
  });
342
541
  }
343
542
  //#endregion
344
- //#region src/resolve-schedule.ts
345
- function resolveTriggerSchedule(attachmentKey, schedule, overrides) {
346
- return (0, _keystrokehq_trigger.resolveCronSchedule)(attachmentKey, schedule, {
347
- cronScheduleOverride: overrides?.global,
348
- attachmentScheduleOverrides: overrides?.byAttachment
349
- });
350
- }
351
- //#endregion
352
- //#region src/sync-trigger-schedules.ts
353
- async function syncTriggerSchedules(options) {
354
- const now = /* @__PURE__ */ new Date();
355
- const projectSlugs = options.schedules.map((schedule) => schedule.attachmentKey);
356
- const ephemeralSlugs = await (0, _keystrokehq_database.selectActiveEphemeralScheduledAttachmentSlugs)();
357
- const slugs = [...projectSlugs, ...ephemeralSlugs];
358
- if (slugs.length === 0) {
359
- await (0, _keystrokehq_database.disableAllTriggerSchedules)(now);
360
- return;
361
- }
362
- await (0, _keystrokehq_database.disableTriggerSchedulesNotInSlugs)(slugs, now);
363
- for (const spec of options.schedules) {
364
- const schedule = resolveTriggerSchedule(spec.attachmentKey, spec.schedule, options.scheduleOverrides);
365
- const existing = await (0, _keystrokehq_database.selectTriggerScheduleBySlug)(spec.attachmentKey);
366
- const scheduleChanged = existing?.schedule !== schedule;
367
- const nextRunAt = existing && !scheduleChanged && existing.enabled === 1 ? existing.nextRunAt : (0, _keystrokehq_trigger.nextTriggerRunAt)(schedule, now);
368
- await (0, _keystrokehq_database.upsertTriggerSchedule)({
369
- attachmentSlug: spec.attachmentKey,
370
- kind: spec.kind,
371
- schedule,
372
- nextRunAt,
373
- enabled: true,
374
- updatedAt: now
375
- });
376
- }
377
- }
378
- //#endregion
379
543
  //#region src/create-scheduler.ts
380
544
  async function createUnderlyingJobQueue(options = {}) {
381
545
  if (options.adapter) return options.adapter;
@@ -387,29 +551,50 @@ async function createUnderlyingJobQueue(options = {}) {
387
551
  organizationId: options.organizationId
388
552
  });
389
553
  }
390
- function wrapScheduler(jobQueue, scope) {
391
- const ticker = createScheduleTicker({
554
+ function pluginContext(options = {}) {
555
+ return {
556
+ scope: options.scope ?? "project",
557
+ url: options.url,
558
+ dialect: options.dialect,
559
+ projectId: options.projectId,
560
+ organizationId: options.organizationId
561
+ };
562
+ }
563
+ async function createTriggerScheduler(options, jobQueue) {
564
+ const scope = options.scope === "organization" ? "organization" : "project";
565
+ const plugin = options.plugin ?? defaultSchedulerPlugin();
566
+ const ctx = pluginContext(options);
567
+ if (plugin.createTriggerScheduler) return plugin.createTriggerScheduler(ctx, jobQueue);
568
+ return createDatabaseTriggerScheduler({
392
569
  jobQueue,
393
570
  scope
394
571
  });
572
+ }
573
+ function wrapScheduler(jobQueue, triggerScheduler) {
395
574
  return {
396
575
  enqueue: (input) => jobQueue.enqueue(input),
397
- startWorker: (handler, options) => jobQueue.startWorker(handler, options),
576
+ startWorker: (handler, workerOptions) => jobQueue.startWorker(handler, workerOptions),
398
577
  publishCancel: (runId) => jobQueue.publishCancel(runId),
399
578
  subscribeCancel: (handler) => jobQueue.subscribeCancel(handler),
400
- syncTriggerSchedules: (options) => syncTriggerSchedules(options),
401
- startScheduleTicker: (options) => ticker.startScheduleTicker(options),
402
- fireDueSchedules: (asOf) => ticker.fireDueSchedules(asOf)
579
+ syncTriggerSchedules: (options) => triggerScheduler.sync(options),
580
+ startScheduleTicker: (options) => triggerScheduler.start(options),
581
+ fireDueSchedules: (asOf) => triggerScheduler.fireDue?.(asOf) ?? Promise.resolve(0),
582
+ ...triggerScheduler.upsert ? { upsertTriggerSchedule: (spec, overrides) => triggerScheduler.upsert(spec, overrides) } : {},
583
+ ...triggerScheduler.remove ? { removeTriggerSchedule: (triggerSlug, projectId) => triggerScheduler.remove(triggerSlug, projectId) } : {}
403
584
  };
404
585
  }
405
586
  async function createScheduler(options = {}) {
406
- return wrapScheduler(await createUnderlyingJobQueue(options), options.scope === "organization" ? "organization" : "project");
587
+ const jobQueue = await createUnderlyingJobQueue(options);
588
+ return wrapScheduler(jobQueue, await createTriggerScheduler(options, jobQueue));
407
589
  }
408
590
  async function createJobQueue(options = {}) {
409
591
  return createUnderlyingJobQueue(options);
410
592
  }
411
- function wrapJobQueueAsScheduler(jobQueue, scope) {
412
- return wrapScheduler(jobQueue, scope);
593
+ async function wrapJobQueueAsScheduler(jobQueue, scope) {
594
+ return wrapScheduler(jobQueue, createDatabaseTriggerScheduler({
595
+ jobQueue,
596
+ scope
597
+ }));
413
598
  }
414
599
  //#endregion
415
600
  //#region src/memory.ts
@@ -468,7 +653,7 @@ function createMemoryJobQueue(options = {}) {
468
653
  //#region src/shared-pgboss-queue.ts
469
654
  let sharedJobQueue$1;
470
655
  async function createSharedPgBossScheduler() {
471
- return wrapJobQueueAsScheduler(await getSharedPgBossJobQueue());
656
+ return await wrapJobQueueAsScheduler(await getSharedPgBossJobQueue());
472
657
  }
473
658
  async function getSharedPgBossJobQueue() {
474
659
  if (sharedJobQueue$1) return sharedJobQueue$1;
@@ -492,7 +677,7 @@ async function createSharedScheduler() {
492
677
  const plugin = configuredPlugin ?? defaultSchedulerPlugin();
493
678
  if (plugin.name === "default") return createSharedPgBossScheduler();
494
679
  if (!sharedJobQueue) sharedJobQueue = await plugin.createJobQueue({ scope: "platform" });
495
- return wrapJobQueueAsScheduler(sharedJobQueue);
680
+ return await wrapJobQueueAsScheduler(sharedJobQueue);
496
681
  }
497
682
  function resetSharedSchedulerForTests() {
498
683
  configuredPlugin = void 0;
@@ -504,8 +689,10 @@ exports.DEFAULT_QUEUE_NAME = DEFAULT_QUEUE_NAME;
504
689
  exports.DEFAULT_RETRY_DELAY_MS = require_contract.DEFAULT_RETRY_DELAY_MS;
505
690
  exports.buildPgBossJobQueue = buildPgBossJobQueue;
506
691
  exports.configureSharedScheduler = configureSharedScheduler;
692
+ exports.createDatabaseTriggerScheduler = createDatabaseTriggerScheduler;
507
693
  exports.createJobQueue = createJobQueue;
508
694
  exports.createMemoryJobQueue = createMemoryJobQueue;
695
+ exports.createPgBossTriggerScheduler = createPgBossTriggerScheduler;
509
696
  exports.createScheduler = createScheduler;
510
697
  exports.createSharedPgBossJobQueue = createSharedPgBossJobQueue;
511
698
  exports.createSharedPgBossScheduler = createSharedPgBossScheduler;
@@ -516,12 +703,16 @@ exports.getPgBoss = getPgBoss;
516
703
  exports.getSharedPgBossJobQueue = getSharedPgBossJobQueue;
517
704
  exports.pgBossProjectQueueName = pgBossProjectQueueName;
518
705
  exports.pgBossSchedulerPlugin = pgBossSchedulerPlugin;
706
+ exports.pgBossTriggerScheduleKey = pgBossTriggerScheduleKey;
707
+ exports.pgBossTriggerScheduleKeyPrefix = pgBossTriggerScheduleKeyPrefix;
519
708
  exports.pollingSchedulerPlugin = pollingSchedulerPlugin;
520
709
  exports.resetSharedPgBossJobQueueForTests = resetSharedPgBossJobQueueForTests;
521
710
  exports.resetSharedSchedulerForTests = resetSharedSchedulerForTests;
711
+ exports.resolveTriggerSchedule = resolveTriggerSchedule;
522
712
  exports.retryDelayMs = require_contract.retryDelayMs;
523
713
  exports.startPgBoss = startPgBoss;
524
714
  exports.stopPgBoss = stopPgBoss;
715
+ exports.syncTriggerSchedules = syncTriggerSchedules;
525
716
  exports.wrapJobQueueAsScheduler = wrapJobQueueAsScheduler;
526
717
 
527
718
  //# sourceMappingURL=index.cjs.map