Help us shape the future of Go! Take the 2026 Go Developer Survey

limits

package
v1.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 6, 2026 License: AGPL-3.0 Imports: 4 Imported by: 0

Documentation

Overview

Package limits owns the request-rate and consumption vocabulary that bounds what a holder may spend. Both a gateway API key and an account hold limits, so the vocabulary lives here rather than inside either owner.

Index

Constants

View Source
const (
	// IntervalDay selects the fixed UTC day window.
	IntervalDay = "day"
	// IntervalWeek selects the fixed UTC ISO week window.
	IntervalWeek = "week"
	// IntervalMonth selects the fixed UTC month window.
	IntervalMonth = "month"
)

Budget interval names. The values match the fixed UTC aggregation intervals that the usage seam maintains, so a stored budget interval reads one exact aggregate window.

View Source
const CorrectionHorizon = 90 * 24 * time.Hour

CorrectionHorizon bounds new corrections from the original charge settlement. It never expires unresolved reservations or accepted audit evidence.

View Source
const OutstandingJobsPrefix = "limits:v1:outstanding_jobs:"

OutstandingJobsPrefix is the retained account-count namespace. The jobslots repository owns its versioned format and durable claim records.

Variables

View Source
var (
	// ErrInvalidRequestLimit reports a non-positive request limit.
	ErrInvalidRequestLimit = errors.New("request limit must be positive")
	// ErrInvalidRequestWindow reports a non-positive request window.
	ErrInvalidRequestWindow = errors.New("request window seconds must be positive")
	// ErrInvalidBudgetLimit reports a non-positive budget limit.
	ErrInvalidBudgetLimit = errors.New("budget limit must be positive")
	// ErrInvalidBudgetInterval reports an unknown budget interval.
	ErrInvalidBudgetInterval = errors.New("budget interval must be day, week, or month")
	// ErrInvalidStoredBytes reports a non-positive stored byte bound.
	ErrInvalidStoredBytes = errors.New("stored bytes limit must be positive")
	// ErrInvalidOutstandingJobs reports a non-positive outstanding job bound.
	ErrInvalidOutstandingJobs = errors.New("outstanding jobs limit must be positive")
)
View Source
var (
	// ErrCounterRequired reports a meter built without durable storage.
	ErrCounterRequired = errors.New("level counter is required")
	// ErrInvalidHolder reports an empty holder identity.
	ErrInvalidHolder = errors.New("level holder is required")
)
View Source
var ErrBudgetPolicyUnknown = errors.New("budget policy is unknown")

ErrBudgetPolicyUnknown refuses to infer absent budgets from missing policy.

View Source
var ErrCorrectionExpired = errors.New("the settled-charge correction deadline passed")

ErrCorrectionExpired refuses a new correction after its original deadline.

View Source
var ErrOutstandingJobsRecoveryRequired = errors.New("outstanding job ownership requires recovery")

ErrOutstandingJobsRecoveryRequired refuses admission without known ownership.

View Source
var ErrSpendLimitExceeded = errors.New("spend limit exceeded")

ErrSpendLimitExceeded reports work a holder's spend budget cannot pay for.

View Source
var ErrTooManyOutstandingJobs = errors.New("outstanding job limit exceeded")

ErrTooManyOutstandingJobs refuses work beyond the account's current bound.

Functions

func ContextWithAllowance

func ContextWithAllowance(ctx context.Context, allowance Allowance) context.Context

ContextWithAllowance carries one holder's remaining spend into the request.

func ValidInterval

func ValidInterval(interval string) bool

ValidInterval reports whether interval names a supported budget window.

Types

type AdmissionRule added in v1.3.0

type AdmissionRule struct {
	Scope     Scope
	Holder    string
	Revision  uint64
	Dimension Dimension
	Budget    Budget
}

AdmissionRule is one applicable meter and its admitted policy revision.

type Allowance

type Allowance struct {
	// NanoUSD is what remains in the window. It is meaningful only when
	// Bounded is true.
	NanoUSD int64
	// Bounded reports that a spend budget applies to this holder.
	Bounded bool
}

Allowance is what one holder may still spend in its current budget window, in integer nano-USD.

An unbounded allowance is the normal case: most deployments set no spend budget at all, and a holder without one is not metered against anything. Bounded says which of the two a zero means, because a holder with nothing left and a holder with no budget are opposite answers.

func AllowanceFromContext

func AllowanceFromContext(ctx context.Context) Allowance

AllowanceFromContext reads the remaining spend the budget gate recorded.

A request that never passed the gate reads as unbounded. That is the honest answer rather than a permissive default: no budget was found, so no budget refuses anything.

func (Allowance) Covers

func (a Allowance) Covers(nanoUSD int64) error

Covers reports whether the allowance pays for work priced at nanoUSD.

It refuses the work that crosses the bound rather than the work after it. A caller at the door is refused on a window already spent, which lets the crossing request through; here the price is known before the money is spent, so refusing first is both possible and cheaper for the account.

type Budget

type Budget struct {
	Limit    int64  `json:"limit"`
	Interval string `json:"interval"`
	// HistoryID is server-owned accounting continuity. Missing history remains unknown.
	HistoryID string `json:"history_id,omitempty"`
}

Budget bounds one consumption dimension inside one fixed UTC interval.

type BudgetHolder added in v1.3.0

type BudgetHolder struct {
	ID       string
	Revision uint64
	Spend    *Budget
	Tokens   *Budget
}

BudgetHolder contains the consumption policy of one verified holder revision. Nil budgets mean confirmed absence only after the caller verifies that record.

type BudgetPolicy added in v1.3.0

type BudgetPolicy struct {
	// contains filtered or unexported fields
}

BudgetPolicy retains immutable account, key, and optional team consumption policy. The authorization owner constructs it once when accepting the complete bundle.

func NewBudgetPolicy added in v1.3.0

func NewBudgetPolicy(account, key BudgetHolder, team *BudgetHolder) (*BudgetPolicy, error)

NewBudgetPolicy copies all limits from verified policy records. A nil team confirms that the key has no team dependency.

func (*BudgetPolicy) Identity added in v1.3.0

func (p *BudgetPolicy) Identity() (account, key, team string)

Identity returns the original meter populations, including an absent team.

func (*BudgetPolicy) Rule added in v1.3.0

func (p *BudgetPolicy) Rule(index int) (AdmissionRule, bool)

Rule returns a value copy of one meter without copying unrelated account metadata.

func (*BudgetPolicy) RuleCount added in v1.3.0

func (p *BudgetPolicy) RuleCount() int

RuleCount returns how many required meters apply. Zero confirms no budgets.

type BudgetPolicyReader added in v1.3.0

type BudgetPolicyReader interface {
	BudgetPolicy() (*BudgetPolicy, error)
}

BudgetPolicyReader checks the original permission before returning its policy. Child calls inherit this reader. They cannot invent an unlimited default.

type BudgetRule

type BudgetRule struct {
	Scope  Scope
	Budget Budget
}

BudgetRule is one consumption meter a request must satisfy.

func BudgetRules

func BudgetRules(accountLimits, keyLimits *Limits, dimension Dimension) []BudgetRule

BudgetRules returns every consumption meter one request must satisfy for one dimension, account before key.

func TeamBudgetRule added in v1.2.0

func TeamBudgetRule(budget *TeamBudget) (BudgetRule, bool)

TeamBudgetRule projects a stored team budget into the consumption rule the enforcement path runs beside the account and key rules. It reports false when the team sets no budget.

type Dimension

type Dimension string

Dimension names which consumption budget a rule meters.

const (
	// DimensionSpend meters integer nano-USD spend.
	DimensionSpend Dimension = "spend"
	// DimensionTokens meters total token consumption.
	DimensionTokens Dimension = "token"
)

type LevelRule

type LevelRule struct {
	Scope Scope
	Limit int64
}

LevelRule is one level bound a call must satisfy, and the holder that set it.

type Limits

type Limits struct {
	// Requests overrides the global request window for this holder.
	Requests *RequestLimit `json:"requests,omitempty"`
	// Spend bounds integer nano-USD spend inside one fixed UTC interval.
	Spend *Budget `json:"spend,omitempty"`
	// Tokens bounds total token consumption inside one fixed UTC interval.
	Tokens *Budget `json:"tokens,omitempty"`
	// StoredBytes bounds how many bytes this holder keeps in file storage at
	// one time. It is a level rather than a rate, so no interval resets it: a
	// write raises the total and a delete lowers it.
	StoredBytes *int64 `json:"stored_bytes,omitempty"`
	// OutstandingJobs bounds how many jobs this holder may have running at
	// one time. Like StoredBytes it is a level rather than a rate, and unlike
	// every other limit here it meters work that has not finished: a submitted
	// job is a spend commitment this gateway cannot read yet.
	OutstandingJobs *int64 `json:"outstanding_jobs,omitempty"`
}

Limits carries the request-rate override and the consumption budgets of one holder. A nil field leaves that dimension unlimited by this holder.

func (*Limits) Clone

func (l *Limits) Clone() *Limits

Clone returns a deep copy of the limits.

func (*Limits) IsZero

func (l *Limits) IsZero() bool

IsZero reports whether no limit dimension is set.

func (*Limits) Validate

func (l *Limits) Validate() error

Validate checks the limits invariants.

func (*Limits) WithBudgetHistory added in v1.3.0

func (l *Limits) WithBudgetHistory(previous *Limits) *Limits

WithBudgetHistory ignores caller-supplied history identifiers and preserves continuity only for a budget that keeps its original interval.

type OutstandingJobsRule

type OutstandingJobsRule = LevelRule

OutstandingJobsRule is one outstanding job bound a submission must satisfy.

func TightestOutstandingJobs

func TightestOutstandingJobs(accountLimits, keyLimits *Limits) (OutstandingJobsRule, bool)

TightestOutstandingJobs reports the outstanding job bound a submission must satisfy, and whether one applies at all.

It resolves the same way stored bytes do, and for the same reason. A job belongs to an account, so both bounds read one counter and the smaller of them satisfies the larger. A key bound is an operator asking that this key not fill the account's queue on its own.

type RequestLimit

type RequestLimit struct {
	Limit         int64 `json:"limit"`
	WindowSeconds int64 `json:"window_seconds"`
}

RequestLimit is one request-rate override.

type RequestRule

type RequestRule struct {
	Scope Scope
	Limit RequestLimit
}

RequestRule is one request-rate meter a request must satisfy.

func RequestRules

func RequestRules(accountLimits, keyLimits *Limits, deploymentDefault *RequestLimit) []RequestRule

RequestRules returns every request-rate meter one request must satisfy, account before key. deploymentDefault is the gateway's global window; it applies at key scope only when the key sets no request limit of its own, because an explicit key limit is admin intent about that key. Pass nil when the deployment has no global window.

type Scope

type Scope string

Scope names the holder that set a limit.

const (
	// ScopeAccount is an account-wide limit. It meters every key the account
	// holds, so it is the operator's cap on what the account may spend.
	ScopeAccount Scope = "account"
	// ScopeKey is one gateway API key's own limit.
	ScopeKey Scope = "key"
)
const ScopeTeam Scope = "team"

ScopeTeam is a team-wide limit. It meters every key attributed to the team.

type StoredBytesRule

type StoredBytesRule = LevelRule

StoredBytesRule is one stored byte bound an upload must satisfy.

func TightestStoredBytes

func TightestStoredBytes(accountLimits, keyLimits *Limits) (StoredBytesRule, bool)

TightestStoredBytes reports the stored byte bound an upload must satisfy, and whether one applies at all.

Stored bytes resolve to the smaller of the two, which is the opposite of what RequestRules does above, and for a reason the shapes of the two meters give. A request rate meters two different populations, so both meters have to run. Stored bytes meter one: a file belongs to an account, and a key holds no bytes of its own. Both bounds therefore read the same counter, and running the smaller one satisfies the larger by arithmetic.

A key bound is an operator asking that this key not push the account past a tighter number than the account's own. The returned scope names which holder set the bound, so a refusal can name the owner an operator has to talk to.

type TeamBudget added in v1.2.0

type TeamBudget struct {
	Limit    int64  `json:"limit"`
	Interval string `json:"interval"`
	// HistoryID identifies continuous accounting independently of policy revisions.
	HistoryID string `json:"history_id,omitempty"`
}

TeamBudget bounds a team's consumption of one dimension inside one fixed UTC interval. It is a distinct named type rather than a bare Budget so the identity seam can carry it without importing the meaning of every other limit dimension a Limits carrier holds.

func (*TeamBudget) Clone added in v1.2.0

func (b *TeamBudget) Clone() *TeamBudget

Clone returns a deep copy of the team budget.

func (*TeamBudget) Validate added in v1.2.0

func (b *TeamBudget) Validate() error

Validate checks the team budget invariants.

func (*TeamBudget) WithBudgetHistory added in v1.3.0

func (b *TeamBudget) WithBudgetHistory(previous *TeamBudget) *TeamBudget

WithBudgetHistory gives team policies the same continuity rules as other holders.

Directories

Path Synopsis
Package admission owns permission, capacity, and settlement for paid attempts.
Package admission owns permission, capacity, and settlement for paid attempts.
Package jobslots owns durable outstanding-work claims for videos and batches.
Package jobslots owns durable outstanding-work claims for videos and batches.
Package reservation owns durable budget capacity for individual provider attempts.
Package reservation owns durable budget capacity for individual provider attempts.
Package storedbytes owns durable byte claims and account capacity.
Package storedbytes owns durable byte claims and account capacity.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL