Documentation
¶
Overview ¶
Package queryadmission bounds the aggregate concurrency of the goroutine-fanning phases of object search on a single node, so a traffic spike degrades gracefully instead of exhausting the Go scheduler.
It gates Shard.ObjectSearch when a filter or keyword ranking is present and the whole of Shard.ObjectVectorSearch. A grant is taken per shard searched on this node, since each shard search runs its own worker pool. Filtered aggregations and batch-delete-by-filter are not yet gated. The grant seeds entities/concurrency's per-query budget, which bounds one query's fan-out while this bounds the aggregate across queries.
The limiter owns no goroutines; all coordination is a mutex plus per-waiter buffered channels.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrOverloaded = errors.New("query admission: node overloaded, request shed (429)")
ErrOverloaded is returned by Admit when the node and wait queue are both full. Ingress maps it to HTTP 429 / gRPC ResourceExhausted.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Capacity is the goroutine-equivalent budget shared by all admitted queries.
Capacity int
// MaxQueue is how many queries may wait for capacity before arrivals are shed.
MaxQueue int
// Disabled is a live kill switch; nil reads as false (enabled). Flipping it
// on does not wake parked waiters (DynamicValue has no change hook); they
// drain via normal releases or ctx cancellation, and since new arrivals
// bypass admission the queue never re-fills.
Disabled *configRuntime.DynamicValue[bool]
}
Config configures a Limiter. The zero value is valid; <=0 fields resolve to the defaults in New.
type Limiter ¶
type Limiter struct {
// contains filtered or unexported fields
}
Limiter is a node-level query admission controller, safe for concurrent use.
Nesting: same-node re-entrant admits inherit the parent's grant (admissionKey), so they can't deadlock locally. A grant IS held while fanning out to a REMOTE node's admission; liveness there rests on the bounded wait queue, the coordinator's bounded retry backoff, and request deadlines, not on releasing the grant, so the cost is latency, not deadlock.
func New ¶
func New(reg prometheus.Registerer, cfg Config) *Limiter
New builds a Limiter and registers its metrics with reg (may be a noop).
func (*Limiter) Admit ¶
Admit acquires a share of the node's query budget for the caller.
On success it returns a ctx seeded with the grant (and a re-entrancy marker) and an idempotent release func that must be called exactly once. It returns ErrOverloaded if the node and wait queue are both full, or the ctx error if ctx is/becomes done before a grant.
Admit is nil-receiver-safe: a nil Limiter, disabled limiter, or re-entrant call all return the ctx unchanged and a no-op release. Production always wires a limiter; this exists purely so tests can skip it.