ecluse:ecluse-core
Safe HaskellNone
LanguageGHC2021

Ecluse.Core.Server.Admission.Meter

Description

The metadata memory gate's meter: one byte budget that requests pay into as they read and build.

A request takes a small entry step before its CPU slot and is shed, as a value, when that step does not fit within the admission wait. A started request pays for what it reads one step at a time, and pauses instead of failing when the budget is spent. One ticket at a time holds the overdraw token until its request ends. Work that request waits on, a shared fetch or render, may overdraw on the same token, so the overshoot stays near one request with its shared work, and a pause never deadlocks.

Synopsis

The meter

data MemoryMeter Source #

The process-wide meter. The constructor stays hidden so only the checked operations change it.

data MeterSettings Source #

The boot-time shape of a meter.

Constructors

MeterSettings 

Fields

newMemoryMeter :: MeterSettings -> IO MemoryMeter Source #

Build a meter. The step floors at one byte, and the room and the wait at zero.

steerMeter :: MemoryMeter -> Int -> BrakeLevel -> IO () Source #

Move the budget and record the brake level that moved it. Paused reads and queued entries retry at once.

meterSnapshot :: MemoryMeter -> IO MeterSnapshot Source #

Read the meter's figures without blocking a request.

meterFigures :: MemoryMeter -> STM MeterSnapshot Source #

The meter's figures inside a transaction, so a caller can wait for them to change.

takeLargestCharge :: MemoryMeter -> IO Int Source #

The largest total one ticket reached since the last call, for the sampler alone.

A request's ticket

data MemoryTicket Source #

One request's account with the meter, or a view of it that pays for shared work.

withMemoryEntry :: MonadUnliftIO m => MetricsPort -> MemoryMeter -> (MemoryTicket -> m a) -> m (Maybe a) Source #

Run a request under the meter. Nothing is a shed: the waiting room was full, or the entry step did not fit within the wait. Everything the ticket paid returns on every exit path.

charge :: MemoryTicket -> Int -> IO () Source #

Pay for bytes the request is about to hold, already scaled to their charge.

Shared work

awaitingFlight :: MonadUnliftIO m => MemoryTicket -> FlightKey -> m a -> m a Source #

Mark this request as waiting on a unit of shared work for the length of the action, so the request that does that work may pause and overdraw with this request's priority.

servingFlight :: FlightKey -> MemoryTicket -> MemoryTicket Source #

The same ticket, paying for shared work: its charges carry the priority of every request waiting on it.