DoubleEntryLedger.Workers.CommandWorker.UpdateTransactionCommand (double_entry_ledger v0.2.0)
View SourceProcesses update (transaction) events in the double-entry ledger system.
This module handles the complete lifecycle of update events, which modify existing transactions in the ledger system. It implements optimistic concurrency control (OCC) to handle potential conflicts when multiple processes attempt to update the same transaction.
Workflow
- Retrieves the original transaction created by a creation event.
- Applies modifications specified in the update event.
- Handles potential conflicts using retry mechanisms.
- Updates the event status based on the operation result.
Error Handling
Comprehensive error handling is provided for:
- Pending create events (update attempted before create is complete)
- Optimistic concurrency failures (OCC conflicts)
- General processing errors
Main Functions
process/2— Entry point for processing an update event.build_transaction/3— Constructs the Ecto.Multi for transaction update.handle_build_transaction/3— Adds event update or error handling steps to the Multi.handle_transaction_map_error/3— Handles errors in transaction map conversion.handle_occ_final_timeout/2— Handles OCC retry exhaustion.
Summary
Functions
Builds the shared Ecto.Multi pipeline for both success and error flows.
Builds a multi-step transaction for updating a transaction record.
Adds the step to update the event or handle errors after transaction processing.
Handles the case when OCC retries are exhausted.
Handles errors that occur when converting event data to a transaction map.
Processes an update event by modifying the corresponding transaction.
Processes a command with OCC retry logic.
Finalizes when retry attempts are exhausted.
Functions
@spec build_multi(module(), DoubleEntryLedger.Occ.Occable.t(), Ecto.Repo.t()) :: Ecto.Multi.t()
Builds the shared Ecto.Multi pipeline for both success and error flows.
:transaction_map– converts raw data to a map or returns an error tuple- merges in either:
handle_transaction_map_error/3when conversion failsbuild_transaction/4+handle_build_transaction/3on success
Parameters
module- the processor module implementing the callbacksoccable_item- the Command or TransactionCommandMap being processedrepo- the Ecto repo to use for DB ops
Returns
- an
Ecto.Multiready forrepo.transaction/1
Builds a multi-step transaction for updating a transaction record.
This function implements the OCC.Processor behavior by constructing an Ecto.Multi that:
- Retrieves the original transaction created by a creation event.
- Updates the transaction with the new attributes.
- Marks the update event as processed.
Parameters
event: The update event being processed.attr: The attributes to apply to the transaction.repo: The Ecto repo to use for database operations.
Returns
- An
Ecto.Multistruct with named operations for transaction processing.
Adds the step to update the event or handle errors after transaction processing.
This function inspects the results of the previous Multi steps and determines whether to mark the event as processed, revert it to pending, schedule a retry, or move it to the dead letter queue.
Parameters
multi: The Ecto.Multi built so far.event: The event being processed._repo: The Ecto repository (unused).
Returns
- The updated
Ecto.Multiwith an:command_successor:command_failurestep.
Handles the case when OCC retries are exhausted.
Delegates to DoubleEntryLedger.Workers.CommandWorker.TransactionCommandResponseHandler.handle_occ_final_timeout/2.
Parameters
command_map: The event being processed.repo: The Ecto repository.
Returns
- An
Ecto.Multithat updates the event as dead letter or timed out.
Handles errors that occur when converting event data to a transaction map.
Delegates to DoubleEntryLedger.Workers.CommandWorker.TransactionCommandResponseHandler.handle_transaction_map_error/3.
Parameters
command_map: The event being processed.error: The error encountered during transaction map conversion.repo: The Ecto repository.
Returns
- An
Ecto.Multithat updates the event with error information.
@spec process(DoubleEntryLedger.Command.t(), Ecto.Repo.t()) :: DoubleEntryLedger.Workers.CommandWorker.success_tuple() | DoubleEntryLedger.Workers.CommandWorker.error_tuple()
Processes an update event by modifying the corresponding transaction.
This function serves as the main entry point for processing update events. It utilizes optimistic concurrency control with retry logic to handle potential conflicts when multiple processes attempt to update the same transaction simultaneously.
Parameters
event: The%Command{}struct with action:updateto process.repo: The Ecto repo to use for database operations (defaults toRepo).
Returns
{:ok, transaction, event}: Successfully processed the update event.{:error, event}: Failed to process the event, with the event containing error details.{:error, changeset}: Failed to update the event status, with changeset containing validation errors.{:error, reason}: Failed to process the event, with reason explaining the failure.
Error Handling
- Handles create events that are still pending.
- Handles optimistic concurrency conflicts with retries.
- Properly marks events as failed with meaningful error messages.
Processes a command with OCC retry logic.
Converts command data to a transaction map, builds an Ecto.Multi, and
retries on Ecto.StaleEntryError up to the configured maximum.
Parameters
occable_item: The command or command map to processrepo: The Ecto repository (defaults toRepo)
Returns
{:ok, %{transaction: Transaction.t(), command_success: Command.t()}}on success{:ok, %{command_failure: Command.t()}}on failureEcto.Multi.failure()on unrecoverable error
@spec retry( module(), DoubleEntryLedger.Occ.Occable.t(), DoubleEntryLedger.Command.ErrorMap.t(), non_neg_integer(), Ecto.Repo.t() ) :: {:ok, %{ transaction: DoubleEntryLedger.Transaction.t(), command_success: DoubleEntryLedger.Command.t() }} | {:ok, %{command_failure: DoubleEntryLedger.Command.t()}} | Ecto.Multi.failure()
Finalizes when retry attempts are exhausted.
Invokes Occable.timed_out/3 to mark the item as timed out, merges in
handle_occ_final_timeout/2, then runs one last transaction.
Parameters
module- the processor moduleoccable_item- the item that timed outerror_map- the accumulated errors and retry countrepo- the Ecto repo
Returns
- The result of the final
repo.transaction/1