.NET API
IQuotaStore
Tracon.Abstractions.dllThe store for quota rules and consumption counters.
public interface IQuotaStoreRemarks
Section titled “Remarks”Two different kinds of data live here: rules (defined by an administrator, change rarely) and counters (increment at the end of every run). Both sit in the same contract because a check always reads them together.
Important: IQuotaStore.AddUsageAsync must be atomic —
the PostgreSQL implementation uses INSERT ... ON CONFLICT DO UPDATE.
Concurrent runs increment the same row and no increment is lost.
Methods
Section titled “Methods”AddUsageAsync(QuotaConsumption, IReadOnlyDictionary<QuotaPeriod, DateOnly>, CancellationToken)
Section titled “ AddUsageAsync(QuotaConsumption, IReadOnlyDictionary<QuotaPeriod, DateOnly>, CancellationToken)”Adds a consumption to both the agent counter and the tenant-wide counter.
ValueTask AddUsageAsync(QuotaConsumption consumption, IReadOnlyDictionary<QuotaPeriod, DateOnly> periodStarts, CancellationToken cancellationToken = default)Parameters
Section titled “Parameters”consumption QuotaConsumption
The consumption.
periodStarts IReadOnlyDictionary<QuotaPeriod, DateOnly>
For each period, the first day of the period the consumption falls into. The caller computes this from the configured time zone; the store does not know time zones.
cancellationToken CancellationToken
The cancellation token.
Returns
Section titled “Returns”The completion task.
Remarks
Section titled “Remarks”The store carries no time zone: the caller computes the period boundary and passes it ready-made. This lets the same store behave correctly for consumers running in different time zones.
DeleteAsync(string, Guid, CancellationToken)
Section titled “ DeleteAsync(string, Guid, CancellationToken)”Deletes a rule.
ValueTask<bool> DeleteAsync(string tenantId, Guid id, CancellationToken cancellationToken = default)Parameters
Section titled “Parameters”tenantId string
The tenant identifier.
id Guid
The rule identifier.
cancellationToken CancellationToken
The cancellation token.
Returns
Section titled “Returns”true if the delete happened.
GetAsync(string, Guid, CancellationToken)
Section titled “ GetAsync(string, Guid, CancellationToken)”Fetches a single rule.
ValueTask<QuotaDefinition?> GetAsync(string tenantId, Guid id, CancellationToken cancellationToken = default)Parameters
Section titled “Parameters”tenantId string
The tenant identifier.
id Guid
The rule identifier.
cancellationToken CancellationToken
The cancellation token.
Returns
Section titled “Returns”The rule; null if it does not exist or belongs to another tenant.
GetUsageAsync(QuotaUsageQuery, CancellationToken)
Section titled “ GetUsageAsync(QuotaUsageQuery, CancellationToken)”Fetches the current period’s counters.
ValueTask<IReadOnlyList<QuotaUsageRecord>> GetUsageAsync(QuotaUsageQuery query, CancellationToken cancellationToken = default)Parameters
Section titled “Parameters”query QuotaUsageQuery
The filter.
cancellationToken CancellationToken
The cancellation token.
Returns
Section titled “Returns”ValueTask<IReadOnlyList<QuotaUsageRecord>>
The counters. An empty list when there is no consumption at all.
ListAsync(string, CancellationToken)
Section titled “ ListAsync(string, CancellationToken)”Lists a tenant’s quota rules.
ValueTask<IReadOnlyList<QuotaDefinition>> ListAsync(string tenantId, CancellationToken cancellationToken = default)Parameters
Section titled “Parameters”tenantId string
The tenant identifier.
cancellationToken CancellationToken
The cancellation token.
Returns
Section titled “Returns”ValueTask<IReadOnlyList<QuotaDefinition>>
The rules.
SaveAsync(QuotaDefinition, CancellationToken)
Section titled “ SaveAsync(QuotaDefinition, CancellationToken)”Saves a rule. Overwrites an existing rule for the same scope (tenant + agent + period), if one already exists.
ValueTask<QuotaDefinition> SaveAsync(QuotaDefinition definition, CancellationToken cancellationToken = default)Parameters
Section titled “Parameters”definition QuotaDefinition
The rule.
cancellationToken CancellationToken
The cancellation token.
Returns
Section titled “Returns”The saved rule.
Remarks
Section titled “Remarks”Scope uniqueness is built over COALESCE(agent_name, ''); a plain
UNIQUE constraint treats NULLs as distinct from each other and
would let the same rule be added an unlimited number of times.
TryClaimThresholdNotificationAsync(string, string, QuotaPeriod, DateOnly, QuotaMetric, int, CancellationToken)
Section titled “ TryClaimThresholdNotificationAsync(string, string, QuotaPeriod, DateOnly, QuotaMetric, int, CancellationToken)”Atomically claims a quota threshold notification for one scope/period, so that only one caller among concurrent workers — and only the first run to reach it across a process restart — proceeds to publish it.
ValueTask<bool> TryClaimThresholdNotificationAsync(string tenantId, string agentName, QuotaPeriod period, DateOnly periodStart, QuotaMetric metric, int thresholdPercent, CancellationToken cancellationToken = default)Parameters
Section titled “Parameters”tenantId string
The tenant identifier.
agentName string
The scope: an agent name, or an empty string ("") for the
tenant-wide counter — the same convention QuotaUsageRecord.AgentName uses.
period QuotaPeriod
The counter’s interval.
periodStart DateOnly
The first day of the period (local time).
metric QuotaMetric
The metric whose threshold was crossed.
thresholdPercent int
The crossed threshold percentage.
cancellationToken CancellationToken
The cancellation token.
Returns
Section titled “Returns”true if this call is the one that claims the threshold — no earlier call claimed it in this period, and the caller should publish the notice. false if it was already claimed (by an earlier run, or a concurrent worker), or the usage row for this scope/period does not exist yet.
Remarks
Section titled “Remarks”The claim survives a process restart: it lives in the same durable row IQuotaStore.AddUsageAsync writes to, not in memory. When the period rolls over, a new row forms and the claim starts clean — there is nothing to reset by hand.