Skip to content

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:

  1. The operation starts an external job and returns its ID.
  2. The workflow waits for an event or a durable poll timer.
  3. A callback records completion and wakes replay.

See Also ​