Vyuh Workflows
Write long-running business processes as typed Dart. Every side effect, human decision, signal, and timer is a durable await that WorkflowRuntime can replay after a crash, restart, or competing worker.
Why Durable Workflows?
Deterministic Replay
Workflows are Dart functions. After a restart, the runtime replays recorded history and stops at the next unresolved durable await.
Assigned Work
User tasks wait in storage, not in a process. Assignment, claim, expiry, and completion are first-class runtime actions.
Transactional History
Runs, events, and commands commit together. PostgreSQL leases, fencing, and SKIP LOCKED keep competing workers honest.
One Vocabulary, Two Surfaces
Author in typed Dart or constrained JSON. Both compile to a WorkflowDefinition and execute in WorkflowRuntime.
Getting Started
Core Concepts
- Workflow — A versioned Dart or JSON definition with stable operation IDs
- Runs and History — An execution is a run plus immutable events and commands
- Registration — Install workflows and handlers through WorkflowModule
- Replay — Completed awaits return recorded results; unresolved ones block
- Bindings — How JSON workflows read input and published step results
- CDX Integration — Templates, Blueprint, inbox UI, and the workflow service
Durable Vocabulary
| Await | Purpose |
|---|---|
| Service task | Idempotent automated work |
| User task | Assigned durable work |
| Signal | External event wait |
| Timer | Durable sleep |
| Child workflow | Call, spawn, and join |
Patterns & Examples
Quick Example
import 'package:vyuh_workflow_engine/vyuh_workflow_runtime.dart';
final reserve = Workflow.activity<Order, Reservation>(
name: 'orders.reserve',
input: orderCodec,
output: reservationCodec,
);
final approve = Workflow.userTask<Reservation, Approval>(
name: 'orders.approve',
input: reservationCodec,
response: approvalCodec,
);
final orderApproval = Workflow.define<Order, Result>(
code: 'orders.approval',
version: 1,
fingerprint: buildFingerprint,
input: orderCodec,
output: resultCodec,
execute: (flow, order) async {
final reservation = await flow.serviceTask(
reserve,
order,
id: 'reserve',
retry: RetryPolicy.simple,
);
final decision = await flow.userTask(
approve,
reservation,
id: 'approve',
title: 'Approve order',
assignment: Assignment(roleIds: ['order-approver']),
);
return decision.approved ? Result.approved() : Result.rejected();
},
);
final runtime = WorkflowRuntime(
storage: InMemoryWorkflowStorage(),
modules: [
WorkflowModule(
name: 'orders',
workflows: [orderApproval],
activities: [
ActivityBinding.from(reserve, ReservationHandler()),
],
userTasks: [approve],
),
],
);
final run = await runtime.start(orderApproval.ref, order);New application code imports vyuh_workflow_runtime.dart. The graph LegacyWorkflowEngine remains only as a compatibility surface for in-flight product runs.
For CDX approvals, use ApprovalWorkflowDefinition from cdx_workflow_templates and complete work through the workflow service. See Approval Workflows and CDX Integration.