QueryBudget

class QueryBudget(val label: String, val maxListSize: Int = 1000, val maxPageSize: Int = 100, val maxPageWindow: Long, val maxFilterNodes: Int = DEFAULT_MAX_FILTER_NODES, val maxFilterValues: Int = DEFAULT_MAX_FILTER_VALUES, val allowExpensiveOperators: Boolean = true, val maxResidualGroups: Int = DEFAULT_MAX_RESIDUAL_GROUPS, val countLimit: Int = DEFAULT_COUNT_LIMIT, val allowExactCount: Boolean = false, val timeout: Duration = DEFAULT_TIMEOUT, val unindexedSortExpensive: Boolean = false)

Size limits and expensive-operator gates for one QueryEntry, checked at admission step 0: against the query as the caller submitted it plus the caller's scope from the edge, before any extension rewrites it. A route's selection (what a load route names in its URL), policy conditions, the model's default scope and cursor tie-breakers therefore never count, and a policy may use a gated operator.

A limit of 0 disables that limit. Every rejection is a request QueryViolation whose text label opens, e.g. HTTP page size[0] ....

maxResidualGroups is metered during execution instead: when a storage cannot run an aggregation's HAVING or metric sort natively, the core reads every group to compute it, and fails once more than this many groups arrive.

Counting is bounded: countLimit is the default and the largest limit of a count and the bound of a paged query's BOUNDED total; allowExactCount lets the entry ask for an EXACT total. timeout is the execution timeout of every query of the entry, which the backend receives and the core enforces; Duration.ZERO runs without one.

unindexedSortExpensive treats a sort the storage runs without an index (QueryFieldBinding.indexed false) as an expensive operator, so an entry that refuses expensive operators refuses it too. It is checked once the schema is known, after the query is resolved; the tie-breakers a cursor appends never count. Off by default: a storage grants a sort it can run correctly, indexed or not.

Constructors

Link copied to clipboard
constructor(label: String, maxListSize: Int = 1000, maxPageSize: Int = 100, maxPageWindow: Long, maxFilterNodes: Int = DEFAULT_MAX_FILTER_NODES, maxFilterValues: Int = DEFAULT_MAX_FILTER_VALUES, allowExpensiveOperators: Boolean = true, maxResidualGroups: Int = DEFAULT_MAX_RESIDUAL_GROUPS, countLimit: Int = DEFAULT_COUNT_LIMIT, allowExactCount: Boolean = false, timeout: Duration = DEFAULT_TIMEOUT, unindexedSortExpensive: Boolean = false)

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard

The bound of a paged query's BOUNDED total: countLimit, null when it is 0.

Link copied to clipboard

Functions

Link copied to clipboard
fun check(query: AggregationQuery, scope: FilterExpression = MatchAllFilter)
fun check(query: CountQuery, scope: FilterExpression = MatchAllFilter)
fun check(query: CursorQuery, scope: FilterExpression = MatchAllFilter)
fun check(query: ListQuery, scope: FilterExpression = MatchAllFilter)
fun check(query: PagedQuery, scope: FilterExpression = MatchAllFilter)
fun check(query: SingleQuery, scope: FilterExpression = MatchAllFilter)
Link copied to clipboard
fun checkStream(query: CursorQuery, scope: FilterExpression = MatchAllFilter)

A resumable stream of a list, run as keyset chunks of the server's size: bounded by time and bulkhead permits, not by rows, so neither its limit nor its chunk size is checked, only its filter.

Link copied to clipboard
fun countLimit(query: CountQuery): Int?

The limit a count of query runs with under this budget: the query's own, else countLimit; null counts exactly.

Link copied to clipboard
fun listDefault(default: Int): Int?

The list size applied to a list query that sends none, from the configured default: at most maxListSize, and null (none applied: the list reads every match) when either is 0.