AuroraMeter.Storage behaviour (Aurora Meter v0.3.0)

View Source

Behaviour for persisting Aurora Meter state, plus dispatch helpers that route to the configured adapter (AuroraMeter.Config.storage/0, default AuroraMeter.Storage.Ecto).

Only a Postgres/Ecto adapter ships in v1; this behaviour keeps the door open for others without building through it now.

Summary

Types

A counter delta to add: value = value + delta.

A counter snapshot to persist. feature may be an atom or string.

A total as returned after adding deltas. feature is a string.

A raw usage event to persist.

A day-bucket delta to add.

A day bucket as read back: %{date: Date.t(), value: integer()}.

A day-bucket snapshot to persist.

A day-bucket total as returned after adding deltas.

Functions

Adds deltas to counters (value = value + delta, inserting at delta when the row is new) and returns the resulting totals. This is what makes cluster-wide counting correct: each node writes only what it added.

Adds deltas to day buckets and returns the resulting totals. See add_counters/1.

Fetches a tenant's subscription straight from storage (uncached), or nil.

Appends raw usage events (durable mode / audit).

Loads a single flushed counter value, or nil if absent.

Loads a single flushed day-bucket value, or nil if absent.

Loads the flushed day buckets for a feature between two dates (inclusive), oldest first.

Inserts or updates a tenant's subscription (upsert on tenant_key) and evicts it from the subscription cache on every node.

Returns all counter snapshots for a period (used by Pro rollups).

Sets counter snapshots to absolute values by {tenant_key, feature, period_start}. For backfills and test fixtures; the flusher uses add_counters/1 so that nodes add up instead of overwriting one another.

Upserts day-bucket snapshots (absolute values) by {tenant_key, feature, date}.

Types

counter_delta()

@type counter_delta() :: %{
  tenant_key: String.t(),
  feature: atom() | String.t(),
  period_start: DateTime.t(),
  delta: integer()
}

A counter delta to add: value = value + delta.

counter_row()

@type counter_row() :: %{
  tenant_key: String.t(),
  feature: atom() | String.t(),
  period_start: DateTime.t(),
  value: integer()
}

A counter snapshot to persist. feature may be an atom or string.

counter_total()

@type counter_total() :: %{
  tenant_key: String.t(),
  feature: String.t(),
  period_start: DateTime.t(),
  value: integer()
}

A total as returned after adding deltas. feature is a string.

event_row()

@type event_row() :: %{
  :tenant_key => String.t(),
  :feature => atom() | String.t(),
  optional(:quantity) => integer(),
  optional(:metadata) => map()
}

A raw usage event to persist.

history_delta()

@type history_delta() :: %{
  tenant_key: String.t(),
  feature: atom() | String.t(),
  date: Date.t(),
  delta: integer()
}

A day-bucket delta to add.

history_point()

@type history_point() :: %{date: Date.t(), value: integer()}

A day bucket as read back: %{date: Date.t(), value: integer()}.

history_row()

@type history_row() :: %{
  tenant_key: String.t(),
  feature: atom() | String.t(),
  date: Date.t(),
  value: integer()
}

A day-bucket snapshot to persist.

history_total()

@type history_total() :: %{
  tenant_key: String.t(),
  feature: String.t(),
  date: Date.t(),
  value: integer()
}

A day-bucket total as returned after adding deltas.

Callbacks

add_counters(list)

@callback add_counters([counter_delta()]) :: {:ok, [counter_total()]}

add_history(list)

@callback add_history([history_delta()]) :: {:ok, [history_total()]}

get_subscription(t)

@callback get_subscription(String.t()) :: AuroraMeter.Schema.Subscription.t() | nil

insert_events(list)

@callback insert_events([event_row()]) :: :ok

load_counter(t, arg2, t)

@callback load_counter(String.t(), atom() | String.t(), DateTime.t()) :: integer() | nil

load_history(t, arg2, t)

@callback load_history(String.t(), atom() | String.t(), Date.t()) :: integer() | nil

load_history_range(t, arg2, t, t)

@callback load_history_range(String.t(), atom() | String.t(), Date.t(), Date.t()) :: [
  history_point()
]

put_subscription(map)

@callback put_subscription(map()) ::
  {:ok, AuroraMeter.Schema.Subscription.t()} | {:error, Ecto.Changeset.t()}

stream_counters(t)

@callback stream_counters(DateTime.t()) :: [AuroraMeter.Schema.Counter.t()]

upsert_counters(list)

@callback upsert_counters([counter_row()]) :: :ok

upsert_history(list)

@callback upsert_history([history_row()]) :: :ok

Functions

add_counters(rows)

@spec add_counters([counter_delta()]) :: {:ok, [counter_total()]}

Adds deltas to counters (value = value + delta, inserting at delta when the row is new) and returns the resulting totals. This is what makes cluster-wide counting correct: each node writes only what it added.

add_history(rows)

@spec add_history([history_delta()]) :: {:ok, [history_total()]}

Adds deltas to day buckets and returns the resulting totals. See add_counters/1.

get_subscription(tenant_key)

@spec get_subscription(String.t()) :: AuroraMeter.Schema.Subscription.t() | nil

Fetches a tenant's subscription straight from storage (uncached), or nil.

insert_events(rows)

@spec insert_events([event_row()]) :: :ok

Appends raw usage events (durable mode / audit).

load_counter(tenant_key, feature, period_start)

@spec load_counter(String.t(), atom() | String.t(), DateTime.t()) :: integer() | nil

Loads a single flushed counter value, or nil if absent.

load_history(tenant_key, feature, date)

@spec load_history(String.t(), atom() | String.t(), Date.t()) :: integer() | nil

Loads a single flushed day-bucket value, or nil if absent.

load_history_range(tenant_key, feature, from, to)

@spec load_history_range(String.t(), atom() | String.t(), Date.t(), Date.t()) :: [
  history_point()
]

Loads the flushed day buckets for a feature between two dates (inclusive), oldest first.

put_subscription(attrs)

@spec put_subscription(map()) ::
  {:ok, AuroraMeter.Schema.Subscription.t()} | {:error, Ecto.Changeset.t()}

Inserts or updates a tenant's subscription (upsert on tenant_key) and evicts it from the subscription cache on every node.

stream_counters(period_start)

@spec stream_counters(DateTime.t()) :: [AuroraMeter.Schema.Counter.t()]

Returns all counter snapshots for a period (used by Pro rollups).

upsert_counters(rows)

@spec upsert_counters([counter_row()]) :: :ok

Sets counter snapshots to absolute values by {tenant_key, feature, period_start}. For backfills and test fixtures; the flusher uses add_counters/1 so that nodes add up instead of overwriting one another.

upsert_history(rows)

@spec upsert_history([history_row()]) :: :ok

Upserts day-bucket snapshots (absolute values) by {tenant_key, feature, date}.