evoq_saga_compensation (evoq v1.14.1)
View SourceSaga compensation for rollback transactions.
Provides utilities for implementing compensating transactions in process managers (sagas).
Compensation Flow
1. Saga dispatches commands: [Cmd1, Cmd2, Cmd3] 2. Cmd3 fails 3. Saga calls compensate/2 for rollback 4. Compensation generates: [Compensate2, Compensate1] 5. Compensating commands executed in reverse order
Example
-module(order_saga).
-behaviour(evoq_process_manager).
compensate(State, #evoq_command{command_type = ship_order}) ->
%% Compensate shipping by canceling shipment
CancelCmd = evoq_command:new(cancel_shipment, shipping, ...),
{ok, [CancelCmd]};
compensate(State, #evoq_command{command_type = charge_payment}) ->
%% Compensate payment by issuing refund
RefundCmd = evoq_command:new(issue_refund, payment, ...),
{ok, [RefundCmd]};
compensate(_State, _Cmd) ->
skip. %% No compensation needed
Summary
Functions
Build a chain of compensating commands for all executed commands. Returns commands in reverse order (last executed = first compensated).
Execute compensation for a failed command. Generates and dispatches compensating commands.
Get all executed commands from saga state.
Record an executed command in the saga state. Used for tracking commands for compensation.
Functions
-spec build_compensation_chain(atom(), term()) -> [#evoq_command{command_id :: binary() | undefined, command_type :: atom() | undefined, aggregate_type :: atom() | undefined, aggregate_id :: binary() | undefined, payload :: map(), metadata :: map(), causation_id :: binary() | undefined, correlation_id :: binary() | undefined, idempotency_key :: binary() | undefined}].
Build a chain of compensating commands for all executed commands. Returns commands in reverse order (last executed = first compensated).
-spec execute_compensation(pid(), #evoq_command{command_id :: binary() | undefined, command_type :: atom() | undefined, aggregate_type :: atom() | undefined, aggregate_id :: binary() | undefined, payload :: map(), metadata :: map(), causation_id :: binary() | undefined, correlation_id :: binary() | undefined, idempotency_key :: binary() | undefined}, map()) -> {ok, [{ok, non_neg_integer(), [map()]} | {error, term()}]} | skip.
Execute compensation for a failed command. Generates and dispatches compensating commands.
-spec get_executed_commands(term()) -> [#evoq_command{command_id :: binary() | undefined, command_type :: atom() | undefined, aggregate_type :: atom() | undefined, aggregate_id :: binary() | undefined, payload :: map(), metadata :: map(), causation_id :: binary() | undefined, correlation_id :: binary() | undefined, idempotency_key :: binary() | undefined}].
Get all executed commands from saga state.
-spec record_command(#evoq_command{command_id :: binary() | undefined, command_type :: atom() | undefined, aggregate_type :: atom() | undefined, aggregate_id :: binary() | undefined, payload :: map(), metadata :: map(), causation_id :: binary() | undefined, correlation_id :: binary() | undefined, idempotency_key :: binary() | undefined}, term()) -> term().
Record an executed command in the saga state. Used for tracking commands for compensation.