Genel bakış

Delay

Delay behavior execution with AbortSignal cancellation.

delaycancellation

Install

$
Terminal window
pnpm dlx shadcn@latest add https://archyn.net/r/delay.json

Copy the files below into the target paths shown in each tab.

ts@lib/flow/delay.ts
import { type Behavior, type RuntimeContext, resultFromSignal, runBehavior } from "./core/runtime";
import { type TimingError } from "./timeout";
import { wait } from "./wait";
/**
* Waits before running a source behavior.
*
* `delay` models a pause that is part of the workflow itself. Cancellation during the delay returns
* a timing cancellation error and the source behavior is not started.
*
* @typeParam I - Input type.
* @typeParam O - Source output type.
* @typeParam E - Source domain error type.
* @typeParam C - Custom context type.
* @param source - Behavior to run after the delay.
* @param ms - Delay in milliseconds before source execution.
* @returns A behavior with the source result or timing errors.
*
* @example
* ```ts
* const delayedLoad = delay(loadUser, 250);
* ```
*/
export function delay<I, O, E, C extends object>(
source: Behavior<I, O, E, C>,
ms: number,
): Behavior<I, O, E | TimingError, C> {
return async (input: I, context: RuntimeContext<C>) => {
if (context.signal.aborted) {
return resultFromSignal(context.signal);
}
const delayResult = await wait(ms, context.signal);
if (!delayResult.ok) {
return delayResult;
}
return runBehavior(source, input, context);
};
}

Update the import paths to match your project setup.

Delay the start of a Behavior while preserving cancellation and typed errors.

Usage

delay waits before running a source Behavior. It is useful when the pause is part of the workflow contract rather than retry policy.

Use it when:

  • Debounce or pace work before a Behavior starts.
  • Use a typed, cancellable delay without writing custom timer code.
  • Keep the source Behavior types unchanged apart from timing errors.
import { delay } from "@/lib/flow/delay";
import { task } from "@/lib/flow/task";
const saveDraft = task((draft: { body: string }) => ({ saved: true, draft }));
const delayedSave = delay(saveDraft, 300);

Behavior

delay calls wait(ms, context.signal) first. If the wait succeeds, it runs the source Behavior with the original input and context.

Source domain errors pass through. Cancellation during the delay returns Cancelled, and cancellation after the delay is handled by the source runtime path.

Types

The source output and error types are preserved, with TimingError added for cancellation during the delay.

Import from @/lib/flow/delay.

Composition Notes

Use delay before a source when the pause is part of the workflow contract.

Do not use delay for backoff after failure; retry delay communicates that intent better.

Source

ts@lib/flow/delay.ts
import { type Behavior, type RuntimeContext, resultFromSignal, runBehavior } from "./core/runtime";
import { type TimingError } from "./timeout";
import { wait } from "./wait";
/**
* Waits before running a source behavior.
*
* `delay` models a pause that is part of the workflow itself. Cancellation during the delay returns
* a timing cancellation error and the source behavior is not started.
*
* @typeParam I - Input type.
* @typeParam O - Source output type.
* @typeParam E - Source domain error type.
* @typeParam C - Custom context type.
* @param source - Behavior to run after the delay.
* @param ms - Delay in milliseconds before source execution.
* @returns A behavior with the source result or timing errors.
*
* @example
* ```ts
* const delayedLoad = delay(loadUser, 250);
* ```
*/
export function delay<I, O, E, C extends object>(
source: Behavior<I, O, E, C>,
ms: number,
): Behavior<I, O, E | TimingError, C> {
return async (input: I, context: RuntimeContext<C>) => {
if (context.signal.aborted) {
return resultFromSignal(context.signal);
}
const delayResult = await wait(ms, context.signal);
if (!delayResult.ok) {
return delayResult;
}
return runBehavior(source, input, context);
};
}