AuroraMeter.Credits.ConservationError exception (Aurora Meter v1.0.0)

View Source

Raised when a wallet's balance row and its credit lots disagree.

Every ledger write on a wallet that has been cut over to lots ends by comparing the row it just wrote against a SUM over that wallet's lots:

balance     = sum(available) + sum(reserved) - debt
held        = sum(reserved)
promotional = sum(available + reserved) over promotional lots
expired     = sum(expired)

When they differ, this is raised rather than returned. A with chain can swallow an error tuple, and a financial invariant breach is the one thing that must never be swallowed: the raise aborts the transaction, so the write that would have been built on a wrong projection is not committed and the wallet is left exactly as it was.

Catching this and continuing is never correct. The wallet is out of service for writes until a human has looked at it, which is the intended trade: a refused write is recoverable and a wrong balance is not. Reads keep working, so the lots and the ledger can both be inspected. Before raising, the ledger emits [:aurora_meter, :credits, :conservation_error] with the four deltas, so an alert fires on the first occurrence rather than on the first complaint.

Summary

Types

t()

@type t() :: %AuroraMeter.Credits.ConservationError{
  __exception__: term(),
  actual: %{required(atom()) => integer()},
  deltas: %{required(atom()) => integer()},
  expected: %{required(atom()) => integer()},
  message: String.t(),
  operation: atom(),
  reference: String.t() | nil,
  tenant_key: String.t()
}