ecluse:ecluse-core
Safe HaskellNone
LanguageGHC2021

Ecluse.Core.Server.Admission

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

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.