AuroraMeter.Schema.CreditBalance (Aurora Meter v1.0.0)

View Source

A tenant's prepaid credit balance, one row per tenant, in micro-dollars (1e-6 USD; see AuroraMeter.Credits.Money).

  • balance: everything granted minus everything settled, debited or expired; signed, because a settlement may exceed its hold.
  • held: the sum of pending holds; balance - held is what AuroraMeter.Credits.available/1 returns.
  • promotional: the part of balance that came from promotional grants; consumed before paid credit and the only part that can expire.
  • low_balance_threshold: per-tenant override of :credits_low_balance_threshold.
  • debt: executed cost the wallet could not fund, recorded rather than hidden. Every incoming grant repays it before creating availability, and no hold or debit may spend while it is outstanding.
  • expired: value destroyed by expiry, kept apart from value spent so the two are never confused.
  • lots_enabled_at: nil means the legacy writer owns this wallet. Non-nil means AuroraMeter.Credits.Allocator does, and the balance row is a checked projection of the wallet's lots rather than an independent source of truth. It is read under the row's own FOR UPDATE lock, which is what stops the two writers ever running together on one wallet.
  • projection_checked_at: stamped by every successful conservation check.
  • low_balance_crossing_id: the persisted identity of the current low-balance crossing (written by build unit 06c).

The row is only ever changed by the AuroraMeter.Credits ledger under a FOR UPDATE lock, alongside an AuroraMeter.Schema.CreditTransaction.

Summary

Functions

Builds a changeset for a balance row.

Types

t()

@type t() :: %AuroraMeter.Schema.CreditBalance{
  __meta__: term(),
  balance: term(),
  currency: term(),
  debt: term(),
  expired: term(),
  held: term(),
  id: term(),
  inserted_at: term(),
  lots_enabled_at: term(),
  low_balance_crossing_id: term(),
  low_balance_threshold: term(),
  projection_checked_at: term(),
  promotional: term(),
  tenant_key: term(),
  updated_at: term()
}

Functions

changeset(balance, attrs)

@spec changeset(t(), map()) :: Ecto.Changeset.t()

Builds a changeset for a balance row.

The four >= 0 validations mirror the CHECK constraints schema version 9 put on the table. Until then the changeset was the only thing asserting them and nothing enforced them on a row the ledger wrote directly (finding X183), so a lost row lock would have been silent corruption rather than a refused write.