pg-workflows 0.13.1 → 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.
@@ -94,7 +94,7 @@ var isInvokeChildWorkflowTimelineEntry = (entry) => !!entry && typeof entry ===
94
94
 
95
95
  // src/db/migration.ts
96
96
  var MIGRATION_LOCK_ID = 738291645;
97
- var CURRENT_SCHEMA_VERSION = 5;
97
+ var CURRENT_SCHEMA_VERSION = 6;
98
98
  async function runMigrations(db) {
99
99
  if (await isSchemaUpToDate(db)) {
100
100
  return;
@@ -102,6 +102,16 @@ async function runMigrations(db) {
102
102
  const currentVersion = await getCurrentVersion(db);
103
103
  const commands = [];
104
104
  if (currentVersion < 1) {
105
+ const existing = await db.executeSql(`SELECT
106
+ to_regclass('workflow_runs') IS NOT NULL AS has_runs_table,
107
+ to_regclass('workflow_schema_version') IS NOT NULL AS has_version_table`, []);
108
+ const row = existing.rows[0];
109
+ if (row?.has_runs_table && !row.has_version_table) {
110
+ throw new Error(`pg-workflows: a "workflow_runs" table already exists in this schema but was not ` + `created by pg-workflows. Point the workflow engine at a dedicated schema/database.`);
111
+ }
112
+ if (!row?.has_runs_table && row?.has_version_table) {
113
+ throw new Error(`pg-workflows: a "workflow_schema_version" table already exists in this schema but was not ` + `created by pg-workflows. Point the workflow engine at a dedicated schema/database.`);
114
+ }
105
115
  commands.push(`
106
116
  CREATE TABLE IF NOT EXISTS workflow_runs (
107
117
  id varchar(32) PRIMARY KEY NOT NULL,
@@ -160,6 +170,9 @@ async function runMigrations(db) {
160
170
  if (currentVersion < 5) {
161
171
  commands.push("ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS scheduled_at timestamp with time zone");
162
172
  }
173
+ if (currentVersion < 6) {
174
+ commands.push("ALTER TABLE workflow_runs ADD COLUMN IF NOT EXISTS priority integer DEFAULT 0 NOT NULL");
175
+ }
163
176
  if (currentVersion === 0) {
164
177
  commands.push(`INSERT INTO workflow_schema_version (version) VALUES (${CURRENT_SCHEMA_VERSION})`);
165
178
  } else {
@@ -221,6 +234,7 @@ function mapRowToWorkflowRun(row) {
221
234
  timeoutAt: row.timeout_at ? new Date(row.timeout_at) : null,
222
235
  retryCount: row.retry_count,
223
236
  maxRetries: row.max_retries,
237
+ priority: row.priority,
224
238
  jobId: row.job_id,
225
239
  idempotencyKey: row.idempotency_key,
226
240
  parentRunId: row.parent_run_id,
@@ -236,6 +250,7 @@ async function insertWorkflowRun({
236
250
  status,
237
251
  input,
238
252
  maxRetries,
253
+ priority,
239
254
  timeoutAt,
240
255
  idempotencyKey,
241
256
  parentRunId,
@@ -253,6 +268,7 @@ async function insertWorkflowRun({
253
268
  status,
254
269
  input,
255
270
  max_retries,
271
+ priority,
256
272
  timeout_at,
257
273
  created_at,
258
274
  updated_at,
@@ -264,7 +280,7 @@ async function insertWorkflowRun({
264
280
  parent_resource_id,
265
281
  scheduled_at
266
282
  )
267
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
283
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)
268
284
  ON CONFLICT (idempotency_key) WHERE idempotency_key IS NOT NULL DO NOTHING
269
285
  RETURNING *`, [
270
286
  runId,
@@ -274,6 +290,7 @@ async function insertWorkflowRun({
274
290
  status,
275
291
  JSON.stringify(input),
276
292
  maxRetries,
293
+ priority,
277
294
  timeoutAt,
278
295
  now,
279
296
  now,
@@ -553,6 +570,30 @@ class WorkflowRunNotFoundError extends WorkflowEngineError {
553
570
  }
554
571
  }
555
572
 
573
+ // src/priority.ts
574
+ var PRIORITY_LEVELS = { high: 100, normal: 0, low: -100 };
575
+ function priorityToInt(value) {
576
+ if (typeof value === "number") {
577
+ if (!Number.isInteger(value)) {
578
+ throw new WorkflowEngineError(`Invalid priority ${value}: numeric priority must be an integer.`);
579
+ }
580
+ return value;
581
+ }
582
+ const mapped = PRIORITY_LEVELS[value];
583
+ if (mapped === undefined) {
584
+ throw new WorkflowEngineError(`Invalid priority "${value}": expected one of ${Object.keys(PRIORITY_LEVELS).map((k) => `"${k}"`).join(", ")} or an integer.`);
585
+ }
586
+ return mapped;
587
+ }
588
+ function resolvePriority(...candidates) {
589
+ for (const candidate of candidates) {
590
+ if (candidate !== undefined) {
591
+ return priorityToInt(candidate);
592
+ }
593
+ }
594
+ return PRIORITY_LEVELS.normal;
595
+ }
596
+
556
597
  // src/types.ts
557
598
  var WorkflowStatus;
558
599
  ((WorkflowStatus2) => {
@@ -563,6 +604,17 @@ var WorkflowStatus;
563
604
  WorkflowStatus2["FAILED"] = "failed";
564
605
  WorkflowStatus2["CANCELLED"] = "cancelled";
565
606
  })(WorkflowStatus ||= {});
607
+ var _STEP_BASE_METHOD_TO_TYPE = {
608
+ run: "run" /* RUN */,
609
+ waitFor: "waitFor" /* WAIT_FOR */,
610
+ waitUntil: "waitUntil" /* WAIT_UNTIL */,
611
+ delay: "delay" /* DELAY */,
612
+ sleep: "delay" /* DELAY */,
613
+ pause: "pause" /* PAUSE */,
614
+ poll: "poll" /* POLL */,
615
+ invokeChildWorkflow: "invokeChildWorkflow" /* INVOKE_CHILD_WORKFLOW */
616
+ };
617
+ var STEP_BASE_METHOD_TYPES = new Map(Object.entries(_STEP_BASE_METHOD_TO_TYPE));
566
618
 
567
619
  // src/client.ts
568
620
  var LOG_PREFIX = "[WorkflowClient]";
@@ -657,6 +709,7 @@ class WorkflowClient {
657
709
  status: "running" /* RUNNING */,
658
710
  input,
659
711
  maxRetries: options?.retries ?? 0,
712
+ priority: resolvePriority(options?.priority),
660
713
  timeoutAt,
661
714
  idempotencyKey
662
715
  }, _db);
@@ -670,6 +723,7 @@ class WorkflowClient {
670
723
  await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
671
724
  startAfter: new Date,
672
725
  expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,
726
+ priority: insertedRun.priority,
673
727
  db: _db
674
728
  });
675
729
  }
@@ -698,7 +752,8 @@ class WorkflowClient {
698
752
  }
699
753
  };
700
754
  await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {
701
- expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds
755
+ expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,
756
+ priority: run.priority
702
757
  });
703
758
  this.logger.log(`${LOG_PREFIX} Event ${eventName} sent for workflow run ${runId}`);
704
759
  return run;
@@ -877,6 +932,7 @@ function createWorkflowRef(id, options) {
877
932
  inputSchema: options?.inputSchema,
878
933
  timeout: defineOptions?.timeout,
879
934
  retries: defineOptions?.retries,
935
+ priority: defineOptions?.priority,
880
936
  schedule: defineOptions?.schedule,
881
937
  timezone: defineOptions?.timezone
882
938
  });
@@ -888,12 +944,13 @@ function createWorkflowRef(id, options) {
888
944
  return ref;
889
945
  }
890
946
  function createWorkflowFactory(plugins = []) {
891
- const factory = (id, handler, { inputSchema, timeout, retries, schedule, timezone } = {}) => ({
947
+ const factory = (id, handler, { inputSchema, timeout, retries, priority, schedule, timezone } = {}) => ({
892
948
  id,
893
949
  handler,
894
950
  inputSchema,
895
951
  timeout,
896
952
  retries,
953
+ priority,
897
954
  schedule,
898
955
  timezone,
899
956
  plugins: plugins.length > 0 ? plugins : undefined
@@ -907,5 +964,5 @@ function createWorkflowFactory(plugins = []) {
907
964
  }
908
965
  var workflow = createWorkflowFactory();
909
966
 
910
- //# debugId=BBCF954233412F9C64756E2164756E21
967
+ //# debugId=65B5E13A5C10F50064756E2164756E21
911
968
  //# sourceMappingURL=client.entry.js.map
@@ -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",
@@ -52,11 +66,13 @@ type StartWorkflowOptions = {
52
66
  retries?: number;
53
67
  expireInSeconds?: number;
54
68
  idempotencyKey?: string;
69
+ priority?: WorkflowPriority;
55
70
  };
56
71
  type WorkflowOptions<I extends InputParameters> = {
57
72
  timeout?: number;
58
73
  retries?: number;
59
74
  inputSchema?: I;
75
+ priority?: WorkflowPriority;
60
76
  /**
61
77
  * Recurring schedule. Accepts a cron expression (`'0 9 * * 1-5'`),
62
78
  * a duration string (`'5m'`, `'1 hour'`), or a `DurationObject`.
@@ -164,6 +180,7 @@ type WorkflowDefinition<TInput extends InputParameters = InputParameters> = {
164
180
  inputSchema?: TInput;
165
181
  timeout?: number;
166
182
  retries?: number;
183
+ priority?: WorkflowPriority;
167
184
  schedule?: Schedule;
168
185
  timezone?: string;
169
186
  plugins?: WorkflowPlugin[];
@@ -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",
@@ -52,11 +66,13 @@ type StartWorkflowOptions = {
52
66
  retries?: number;
53
67
  expireInSeconds?: number;
54
68
  idempotencyKey?: string;
69
+ priority?: WorkflowPriority;
55
70
  };
56
71
  type WorkflowOptions<I extends InputParameters> = {
57
72
  timeout?: number;
58
73
  retries?: number;
59
74
  inputSchema?: I;
75
+ priority?: WorkflowPriority;
60
76
  /**
61
77
  * Recurring schedule. Accepts a cron expression (`'0 9 * * 1-5'`),
62
78
  * a duration string (`'5m'`, `'1 hour'`), or a `DurationObject`.
@@ -164,6 +180,7 @@ type WorkflowDefinition<TInput extends InputParameters = InputParameters> = {
164
180
  inputSchema?: TInput;
165
181
  timeout?: number;
166
182
  retries?: number;
183
+ priority?: WorkflowPriority;
167
184
  schedule?: Schedule;
168
185
  timezone?: string;
169
186
  plugins?: WorkflowPlugin[];
@@ -4,7 +4,7 @@ import {
4
4
  WorkflowRunNotFoundError,
5
5
  WorkflowStatus,
6
6
  createWorkflowRef
7
- } from "./shared/chunk-5xswmve7.js";
7
+ } from "./shared/chunk-w3qcrrwx.js";
8
8
  export {
9
9
  createWorkflowRef,
10
10
  WorkflowStatus,