Skip to content

Service Tasks

A service task is automated, side-effecting work. The workflow schedules it; a leased worker executes a versioned ActivityHandler.

dart
final reservation = await flow.serviceTask(
  reserve,
  order,
  id: 'reserve',
  retry: RetryPolicy(maxAttempts: 3),
);

id is the replay identity. activity is a compatibility alias for serviceTask.

Handler

dart
final class ReservationHandler implements ActivityHandler<Order, Reservation> {
  @override
  Future<Reservation> handle(ActivityContext context, Order order) {
    return reservations.reserve(
      order,
      idempotencyKey: context.idempotencyKey,
    );
  }
}

ActivityContext exposes runId, commandId, operationKey, attempt, idempotencyKey, and heartbeat(). Long work must heartbeat before the lease expires.

Timeouts and Retries

Activities 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 activity starts an external job and returns its ID.
  2. The workflow waits for a signal or a durable poll timer.
  3. A callback records completion and wakes replay.

See Also