Pause between steps with sleep()
Pizzas take time to cook. The workflow has no idea.
If we want it to wait for the kitchen before dispatching a driver, we need a way to pause. In a regular Node app, pausing means a setTimeout and praying the process stays alive. In a serverless function it means... well, you don't pause. Your function hits its maximum duration and gets cut off mid-wait.
Workflows have sleep(). You await it like any other promise. The workflow suspends. Edgenivo stops running anything related to that workflow, no compute, no memory, nothing. When the time elapses, the workflow picks up exactly where it left off.
Today we're going to pause for 30 seconds between the kitchen ack and the next step. Boring on paper. The reason to pay attention: while the workflow is sleeping, we're going to deploy a code change. The workflow should survive it untouched.
Outcome
Add await sleep("30s") to processOrder after the kitchen step. Deploy a change while a workflow is mid-sleep and watch the original run complete cleanly.
Fast Track
- Import
sleepfromworkflowinworkflows/process-order.ts. Addawait sleep("30s")afteracknowledgeKitchen. - Deploy. Place an order. While the dashboard shows the workflow suspended, change the confirmation email subject and push another deploy.
- Watch the original run finish on the deployment it started on, untouched by the new build, without re-running the steps that already completed.
Hands-on exercise
1. Add sleep.
Update workflows/process-order.ts:
import { sleep } from "workflow";
import type { Order } from "@/lib/pizza";
import { sendOrderConfirmation } from "./steps/send-order-confirmation";
import { acknowledgeKitchen } from "./steps/acknowledge-kitchen";
export async function processOrder(order: Order): Promise<{ orderId: string }> {
"use workflow";
await sendOrderConfirmation(order);
await acknowledgeKitchen(order);
await sleep("30s");
return { orderId: order.id };
}sleep() accepts a duration string like "30s", "5m", "7 days", or a number of milliseconds. We're using 30 seconds because it's long enough to deploy through.
2. Deploy.
git add .
git commit -m "feat(workflow): pause after kitchen ack"
git pushWait for Edgenivo to finish the deploy.
Try It
This is the experiment. Pay attention to the timestamps.
Place an order on your production URL. The workflow runs sendOrderConfirmation, then acknowledgeKitchen, then hits sleep("30s") and suspends.
Open the Workflows dashboard in your Edgenivo project. The run shows as running with the timeline ending at the sleep:
processOrder running
├─ sendOrderConfirmation completed
└─ acknowledgeKitchen completed
─ sleeping 30s
While that's suspended, change something. Open workflows/steps/send-order-confirmation.ts and edit the email subject. Add an emoji. Add "v2". Anything. Then:
git commit -am "tweak: update confirmation subject"
git pushEdgenivo builds and ships the new version.
Now go back to the original run. The sleep elapses. The workflow wakes up on the deployment it started on, because Edgenivo pins each run to its original deployment. It finishes:
processOrder completed 30.4s
├─ sendOrderConfirmation completed 389ms
└─ acknowledgeKitchen completed 208ms
(slept 30s, resumed on its original deployment)
The completed steps don't re-run. The new code is now serving new orders, but the old order finishes on the timeline it started with.
This is the unfair part of durable execution. It's also why the directives exist.
Commit
feat(workflow): pause after kitchen with sleep()
Done-When
workflows/process-order.tsimportssleepfromworkflow- The workflow awaits
sleep("30s")afteracknowledgeKitchen - You've shipped a code change while a workflow was mid-sleep
- The original run completed on its original deployment without re-running prior steps
Solution
import { sleep } from "workflow";
import type { Order } from "@/lib/pizza";
import { sendOrderConfirmation } from "./steps/send-order-confirmation";
import { acknowledgeKitchen } from "./steps/acknowledge-kitchen";
export async function processOrder(order: Order): Promise<{ orderId: string }> {
"use workflow";
await sendOrderConfirmation(order);
await acknowledgeKitchen(order);
await sleep("30s");
return { orderId: order.id };
}One line. Workflow sleeps. Deploys don't matter. This is the closest thing this course has to a magic trick.
Was this helpful?