Saga class final

A saga: a sequence of async operations with automatic compensation on failure.

A Saga implements the Saga pattern for managing distributed transactions in a local/in-process context. It executes a sequence of steps, each with an associated compensation (rollback) function.

Key properties:

  • Atomicity simulation: Either all steps succeed, or all completed steps are compensated (rolled back) on failure
  • Compensation order: Compensations execute in reverse order of step execution (LIFO), like unwinding a stack
  • Error recovery: If any step fails, all prior compensations are executed before rethrowing the original error
  • Type safety: Each SagaStep<T> maintains its own type information, ensuring the return value type matches the compensation input type

Execution model:

  1. For each registered step:
    • Execute the step (get result of type T)
    • Register its compensation with the result
    • If success, continue to next step
  2. If any step throws:
    • Execute all registered compensations in reverse order (LIFO)
    • Rethrow the original error
  3. If all steps succeed:
    • All compensations are registered but never executed
    • Saga completes successfully

Compensation robustness:

  • If a compensation fails, it's logged but doesn't stop other compensations
  • All registered compensations will attempt to execute, even if some fail
  • The original error is rethrown after all compensation attempts

Use cases:

  • Multi-step operations: Operations that span multiple services/databases
  • Data consistency: Ensuring data consistency across multiple steps
  • Order processing: Purchase → Payment → Inventory → Shipping
  • User registration: Create account → Send email → Initialize preferences
  • Batch operations: Multiple interdependent operations with rollback

Example - Order processing:

final saga = Saga();

// Step 1: Create order
saga.step(SagaStep(
  name: 'Create Order',
  execute: () async {
    final orderId = await orderService.create(items);
    return orderId;
  },
  compensate: (orderId) async {
    await orderService.delete(orderId);
  },
));

// Step 2: Process payment
saga.step(SagaStep(
  name: 'Process Payment',
  execute: () async {
    final transactionId = await paymentService.charge(amount);
    return transactionId;
  },
  compensate: (transactionId) async {
    await paymentService.refund(transactionId);
  },
));

// Step 3: Reserve inventory
saga.step(SagaStep(
  name: 'Reserve Inventory',
  execute: () async {
    final reservationId = await inventoryService.reserve(items);
    return reservationId;
  },
  compensate: (reservationId) async {
    await inventoryService.release(reservationId);
  },
));

// Execute the saga
try {
  await saga();
  print('Order processing completed successfully');
} catch (e) {
  print('Order processing failed: \$e');
  // All prior steps have been compensated automatically
}
Annotations
  • @experimental

Constructors

Saga()

Properties

hashCode int
The hash code for this object.
no setterinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

call() Future<void>
Executes all registered saga steps in order.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
step<T extends Object?>(SagaStep<T> step) → void
Registers a saga step to be executed.
toString() String
A string representation of this object.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited