QueryBulkhead
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.
A query holds its permit from the backend call to its end: a streamed list or aggregation until its last row is emitted, or until it fails or its collector cancels it. A paged query that counts its total takes one permit for its page and one for its count, one after the other.
The limit starts at maxConcurrent and may move between 1 and ceiling (limit it to another: an AdaptiveQueryLimit gives way to the store's writes). Lowering it cancels no query: the permits of the queries beyond it are kept back as those queries end. A bulkhead whose ceiling is its maxConcurrent keeps that limit.
Constructors
Properties
Functions
Takes a permit: at once when one is free, else after waiting in the queue at most maxWait, or fails with QueryBusyException. The semaphore hands a released permit to the longest waiter (FIFO) and gives it back when that waiter was cancelled meanwhile. Each permit taken is given back with one release: a caller that reads in chunks may give it back between two and take it again, so a lowered limit applies to it from its next chunk.
How many queries had to wait or were refused since the last call: whether the limit held anyone back.