| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Ecluse.Core.Server.Admission
Contents
Description
Brief-wait admission control for metadata-bearing serve work: the unit-slot instance of the shared Ecluse.Core.Server.Admission.Weighted core (weight one, room equal to the capacity).
The handle caps concurrent operations and retains a bounded room of waiters, so this
bounds aggregate metadata residency by construction while absorbing a burst that merely
brushes the cap: near-capacity load degrades into short queueing delay rather than a
refusal the client immediately retries. The door discipline, the fairness properties,
and the mask reasoning that keeps a slot from leaking between acquisition and the
protected run all live in the core; this module supplies only the unit weight and the
serve-path metric hooks (the in-flight gauge and the queued signal). A refused request
is silently Nothing here: the serve path records its unavailability itself.
Synopsis
- data ServeAdmission
- newServeAdmission :: Int -> IO ServeAdmission
- withServeAdmission :: MonadUnliftIO m => MetricsPort -> ServeAdmission -> m a -> m (Maybe a)
- serveAdmissionWaitMicros :: Int
- newServeAdmissionTuned :: Int -> Int -> Int -> IO ServeAdmission
Documentation
data ServeAdmission Source #
A process-wide serve admission handle. The constructor is hidden so only the checked acquire/wait/release operations can mutate its capacity and waiting room.
newServeAdmission :: Int -> IO ServeAdmission Source #
Allocate a bounded handle with the given positive capacity, a waiting room of the
same size, and the serveAdmissionWaitMicros budget.
The room equals the capacity so a burst of twice the cap is absorbed as brief queueing while anything deeper still gets the instant, cheap refusal -- bounding both waiting memory and worst-case latency. Configuration parsing enforces the positive-capacity precondition; the unchecked integer stays at this internal composition boundary so every request pays only an STM transaction, not another validation step.
withServeAdmission :: MonadUnliftIO m => MetricsPort -> ServeAdmission -> m a -> m (Maybe a) Source #
Run an action within the admission bound. Nothing means the request was refused
-- the waiting room was full, or no slot freed within the wait budget -- and the caller
should shed it.
A request that had to wait records ecluse.serve.admission.queued on admission, so the
queue's work is visible beside the in-flight gauge and the shed decisions.
Inlined so the literal AdmissionObservers folds into the shared core's saturated call
at each request site, leaving no per-request record allocation on the admitted hot path.
serveAdmissionWaitMicros :: Int Source #
How long an operation finding the cap busy waits for a slot before it is refused:
the shared admissionWaitMicros budget, equal to the shed path's Retry-After: 1 hint.
Internals exported for testing
newServeAdmissionTuned :: Int -> Int -> Int -> IO ServeAdmission Source #
Allocate a bounded handle with an explicit waiting-room bound and wait budget
(microseconds), so a test can exercise the queueing behaviour without real-second
sleeps. Production goes through newServeAdmission, which fixes both from the capacity;
a room of zero reproduces pure acquire-or-refuse admission.