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:
- For each registered step:
- Execute the step (get result of type T)
- Register its compensation with the result
- If success, continue to next step
- If any step throws:
- Execute all registered compensations in reverse order (LIFO)
- Rethrow the original error
- 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