MallaDocs

Motor de flujos de trabajo

execSteps, los adaptadores de navegador, síncrono y durable, y las reglas de repetición.

Guía para desarrolladores

Los flujos de trabajo de cliente y de servidor comparten un único formato JSON y un único intérprete, @malla/engine. Solo cambia el adaptador que ejecuta cada paso. Los flujos de trabajo se interpretan, nunca se compilan: publicar guarda una versión inmutable y un solo runner atiende a todos los sitios.

Tres adaptadores

NavegadorSitios publicados y vista previa del lienzo. sleep es un temporizador; waitForEvent no está disponible.
SíncronoEn línea dentro del runner, para endpoints y trabajos cortos. Reintenta en el mismo proceso; los pasos durables lanzan DurableRequired.
DurableCloudflare Workflows (SiteWorkflow): sleep, waitForEvent, reintentos con backoff, replay.
ts
interface StepAdapter {
  do<T>(name: string, retry: RetryPolicy | undefined, fn: () => Promise<T>): Promise<T>
  sleep(name: string, duration: string): Promise<void>
  waitForEvent(name: string, opts: { type: string; timeout?: string }): Promise<unknown>
}

Formato de los pasos

ts
interface WorkflowStep {
  id: string
  action: string                         // core.<name> or <pluginId>.<name>
  params?: Record<string, unknown>       // values may be Bindings at any depth
  branches?: Record<string, WorkflowStep[]>  // then/else, body, try/catch, cases, lanes a…h
  disabled?: boolean
  retry?: { limit: number; delay?: string; backoff?: 'constant' | 'linear' | 'exponential' }
}

El resultado de cada paso se guarda en steps[id]. El control de flujo anida listas de pasos en branches. Un flujo de trabajo de servidor es durable exactamente cuando contiene un core.sleep o un core.waitForEvent activado.

Reglas de replay

Cloudflare Workflows vuelve a ejecutar el código y devuelve resultados en caché para los pasos ya completados, así que:

  • Los nombres de los pasos son rutas deterministas, <branch>/<loop index>/<step>, para que los bucles y las ramas se reproduzcan correctamente; las ramas en paralelo añaden <name>/<lane>/<step>.
  • Todo lo que está fuera de un paso es determinista; fn.now() corre dentro de los pasos.
  • La versión del flujo de trabajo queda fijada en los parámetros de la ejecución, así que las ejecuciones en curso nunca ven las ediciones.
  • Los resultados de los pasos que se guardan en el historial tienen un tope de 16 KB cada uno.

Conexión del runner

text
apps/runner (Worker)
  ├─ POST /run/:siteId/:workflowId     test and editor runs (api)
  ├─ ALL  /api/*                       endpoints + webhooks (sites)
  ├─ Workflows binding  → SiteWorkflow   durable runs
  ├─ Durable Objects    → SiteScheduler (cron alarms), RunStream (live test runs),
  │                       SiteDatabase (tables, visitors)
  └─ Worker Loader      → runJs isolates (no bindings, no secrets)

Los flujos de trabajo de servidor publicados viven en KV en wf:<environment>:<siteId>, con sus rutas HTTP y sus programaciones cron. Una publicación reprograma los crons del sitio.

Límites

ClienteServidor
Pasos por ejecución2001.000, menos según el plan
Profundidad de anidación88
Iteraciones de bucle1.0001.000
Reintentos por paso—5
Tiempo máximo de una ejecución síncrona—30 s
Ramas en paralelo / casos de switch8 / 328 / 32