pg-workflows 0.13.2 → 0.14.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
@@ -97,7 +97,7 @@ var isInvokeChildWorkflowTimelineEntry = (entry) => !!entry && typeof entry ===
97
97
 
98
98
  // src/db/migration.ts
99
99
  var MIGRATION_LOCK_ID = 738291645;
100
- var CURRENT_SCHEMA_VERSION = 5;
100
+ var CURRENT_SCHEMA_VERSION = 6;
101
101
  async function runMigrations(db) {
102
102
  if (await isSchemaUpToDate(db)) {
103
103
  return;
@@ -173,6 +173,9 @@ async function runMigrations(db) {
173
173
  if (currentVersion < 5) {
174
174
  commands.push("ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS scheduled_at timestamp with time zone");
175
175
  }
176
+ if (currentVersion < 6) {
177
+ commands.push("ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS priority integer DEFAULT 0 NOT NULL");
178
+ }
176
179
  if (currentVersion === 0) {
177
180
  commands.push(`INSERT INTO workflow_schema_version (version) VALUES (${CURRENT_SCHEMA_VERSION})`);
178
181
  } else {
@@ -234,6 +237,7 @@ function mapRowToWorkflowRun(row) {
234
237
  timeoutAt: row.timeout_at ? new Date(row.timeout_at) : null,
235
238
  retryCount: row.retry_count,
236
239
  maxRetries: row.max_retries,
240
+ priority: row.priority,
237
241
  jobId: row.job_id,
238
242
  idempotencyKey: row.idempotency_key,
239
243
  parentRunId: row.parent_run_id,
@@ -249,6 +253,7 @@ async function insertWorkflowRun({
249
253
  status,
250
254
  input,
251
255
  maxRetries,
256
+ priority,
252
257
  timeoutAt,
253
258
  idempotencyKey,
254
259
  parentRunId,
@@ -266,6 +271,7 @@ async function insertWorkflowRun({
266
271
  status,
267
272
  input,
268
273
  max_retries,
274
+ priority,
269
275
  timeout_at,
270
276
  created_at,
271
277
  updated_at,
@@ -277,7 +283,7 @@ async function insertWorkflowRun({
277
283
  parent_resource_id,
278
284
  scheduled_at
279
285
  )
280
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
286
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)
281
287
  ON CONFLICT (idempotency_key) WHERE idempotency_key IS NOT NULL DO NOTHING
282
288
  RETURNING *`, [
283
289
  runId,
@@ -287,6 +293,7 @@ async function insertWorkflowRun({
287
293
  status,
288
294
  JSON.stringify(input),
289
295
  maxRetries,
296
+ priority,
290
297
  timeoutAt,
291
298
  now,
292
299
  now,
@@ -566,6 +573,30 @@ class WorkflowRunNotFoundError extends WorkflowEngineError {
566
573
  }
567
574
  }
568
575
 
576
+ // src/priority.ts
577
+ var PRIORITY_LEVELS = { high: 100, normal: 0, low: -100 };
578
+ function priorityToInt(value) {
579
+ if (typeof value === "number") {
580
+ if (!Number.isInteger(value)) {
581
+ throw new WorkflowEngineError(`Invalid priority ${value}: numeric priority must be an integer.`);
582
+ }
583
+ return value;
584
+ }
585
+ const mapped = PRIORITY_LEVELS[value];
586
+ if (mapped === undefined) {
587
+ throw new WorkflowEngineError(`Invalid priority "${value}": expected one of ${Object.keys(PRIORITY_LEVELS).map((k) => `"${k}"`).join(", ")} or an integer.`);
588
+ }
589
+ return mapped;
590
+ }
591
+ function resolvePriority(...candidates) {
592
+ for (const candidate of candidates) {
593
+ if (candidate !== undefined) {
594
+ return priorityToInt(candidate);
595
+ }
596
+ }
597
+ return PRIORITY_LEVELS.normal;
598
+ }
599
+
569
600
  // src/types.ts
570
601
  var WorkflowStatus;
571
602
  ((WorkflowStatus2) => {
@@ -681,6 +712,7 @@ class WorkflowClient {
681
712
  status: "running" /* RUNNING */,
682
713
  input,
683
714
  maxRetries: options?.retries ?? 0,
715
+ priority: resolvePriority(options?.priority),
684
716
  timeoutAt,
685
717
  idempotencyKey
686
718
  }, _db);
@@ -694,6 +726,7 @@ class WorkflowClient {
694
726
  await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
695
727
  startAfter: new Date,
696
728
  expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,
729
+ priority: insertedRun.priority,
697
730
  db: _db
698
731
  });
699
732
  }
@@ -722,7 +755,8 @@ class WorkflowClient {
722
755
  }
723
756
  };
724
757
  await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
725
- expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds
758
+ expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,
759
+ priority: run.priority
726
760
  });
727
761
  this.logger.log(`${LOG_PREFIX} Event ${eventName} sent for workflow run ${runId}`);
728
762
  return run;
@@ -901,6 +935,7 @@ function createWorkflowRef(id, options) {
901
935
  inputSchema: options?.inputSchema,
902
936
  timeout: defineOptions?.timeout,
903
937
  retries: defineOptions?.retries,
938
+ priority: defineOptions?.priority,
904
939
  schedule: defineOptions?.schedule,
905
940
  timezone: defineOptions?.timezone
906
941
  });
@@ -912,12 +947,13 @@ function createWorkflowRef(id, options) {
912
947
  return ref;
913
948
  }
914
949
  function createWorkflowFactory(plugins = []) {
915
- const factory = (id, handler, { inputSchema, timeout, retries, schedule, timezone } = {}) => ({
950
+ const factory = (id, handler, { inputSchema, timeout, retries, priority, schedule, timezone } = {}) => ({
916
951
  id,
917
952
  handler,
918
953
  inputSchema,
919
954
  timeout,
920
955
  retries,
956
+ priority,
921
957
  schedule,
922
958
  timezone,
923
959
  plugins: plugins.length > 0 ? plugins : undefined
@@ -1300,6 +1336,7 @@ class WorkflowEngine {
1300
1336
  parentRunId,
1301
1337
  parentStepId,
1302
1338
  parentResourceId,
1339
+ parentPriority,
1303
1340
  scheduledAt,
1304
1341
  enqueue = true,
1305
1342
  db
@@ -1330,6 +1367,7 @@ class WorkflowEngine {
1330
1367
  status: "running" /* RUNNING */,
1331
1368
  input,
1332
1369
  maxRetries: options?.retries ?? workflow2.retries ?? 0,
1370
+ priority: resolvePriority(options?.priority, workflow2.priority, parentPriority),
1333
1371
  timeoutAt,
1334
1372
  idempotencyKey,
1335
1373
  parentRunId,
@@ -1357,6 +1395,7 @@ class WorkflowEngine {
1357
1395
  await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
1358
1396
  startAfter: new Date,
1359
1397
  expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds2,
1398
+ priority: run.priority,
1360
1399
  ...retrySendOptions(run.maxRetries),
1361
1400
  ...db ? { db } : {}
1362
1401
  });
@@ -1506,6 +1545,7 @@ class WorkflowEngine {
1506
1545
  };
1507
1546
  await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
1508
1547
  expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds2,
1548
+ priority: run.priority,
1509
1549
  ...retrySendOptions(run.maxRetries)
1510
1550
  });
1511
1551
  this.logger.log(`event ${eventName} sent for workflow run with id ${runId}`);
@@ -1915,6 +1955,7 @@ class WorkflowEngine {
1915
1955
  parentRunId: run.id,
1916
1956
  parentStepId: stepId,
1917
1957
  parentResourceId: run.resourceId ?? undefined,
1958
+ parentPriority: run.priority,
1918
1959
  enqueue: true,
1919
1960
  db
1920
1961
  });
@@ -2113,6 +2154,7 @@ ${error.stack}` : String(error)
2113
2154
  await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
2114
2155
  startAfter: timeoutDate.getTime() <= Date.now() ? new Date : timeoutDate,
2115
2156
  expireInSeconds: defaultExpireInSeconds2,
2157
+ priority: run.priority,
2116
2158
  ...retrySendOptions(run.maxRetries)
2117
2159
  });
2118
2160
  } catch (error) {
@@ -2231,6 +2273,7 @@ ${error.stack}` : String(error)
2231
2273
  }, {
2232
2274
  startAfter: new Date(Date.now() + intervalMs),
2233
2275
  expireInSeconds: defaultExpireInSeconds2,
2276
+ priority: run.priority,
2234
2277
  ...retrySendOptions(run.maxRetries)
2235
2278
  });
2236
2279
  } catch (error) {
@@ -2458,5 +2501,5 @@ function otelPlugin(options = {}) {
2458
2501
  };
2459
2502
  }
2460
2503
 
2461
- //# debugId=EB0357F84B3B4EF764756E2164756E21
2504
+ //# debugId=5FA47CDFF028114064756E2164756E21
2462
2505
  //# sourceMappingURL=index.js.map
package/dist/index.d.cts CHANGED
@@ -18,6 +18,8 @@ type WorkflowRun = {
18
18
  timeoutAt: Date | null;
19
19
  retryCount: number;
20
20
  maxRetries: number;
21
+ /** Resolved scheduling priority (pg-boss integer; higher runs first). */
22
+ priority: number;
21
23
  jobId: string | null;
22
24
  idempotencyKey: string | null;
23
25
  parentRunId: string | null;
@@ -35,6 +37,18 @@ type DurationObject = {
35
37
  seconds?: number;
36
38
  };
37
39
  type Duration = string | DurationObject;
40
+ /**
41
+ * Named priority levels mapped to pg-boss integer priorities. Higher numbers
42
+ * are fetched first (pg-boss orders by `priority DESC`), and `normal = 0`
43
+ * matches pg-boss's own default. The ±100 spacing leaves room for numeric
44
+ * tuning between tiers via the escape hatch.
45
+ */
46
+ declare const PRIORITY_LEVELS: {
47
+ readonly high: 100;
48
+ readonly normal: 0;
49
+ readonly low: -100;
50
+ };
51
+ type WorkflowPriority = keyof typeof PRIORITY_LEVELS | number;
38
52
  type Schedule = string | Exclude<Duration, string>;
39
53
  declare enum WorkflowStatus {
40
54
  PENDING = "pending",
@@ -61,11 +75,13 @@ type StartWorkflowOptions = {
61
75
  retries?: number;
62
76
  expireInSeconds?: number;
63
77
  idempotencyKey?: string;
78
+ priority?: WorkflowPriority;
64
79
  };
65
80
  type WorkflowOptions<I extends InputParameters> = {
66
81
  timeout?: number;
67
82
  retries?: number;
68
83
  inputSchema?: I;
84
+ priority?: WorkflowPriority;
69
85
  /**
70
86
  * Recurring schedule. Accepts a cron expression (`'0 9 * * 1-5'`),
71
87
  * a duration string (`'5m'`, `'1 hour'`), or a `DurationObject`.
@@ -173,6 +189,7 @@ type WorkflowDefinition<TInput extends InputParameters = InputParameters> = {
173
189
  inputSchema?: TInput;
174
190
  timeout?: number;
175
191
  retries?: number;
192
+ priority?: WorkflowPriority;
176
193
  schedule?: Schedule;
177
194
  timezone?: string;
178
195
  plugins?: WorkflowPlugin[];
@@ -504,4 +521,4 @@ type OtelPluginOptions = {
504
521
  attributes?: (context: WorkflowContext) => Record<string, AttributeValue>;
505
522
  };
506
523
  declare function otelPlugin(options?: OtelPluginOptions): WorkflowPlugin<StepBaseContext, object>;
507
- export { workflow, otelPlugin, createWorkflowRef, WorkflowStatus, WorkflowRunProgress, WorkflowRunNotFoundError, WorkflowRun, WorkflowRef, WorkflowPlugin, WorkflowOptions, WorkflowLogger, WorkflowEngineOptions, WorkflowEngineError, WorkflowEngine, WorkflowDefinition, WorkflowContext, WorkflowClientOptions, WorkflowClient, StepBaseContext, StartWorkflowOptions, ScheduleContext, Schedule, OtelPluginOptions, InputParameters, InferInputParameters, Duration };
524
+ export { workflow, otelPlugin, createWorkflowRef, WorkflowStatus, WorkflowRunProgress, WorkflowRunNotFoundError, WorkflowRun, WorkflowRef, WorkflowPriority, WorkflowPlugin, WorkflowOptions, WorkflowLogger, WorkflowEngineOptions, WorkflowEngineError, WorkflowEngine, WorkflowDefinition, WorkflowContext, WorkflowClientOptions, WorkflowClient, StepBaseContext, StartWorkflowOptions, ScheduleContext, Schedule, OtelPluginOptions, InputParameters, InferInputParameters, Duration };
package/dist/index.d.ts CHANGED
@@ -18,6 +18,8 @@ type WorkflowRun = {
18
18
  timeoutAt: Date | null;
19
19
  retryCount: number;
20
20
  maxRetries: number;
21
+ /** Resolved scheduling priority (pg-boss integer; higher runs first). */
22
+ priority: number;
21
23
  jobId: string | null;
22
24
  idempotencyKey: string | null;
23
25
  parentRunId: string | null;
@@ -35,6 +37,18 @@ type DurationObject = {
35
37
  seconds?: number;
36
38
  };
37
39
  type Duration = string | DurationObject;
40
+ /**
41
+ * Named priority levels mapped to pg-boss integer priorities. Higher numbers
42
+ * are fetched first (pg-boss orders by `priority DESC`), and `normal = 0`
43
+ * matches pg-boss's own default. The ±100 spacing leaves room for numeric
44
+ * tuning between tiers via the escape hatch.
45
+ */
46
+ declare const PRIORITY_LEVELS: {
47
+ readonly high: 100;
48
+ readonly normal: 0;
49
+ readonly low: -100;
50
+ };
51
+ type WorkflowPriority = keyof typeof PRIORITY_LEVELS | number;
38
52
  type Schedule = string | Exclude<Duration, string>;
39
53
  declare enum WorkflowStatus {
40
54
  PENDING = "pending",
@@ -61,11 +75,13 @@ type StartWorkflowOptions = {
61
75
  retries?: number;
62
76
  expireInSeconds?: number;
63
77
  idempotencyKey?: string;
78
+ priority?: WorkflowPriority;
64
79
  };
65
80
  type WorkflowOptions<I extends InputParameters> = {
66
81
  timeout?: number;
67
82
  retries?: number;
68
83
  inputSchema?: I;
84
+ priority?: WorkflowPriority;
69
85
  /**
70
86
  * Recurring schedule. Accepts a cron expression (`'0 9 * * 1-5'`),
71
87
  * a duration string (`'5m'`, `'1 hour'`), or a `DurationObject`.
@@ -173,6 +189,7 @@ type WorkflowDefinition<TInput extends InputParameters = InputParameters> = {
173
189
  inputSchema?: TInput;
174
190
  timeout?: number;
175
191
  retries?: number;
192
+ priority?: WorkflowPriority;
176
193
  schedule?: Schedule;
177
194
  timezone?: string;
178
195
  plugins?: WorkflowPlugin[];
@@ -504,4 +521,4 @@ type OtelPluginOptions = {
504
521
  attributes?: (context: WorkflowContext) => Record<string, AttributeValue>;
505
522
  };
506
523
  declare function otelPlugin(options?: OtelPluginOptions): WorkflowPlugin<StepBaseContext, object>;
507
- export { workflow, otelPlugin, createWorkflowRef, WorkflowStatus, WorkflowRunProgress, WorkflowRunNotFoundError, WorkflowRun, WorkflowRef, WorkflowPlugin, WorkflowOptions, WorkflowLogger, WorkflowEngineOptions, WorkflowEngineError, WorkflowEngine, WorkflowDefinition, WorkflowContext, WorkflowClientOptions, WorkflowClient, StepBaseContext, StartWorkflowOptions, ScheduleContext, Schedule, OtelPluginOptions, InputParameters, InferInputParameters, Duration };
524
+ export { workflow, otelPlugin, createWorkflowRef, WorkflowStatus, WorkflowRunProgress, WorkflowRunNotFoundError, WorkflowRun, WorkflowRef, WorkflowPriority, WorkflowPlugin, WorkflowOptions, WorkflowLogger, WorkflowEngineOptions, WorkflowEngineError, WorkflowEngine, WorkflowDefinition, WorkflowContext, WorkflowClientOptions, WorkflowClient, StepBaseContext, StartWorkflowOptions, ScheduleContext, Schedule, OtelPluginOptions, InputParameters, InferInputParameters, Duration };
package/dist/index.js CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  insertWorkflowRun,
16
16
  invokeChildWorkflowTimelineKey,
17
17
  isInvokeChildWorkflowTimelineEntry,
18
+ resolvePriority,
18
19
  runMigrations,
19
20
  scheduleQueueNameFor,
20
21
  updateWorkflowRun,
@@ -23,7 +24,7 @@ import {
23
24
  waitForTimelineKey,
24
25
  withPostgresTransaction,
25
26
  workflow
26
- } from "./shared/chunk-hjycwrsq.js";
27
+ } from "./shared/chunk-w3qcrrwx.js";
27
28
  // src/engine.ts
28
29
  import { merge } from "es-toolkit";
29
30
  import pg from "pg";
@@ -394,6 +395,7 @@ class WorkflowEngine {
394
395
  parentRunId,
395
396
  parentStepId,
396
397
  parentResourceId,
398
+ parentPriority,
397
399
  scheduledAt,
398
400
  enqueue = true,
399
401
  db
@@ -424,6 +426,7 @@ class WorkflowEngine {
424
426
  status: "running" /* RUNNING */,
425
427
  input,
426
428
  maxRetries: options?.retries ?? workflow2.retries ?? 0,
429
+ priority: resolvePriority(options?.priority, workflow2.priority, parentPriority),
427
430
  timeoutAt,
428
431
  idempotencyKey,
429
432
  parentRunId,
@@ -451,6 +454,7 @@ class WorkflowEngine {
451
454
  await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
452
455
  startAfter: new Date,
453
456
  expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,
457
+ priority: run.priority,
454
458
  ...retrySendOptions(run.maxRetries),
455
459
  ...db ? { db } : {}
456
460
  });
@@ -600,6 +604,7 @@ class WorkflowEngine {
600
604
  };
601
605
  await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
602
606
  expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,
607
+ priority: run.priority,
603
608
  ...retrySendOptions(run.maxRetries)
604
609
  });
605
610
  this.logger.log(`event ${eventName} sent for workflow run with id ${runId}`);
@@ -1009,6 +1014,7 @@ class WorkflowEngine {
1009
1014
  parentRunId: run.id,
1010
1015
  parentStepId: stepId,
1011
1016
  parentResourceId: run.resourceId ?? undefined,
1017
+ parentPriority: run.priority,
1012
1018
  enqueue: true,
1013
1019
  db
1014
1020
  });
@@ -1207,6 +1213,7 @@ ${error.stack}` : String(error)
1207
1213
  await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
1208
1214
  startAfter: timeoutDate.getTime() <= Date.now() ? new Date : timeoutDate,
1209
1215
  expireInSeconds: defaultExpireInSeconds,
1216
+ priority: run.priority,
1210
1217
  ...retrySendOptions(run.maxRetries)
1211
1218
  });
1212
1219
  } catch (error) {
@@ -1325,6 +1332,7 @@ ${error.stack}` : String(error)
1325
1332
  }, {
1326
1333
  startAfter: new Date(Date.now() + intervalMs),
1327
1334
  expireInSeconds: defaultExpireInSeconds,
1335
+ priority: run.priority,
1328
1336
  ...retrySendOptions(run.maxRetries)
1329
1337
  });
1330
1338
  } catch (error) {
@@ -1566,5 +1574,5 @@ export {
1566
1574
  WorkflowClient
1567
1575
  };
1568
1576
 
1569
- //# debugId=EE11F9509955D59264756E2164756E21
1577
+ //# debugId=A6C8F39FA22E601264756E2164756E21
1570
1578
  //# sourceMappingURL=index.js.map