pg-workflows 0.2.0 → 0.3.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/README.md +67 -2
- package/dist/index.cjs +329 -189
- package/dist/index.d.cts +105 -41
- package/dist/index.d.ts +105 -41
- package/dist/index.js +299 -180
- package/dist/index.js.map +10 -9
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -45,6 +45,8 @@ If you need enterprise-grade features like distributed tracing, complex DAG sche
|
|
|
45
45
|
- **Durable Execution on Postgres** - Workflow state is persisted in PostgreSQL. Workflows survive process crashes, restarts, and deployments.
|
|
46
46
|
- **Step-by-Step Execution** - Break complex processes into discrete, resumable steps. Each step runs exactly once, even across retries.
|
|
47
47
|
- **Event-Driven Orchestration** - Pause workflows and wait for external events with `step.waitFor()`. Resume automatically when signals arrive.
|
|
48
|
+
- **Polling Steps** - Repeatedly check a condition with `step.poll()` at a configurable interval (minimum 30s) until it returns a truthy value or a timeout expires.
|
|
49
|
+
- **Scheduled & Delay Steps** - Wait until a specific date with `step.waitUntil()`, or use `step.delay()` / `step.sleep()` with human-readable durations (`'3 days'`, `{ hours: 2 }`). Past dates run immediately.
|
|
48
50
|
- **Pause and Resume** - Manually pause long-running workflows and resume them later via API.
|
|
49
51
|
- **Built-in Retries** - Automatic retries with exponential backoff at the workflow level.
|
|
50
52
|
- **Configurable Timeouts** - Set workflow-level and step-level timeouts to prevent runaway executions.
|
|
@@ -378,6 +380,23 @@ const eventData = await step.waitFor('wait-step', {
|
|
|
378
380
|
});
|
|
379
381
|
```
|
|
380
382
|
|
|
383
|
+
### Scheduled and Delay Steps
|
|
384
|
+
|
|
385
|
+
Wait until a specific time, or delay for a duration (sugar over `waitUntil`). If the date is in the past, the step runs immediately.
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
// Wait until a specific date (Date, ISO string, or { date })
|
|
389
|
+
await step.waitUntil('scheduled-step', new Date('2025-06-01'));
|
|
390
|
+
await step.waitUntil('scheduled-step', '2025-06-01T12:00:00.000Z');
|
|
391
|
+
await step.waitUntil('scheduled-step', { date: new Date('2025-06-01') });
|
|
392
|
+
|
|
393
|
+
// Delay for a duration (string or object). sleep is an alias of delay.
|
|
394
|
+
await step.delay('cool-off', '3 days');
|
|
395
|
+
await step.delay('cool-off', { days: 3 });
|
|
396
|
+
await step.delay('ramp-up', '2 days 12 hours');
|
|
397
|
+
await step.sleep('backoff', '1 hour');
|
|
398
|
+
```
|
|
399
|
+
|
|
381
400
|
### Resource ID
|
|
382
401
|
|
|
383
402
|
The optional `resourceId` associates a workflow run with an external entity in your application - a user, an order, a subscription, or any domain object the workflow operates on. It serves two purposes:
|
|
@@ -453,6 +472,44 @@ const batchWorkflow = workflow('batch-process', async ({ step }) => {
|
|
|
453
472
|
});
|
|
454
473
|
```
|
|
455
474
|
|
|
475
|
+
### Scheduled Reminder with Delay
|
|
476
|
+
|
|
477
|
+
```typescript
|
|
478
|
+
const reminderWorkflow = workflow('send-reminder', async ({ step, input }) => {
|
|
479
|
+
await step.run('send-initial', async () => {
|
|
480
|
+
return await sendEmail(input.email, 'Welcome!');
|
|
481
|
+
});
|
|
482
|
+
// Pause for 3 days, then send follow-up (durable - survives restarts)
|
|
483
|
+
await step.delay('cool-off', '3 days');
|
|
484
|
+
await step.run('send-follow-up', async () => {
|
|
485
|
+
return await sendEmail(input.email, 'Here’s a reminder…');
|
|
486
|
+
});
|
|
487
|
+
}, { inputSchema: z.object({ email: z.string().email() }) });
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### Polling Until a Condition Is Met
|
|
491
|
+
|
|
492
|
+
```typescript
|
|
493
|
+
const paymentWorkflow = workflow('await-payment', async ({ step, input }) => {
|
|
494
|
+
const result = await step.poll(
|
|
495
|
+
'wait-for-payment',
|
|
496
|
+
async () => {
|
|
497
|
+
const payment = await getPaymentStatus(input.paymentId);
|
|
498
|
+
return payment.completed ? payment : false;
|
|
499
|
+
},
|
|
500
|
+
{ interval: '1 minute', timeout: '24 hours' },
|
|
501
|
+
);
|
|
502
|
+
|
|
503
|
+
if (result.timedOut) {
|
|
504
|
+
return { status: 'expired' };
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
return { status: 'paid', payment: result.data };
|
|
508
|
+
});
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
`conditionFn` returns `false` to keep polling, or a truthy value to resolve the step. The minimum interval is 30s (default). If `timeout` is omitted the step polls indefinitely.
|
|
512
|
+
|
|
456
513
|
### Error Handling with Retries
|
|
457
514
|
|
|
458
515
|
```typescript
|
|
@@ -542,13 +599,21 @@ The context object passed to workflow handlers:
|
|
|
542
599
|
logger: WorkflowLogger, // Logger instance
|
|
543
600
|
step: {
|
|
544
601
|
run: <T>(stepId, handler) => Promise<T>,
|
|
545
|
-
|
|
546
|
-
|
|
602
|
+
// without timeout: always returns event data T
|
|
603
|
+
waitFor: <T>(stepId, { eventName, schema? }) => Promise<T>,
|
|
604
|
+
// with timeout: returns event data T or undefined if timeout fires first
|
|
605
|
+
waitFor: <T>(stepId, { eventName, timeout, schema? }) => Promise<T | undefined>,
|
|
606
|
+
waitUntil: (stepId, date | dateString | { date }) => Promise<void>,
|
|
607
|
+
delay: (stepId, duration) => Promise<void>,
|
|
608
|
+
sleep: (stepId, duration) => Promise<void>,
|
|
547
609
|
pause: (stepId) => Promise<void>,
|
|
610
|
+
poll: <T>(stepId, conditionFn, { interval?, timeout? }) => Promise<{ timedOut: false; data: T } | { timedOut: true }>,
|
|
548
611
|
}
|
|
549
612
|
}
|
|
550
613
|
```
|
|
551
614
|
|
|
615
|
+
`duration` is a string (e.g. `'3 days'`, `'2h'`) or an object (`{ weeks?, days?, hours?, minutes?, seconds? }`). See the `Duration` type and `parseDuration` from the package.
|
|
616
|
+
|
|
552
617
|
### WorkflowStatus
|
|
553
618
|
|
|
554
619
|
```typescript
|