workflow-cron-sleep 1.0.0 → 1.0.2

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.
Files changed (2) hide show
  1. package/README.md +52 -13
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -88,16 +88,16 @@ Throws an error if the cron expression is invalid or has no future occurrences.
88
88
 
89
89
  Since `cronSleep` only sleeps until the **next** occurrence, you need to design your workflow architecture to handle recurring schedules.
90
90
 
91
- ### Pattern: Separate Scheduler and Processor Workflows
91
+ ### Pattern: While Loop Scheduler
92
92
 
93
- Separate your scheduling logic from your business logic by keeping workflows and steps in different files:
93
+ The simplest approach is a single workflow with a `while (true)` loop that sleeps and triggers your business logic workflow repeatedly:
94
94
 
95
95
  **`workflows/report-scheduler.ts`** - The scheduler workflow
96
96
  ```typescript
97
97
  import { cronSleep } from "workflow-cron-sleep"
98
- import { startReportProcessor } from "./steps"
98
+ import { triggerReportProcessor } from "./steps"
99
99
 
100
- interface ReportSchedulerInput {
100
+ export interface ReportSchedulerInput {
101
101
  reportId: string
102
102
  cronExpression: string
103
103
  }
@@ -107,26 +107,65 @@ export async function reportScheduler(input: ReportSchedulerInput) {
107
107
 
108
108
  const { reportId, cronExpression } = input
109
109
 
110
- // Wait for the next scheduled time
111
- await cronSleep(cronExpression, { timezone: "America/New_York" })
112
-
113
- // Trigger the processor workflow
114
- await startReportProcessor(reportId)
110
+ while (true) {
111
+ // Wait for the next scheduled time
112
+ await cronSleep(cronExpression, { timezone: "America/New_York" })
113
+
114
+ // Trigger the processor workflow
115
+ await triggerReportProcessor(reportId)
116
+ }
115
117
  }
116
118
  ```
117
119
 
118
- **`workflows/steps.ts`** - Step functions in a separate file
120
+ **`workflows/steps.ts`** - Step function to start the processor
119
121
  ```typescript
120
- import { start } from "workflow"
122
+ import { start } from "workflow/api"
121
123
  import { reportProcessorWorkflow } from "./report-processor"
122
124
 
123
- export async function startReportProcessor(reportId: string) {
125
+ export async function triggerReportProcessor(reportId: string) {
124
126
  "use step"
125
127
  await start(reportProcessorWorkflow, [{ reportId }])
126
128
  }
127
129
  ```
128
130
 
129
- This pattern keeps your scheduling and business logic decoupled, making each workflow easier to test and maintain.
131
+ **`workflows/report-processor.ts`** - The processor workflow (business logic)
132
+ ```typescript
133
+ export interface ReportProcessorInput {
134
+ reportId: string
135
+ }
136
+
137
+ export async function reportProcessorWorkflow(input: ReportProcessorInput) {
138
+ "use workflow"
139
+
140
+ const { reportId } = input
141
+
142
+ // Your business logic here - completely agnostic to scheduling
143
+ await generateReport(reportId)
144
+ await sendNotifications(reportId)
145
+ }
146
+ ```
147
+
148
+ ### Starting and Canceling
149
+
150
+ ```typescript
151
+ import { start, getRun } from "workflow/api"
152
+ import { reportScheduler } from "./workflows/report-scheduler"
153
+
154
+ // Start the cron scheduler
155
+ const run = await start(reportScheduler, [{
156
+ reportId: "daily-report",
157
+ cronExpression: "0 9 * * *"
158
+ }])
159
+
160
+ // Save the run ID to cancel later
161
+ await db.cronJobs.create({ runId: run.id })
162
+
163
+ // To cancel the cron (stops the while loop)
164
+ const currentRun = getRun(run.id)
165
+ await currentRun.cancel()
166
+ ```
167
+
168
+ This pattern keeps your scheduling and business logic decoupled. The scheduler runs forever, triggering your processor workflow on schedule. Save the `runId` so you can cancel if the cron expression changes or the job is no longer needed.
130
169
 
131
170
  ## Requirements
132
171
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workflow-cron-sleep",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Sleep until the next cron expression occurrence in Vercel Workflows",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -40,4 +40,4 @@
40
40
  "typescript": "^5.3.0",
41
41
  "workflow": "^4.0.1-beta.44"
42
42
  }
43
- }
43
+ }