updateBalance updates a balance entry in the database. This function handles the logic of updating all balance-related fields while ensuring data consistency using optimistic locking. The version field is incremented after a successful update to maintain control over concurrent modifications. Param
(ctx context.Context, tx *sql.Tx, balance *model.Balance)
| 879 | // Returns: |
| 880 | // - error: Returns an error if the update operation fails at any point, including issues with metadata marshalling, query execution, or optimistic locking. |
| 881 | func updateBalance(ctx context.Context, tx *sql.Tx, balance *model.Balance) error { |
| 882 | // SQL query to update the balance |
| 883 | query := ` |
| 884 | UPDATE ledgerforge.balances |
| 885 | SET balance = $2, credit_balance = $3, debit_balance = $4, inflight_balance = $5, inflight_credit_balance = $6, inflight_debit_balance = $7, currency = $8, currency_multiplier = $9, ledger_id = $10, created_at = $11, version = version + 1 |
| 886 | WHERE balance_id = $1 AND version = $12 |
| 887 | ` |
| 888 | |
| 889 | // Execute the update query within the provided transaction context |
| 890 | result, err := tx.ExecContext(ctx, query, balance.BalanceID, balance.Balance.String(), balance.CreditBalance.String(), balance.DebitBalance.String(), balance.InflightBalance.String(), balance.InflightCreditBalance.String(), balance.InflightDebitBalance.String(), balance.Currency, balance.CurrencyMultiplier, balance.LedgerID, balance.CreatedAt, balance.Version) |
| 891 | if err != nil { |
| 892 | // Return an error if the query execution fails |
| 893 | return apierror.NewAPIError(apierror.ErrInternalServer, "Failed to update balance", err) |
| 894 | } |
| 895 | |
| 896 | // Check if any rows were affected by the update |
| 897 | rowsAffected, err := result.RowsAffected() |
| 898 | if err != nil { |
| 899 | // Return an error if unable to get affected rows |
| 900 | return apierror.NewAPIError(apierror.ErrInternalServer, "Failed to get rows affected", err) |
| 901 | } |
| 902 | |
| 903 | // If no rows were updated, return an optimistic locking error |
| 904 | if rowsAffected == 0 { |
| 905 | return apierror.NewAPIError(apierror.ErrConflict, fmt.Sprintf("Optimistic locking failure: balance with ID '%s' may have been updated or deleted by another transaction", balance.BalanceID), nil) |
| 906 | } |
| 907 | |
| 908 | // Increment the version number after a successful update |
| 909 | balance.Version++ |
| 910 | |
| 911 | // Return nil indicating a successful update |
| 912 | return nil |
| 913 | } |
| 914 | |
| 915 | func updateBalanceSet(ctx context.Context, tx *sql.Tx, balances []*model.Balance) error { |
| 916 | seen := make(map[string]struct{}, len(balances)) |
no test coverage detected