AuroraMeter. Entitlements
(Aurora Meter v0.3.1)
View Source
Plan resolution and the entitlement gate.
Semantics (see plan.md D12): a :hard limit blocks at its cap; a :metered
feature is always allowed (overage is billed); a {:feature, false} is denied;
an undeclared feature is permissive. with_quota/4 reserves atomically so hard
limits are correct under concurrency, releasing the reservation if the wrapped
function raises.
Plans resolve through AuroraMeter.Subscriptions (cached), and only a
subscription in an entitled status (AuroraMeter.Schema.Subscription.entitled_statuses/0)
grants its plan; anything else gets the default plan.
Summary
Types
Result of an entitlement check.
A dashboard-ready view of one feature's quota. kind is :hard, :metered,
:boolean or :undeclared; limit is set for hard caps, included for
metered allowances; percent is used relative to whichever applies (nil when
neither does).
Functions
Whether check/2 currently returns :ok.
Checks whether tenant may use feature right now.
Whether the tenant's plan grants access to feature at all (ignores quota).
Returns the plan for tenant: its subscription's plan when the subscription is
in an entitled status, else the default plan.
A dashboard-ready snapshot of feature for tenant: kind, usage, cap or
allowance, remaining, overage, percentage and the current period.
Remaining quota for a hard-limited feature, or :unlimited.
Atomically reserves qty of feature against the plan (increments the counter).
Assigns plan_id to tenant locally (no billing provider).
Gates, runs, and meters in one atomic step.
Types
@type check_result() :: :ok | {:error, :limit_exceeded | :not_entitled}
Result of an entitlement check.
@type quota() :: %{ feature: atom(), kind: :hard | :metered | :boolean | :undeclared, enabled: boolean(), used: integer(), limit: non_neg_integer() | nil, included: non_neg_integer() | nil, unit_price: number() | nil, remaining: non_neg_integer() | :unlimited, overage: non_neg_integer(), percent: non_neg_integer() | nil, period: AuroraMeter.Period.t() }
A dashboard-ready view of one feature's quota. kind is :hard, :metered,
:boolean or :undeclared; limit is set for hard caps, included for
metered allowances; percent is used relative to whichever applies (nil when
neither does).
Functions
Whether check/2 currently returns :ok.
@spec check(term(), atom()) :: check_result()
Checks whether tenant may use feature right now.
Whether the tenant's plan grants access to feature at all (ignores quota).
@spec plan(term()) :: AuroraMeter.Plan.t() | nil
Returns the plan for tenant: its subscription's plan when the subscription is
in an entitled status, else the default plan.
A dashboard-ready snapshot of feature for tenant: kind, usage, cap or
allowance, remaining, overage, percentage and the current period.
@spec remaining(term(), atom()) :: non_neg_integer() | :unlimited
Remaining quota for a hard-limited feature, or :unlimited.
@spec reserve(term(), atom(), pos_integer()) :: :ok | {:error, :limit_exceeded | :not_entitled}
Atomically reserves qty of feature against the plan (increments the counter).
@spec subscribe(term(), atom() | String.t()) :: {:ok, AuroraMeter.Schema.Subscription.t()} | {:error, Ecto.Changeset.t()}
Assigns plan_id to tenant locally (no billing provider).
@spec with_quota(term(), atom(), (-> result)) :: {:ok, result} | {:error, term()} when result: term()
Gates, runs, and meters in one atomic step.
Reserves qty of feature; if allowed, runs fun and returns {:ok, result}
(the reservation is the usage). If the reservation is denied, returns
{:error, reason} without running fun. If fun raises, the reservation is
released and the error re-raised.
@spec with_quota(term(), atom(), pos_integer(), (-> result)) :: {:ok, result} | {:error, term()} when result: term()