Runnel 2.8: replay any workflow from a failed step.Read the release

Skip to content
Runnel

2.6.0

Workflows can wait for an event

ctx.waitForEvent pauses a workflow until something happens elsewhere, such as an approval or a payment, for up to 30 days, without holding a worker.

  • New
  • Fixed

waitForEvent

Some workflows need to stop until something outside them happens: a document signed, a payment settled, a reviewer pressing approve. Until now that meant polling in a loop of sleeps. Workflows can now wait for an event:

const kyc = await ctx.waitForEvent('kyc-approved', {
  event: 'kyc.approved',
  match: { userId: input.userId },
  timeout: '7d',
});
if (!kyc) return ctx.step('send-reminder', () => remind(input.userId));

Send the event from anywhere with runnel.events.send('kyc.approved', { userId: 'usr_311' }), or POST /v1/events. The workflow resumes with the event’s payload, or with null when the timeout passes first.

While it waits, the run holds no worker and no concurrency slot. Waits can last up to 30 days. match compares top-level fields for equality; events that arrive before the workflow starts waiting are kept for 5 minutes, so a fast reply is not lost.

Available in Python as await ctx.wait_for_event(…) and in Go as runnel.WaitForEvent(ctx, …).

Fixes

  • ctx.sleep longer than 7 days was rounded down to 7 days. The limit is now 365 days.
  • A workflow step that returned undefined was stored as null and replayed as null.
  • The dashboard’s run timeline now shows sleeps and waits as gaps instead of a running step.