Dispatcher & Hooks

Wire workflow execution in Node or Cloudflare via durable hooks.

Workflows execute when durable hooks are processed. Request paths enqueue and notify; the dispatcher is responsible for running the workflow hooks when work is available.

In-process dispatcher (Node)

Use the in-process dispatcher for local development or small deployments:

import { createDurableHooksProcessor } from "@fragno-dev/db/dispatchers/node";

const dispatcher = createDurableHooksProcessor([fragment], {
  pollIntervalMs: 2000,
});

dispatcher.startPolling();

Call dispatcher.stopPolling() during application shutdown.

Lifecycle callbacks

The fragment config accepts onWorkflowRestarted and onWorkflowTerminal. Both run through durable hooks after their state transition commits. The dispatcher must process each hook before its callback runs. Make callback side effects idempotent because hook delivery can be retried.

See Workflow lifecycle callbacks for the configuration and payload shapes.

Cloudflare Durable Object dispatcher

For Cloudflare, use the Fragment Durable Object host. It migrates the fragment, creates the durable hooks dispatcher, forwards requests, and runs the alarm handler:

import {
  createFragmentDurableObjectHost,
  type FragmentDurableObjectHost,
} from "@fragno-dev/db/dispatchers/cloudflare-do/fragment-durable-object";
import { createMyWorkflowFragment, type MyWorkflowFragment } from "@/fragno/workflows-fragment";

export class WorkflowsDispatcher {
  fragment!: MyWorkflowFragment;
  host: FragmentDurableObjectHost<undefined, MyWorkflowFragment>;

  constructor(state: DurableObjectState, env: Env) {
    this.host = createFragmentDurableObjectHost({
      state,
      env,
      createRuntime: () => createMyWorkflowFragment({ env, state }),
    });

    state.blockConcurrencyWhile(async () => {
      this.fragment = await this.host.initialize(undefined);
    });
  }

  fetch(request: Request) {
    return this.host.fetch(this.fragment, request);
  }

  alarm() {
    return this.host.alarm();
  }
}

If request processing needs a waitUntil callback, pass it as the third argument to this.host.fetch(...).

Notes

  • Protect dispatcher workers and mounted workflow routes with application and network-level controls.
  • Use a durable hook processor/dispatcher to run workflows when enqueued.
  • Multiple Node dispatcher instances can safely poll concurrently.