Package-level declarations

Types

Link copied to clipboard
class AdaptiveLimitOptions(val floor: Int = DEFAULT_FLOOR, val interval: Duration = DEFAULT_INTERVAL, val latencyFactor: Double = DEFAULT_LATENCY_FACTOR, val minRise: Duration = DEFAULT_MIN_RISE, val connectionWaits: Int = DEFAULT_CONNECTION_WAITS, val periods: Int = DEFAULT_PERIODS)

How an AdaptiveQueryLimit reads its store's write pressure: a period presses when the appends' 90th percentile latency is above latencyFactor times its baseline and at least minRise above it, or when at least connectionWaits callers wait for a connection; periods pressing periods in a row in which the queries contend halve the limit, down to floor. A period is interval long.

Link copied to clipboard
class AdaptiveQueryLimit(val bulkhead: QueryBulkhead, pressure: WritePressure, val options: AdaptiveLimitOptions = AdaptiveLimitOptions.DEFAULT)

The bulkhead's limit, adapted to its store's write pressure (the writes come first), by additive increase and multiplicative decrease, one evaluate per period. The queries contend in a period when the limit held one back (it waited or was refused), or when it ends with queries waiting or running at the limit.

Link copied to clipboard
class AdaptiveQueryLimits(val limits: List<AdaptiveQueryLimit>, interval: Duration = AdaptiveLimitOptions.DEFAULT_INTERVAL, context: CoroutineContext = Dispatchers.Default) : AutoCloseable

Evaluates every one of limits each interval, from start to close. An evaluation that fails is logged; the next one runs all the same.

Link copied to clipboard
class AdmittedQuery<out Q : Any>

A query that admission let through, with the entry it ran under, the execution timeout its budget gives and the resolution of every field reference it carries. Only QueryAdmission creates it, so a QueryBackend cannot receive a query that skipped admission.

Link copied to clipboard
class QueryAdmission(aggregateType: AggregateType, filters: List<QueryFilter> = emptyList(), policies: List<QueryPolicy> = emptyList(), entryPolicy: QueryEntryPolicy = QueryEntryPolicy.DEFAULT, authorizer: ReadAuthorizer = ReadAuthorizer.ALLOW_ALL, model: QueryModel = QueryModel.SNAPSHOT)

The one admission pipeline of an aggregate type's queries: it turns what a caller submitted into the AdmittedQuery a QueryBackend may execute, in the fixed order of the design (§5.4):

Link copied to clipboard
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.

Link copied to clipboard
class QueryBulkhead(val store: String, val maxConcurrent: Int, val maxWait: Duration = DEFAULT_MAX_WAIT, val maxQueued: Int = maxConcurrent * DEFAULT_QUEUE_FACTOR, val ceiling: Int = maxConcurrent)

How many queries one store runs at once: the queries of the snapshots and the events of every aggregate type on the store share it, whichever entry asks, so a burst of list queries cannot take every connection of a pool the store's appends draw from. A query beyond the limit waits briefly: in a FIFO queue of at most maxQueued queries, for at most maxWait, for a permit to free up; it fails with QueryBusyException (wow.query.busy, 429 with Retry-After) when the queue is full (at once) or the wait runs out, as a command beyond the node's in-flight limit is wow.command.busy. A maxWait of zero or a maxQueued of zero refuses at once. A caller cancelled while it waits leaves its queue slot and takes no permit.

Link copied to clipboard

A read QueryTargets refuses: the scope or the tenants it names.

Link copied to clipboard
class QueryTargets(tenants: TenantPolicy = TenantPolicy.CALLERS, crossTenant: Boolean = false)

Where a read decides the tenant and scope its caller reads in: the one home of the read side's scope authorization, which every edge asks instead of deciding it itself. A query route, a state read and the dataset listing all read through of.