ecluse:ecluse-core
Safe HaskellNone
LanguageGHC2021

Ecluse.Core.Registry.Maintenance.Budget

Description

The request capacity a maintenance store runs under: the pool a backend declares, what one cycle spent against it, and the gate each request passes through. Ecluse.Core.Registry.Sweep.Pacing decides the rate. Nothing here decides one.

Synopsis

What a backend declares

data QuotaScope Source #

The capacity pool a store's requests debit, which several stores can share.

mkQuotaScope :: Text -> QuotaScope Source #

Build a scope, folding case and surrounding space so two spellings of one pool are one pool.

renderQuotaScope :: QuotaScope -> Text Source #

The scope as an audit line names it.

data QuotaDimension Source #

One pool a backend meters its callers by. The arms are pool shapes rather than one vendor's API names, so each backend maps its own calls onto them.

Constructors

NameListing

Calls that list a store's package names.

VersionListing

Calls that list one package's versions.

AccountReads

Requests the backend counts as reads of the account holding the store.

AccountWrites

Requests the backend counts as writes to that account.

TokenReads

Requests sharing the ceiling of one authentication token.

StoreRequests

The single undivided request capacity of a backend that publishes no other pool.

parseQuotaDimension :: Text -> Maybe QuotaDimension Source #

Read a configured dimension, refusing a spelling this build meters nothing under.

data QuotaOrigin Source #

Where a scope's quota numbers came from, which the boot line reports.

Constructors

QuotaDocumented

The backend's published defaults, which no call discovered.

QuotaDeclared

The operator declared them, for a backend that publishes none.

QuotaDerived

Derived from the sweep's own package pace, for a backend that publishes none.

QuotaUndeclared

Neither, as the backend leaf hands the budget over before the boot resolves it.

data StoreBudget Source #

One store's capacity: the pool it shares, its per-second quotas, and what each request costs.

Constructors

StoreBudget 

Fields

undeclaredBudget :: StoreBudget Source #

A store whose backend publishes no capacity and whose operator declared none. Its cycles are paced by the sweep's own pauses alone.

budgetDeclared :: StoreBudget -> Bool Source #

Whether anything bounds this store's request rate.

narrowestBudget :: StoreBudget -> StoreBudget -> StoreBudget Source #

Combine two descriptions of one pool: the tightest quota per dimension and the dearest cost per request kind, so two stores sharing a pool are paced by the narrower of what each claims.

smallestQuota :: StoreBudget -> Maybe Rational Source #

The tightest quota in the pool, which the default budget fraction is derived from.

renderStoreBudget :: StoreBudget -> Text Source #

The resolved capacity as the boot line records it, naming where each number came from.

renderRates :: Map QuotaDimension Rational -> Text Source #

Every dimension's rate as a boot or audit line spells them, in dimension order. An empty map renders as the empty string, so a caller with a "none" to say says it itself.

toHundredths :: Rational -> Double Source #

A rational as a line spells it, rounded to whole hundredths. A budget fraction and a rate are both reported this way, so a line never carries an unbounded expansion.

What a cycle spends

data RequestKind Source #

One request a cycle makes against the store being dredged.

Constructors

ListingPage

One page of the store's package-name listing.

VersionPage

One enumeration of a package's versions.

ManifestRead

One read of a package's metadata back from the store.

DeleteBatch

One destructive call, whatever number of versions the backend takes in it.

PermissionRead

One read of a standing permission, including a reassessment before a delete.

CursorRead

One read of the walk's resumption marker.

CursorWrite

One write or clearing of that marker.

requestKinds :: [RequestKind] Source #

Every request a cycle can make, held to requestKindName the way quotaDimensions is.

parseRequestKind :: Text -> Maybe RequestKind Source #

Read a configured request kind, refusing a spelling no cycle makes.

oneRequest :: RequestKind -> RequestTally Source #

The tally of a single attempt.

tallyCounts :: RequestTally -> [(RequestKind, Int)] Source #

Every kind the tally counted, beside its count.

renderRequestTally :: RequestTally -> Text Source #

The counts as an audit line reads them.

The rate one scope runs at

data CyclePace Source #

What one request of each kind costs its scope in seconds, at the rate a cycle runs.

paceOf :: Map RequestKind Rational -> CyclePace Source #

Build a pace from the seconds each kind is held to.

The gate and the meter behind it

newtype RequestGate Source #

The gate one store's requests pass through: it counts each one and waits its scope's pace.

Constructors

RequestGate 

Fields

data CycleCost Source #

What one cycle cost: each scope's own attempts, and the time it spent outside budget waits.

Instances

Instances details
Show CycleCost Source # 
Instance details

Defined in Ecluse.Core.Registry.Maintenance.Budget

Eq CycleCost Source # 
Instance details

Defined in Ecluse.Core.Registry.Maintenance.Budget

data BudgetPort Source #

The cycle's own end of the budget: it opens a measurement, reads what the cycle cost, and installs the rate the next cycle's requests wait at.

newBudgetMeter :: (NominalDiffTime -> IO ()) -> IO (BudgetPort, QuotaScope -> RequestGate) Source #

One meter shared by every store a cycle touches, beside the gate each scope's requests pass through. The wait is injected, so a spec reads the pacing without serving it.