Operations
An operation is automated, side-effecting execution. The workflow schedules it; a leased worker executes a versioned OperationHandler.
dart
final reservation = await workflow.perform(
reserve,
order,
id: 'reserve',
schedule: WorkflowSchedule.exponential(
const Duration(seconds: 1),
attempts: 3,
),
);id is the replay identity. Retry, timeout, idempotency, and annotations are named arguments on the same direct operation.
Handler
dart
final reserveHandler = reserve.implement((operation, order) {
return reservations.reserve(
order,
idempotencyKey: operation.context.idempotencyKey,
);
});OperationContext exposes runId, commandId, operationKey, attempt, idempotencyKey, and heartbeat(). Long work must heartbeat before the lease expires.
Timeouts and Retries
Operations have no timeout unless configured. Retryable failures use backoff and keep the same idempotency key. Permanent failures fail the command. Manual retry creates a new attempt and retains the key.
Prefer this shape for work that lasts days:
- The operation starts an external job and returns its ID.
- The workflow waits for an event or a durable poll timer.
- A callback records completion and wakes replay.