tollgate_admission/lib.rs
1//! The per-request admission pipeline.
2//!
3//! The staged path performs, in order:
4//!
5//! 1. snapshot lookup by [`Principal`] (in-memory map, negative-cached),
6//! 2. account status / staleness / permission checks,
7//! 3. batch-cap check and cost quote (direct-indexed table),
8//! 4. request-count and weighted local rate-token consumption (`governor`),
9//! 5. principal and account concurrency acquisition,
10//! 6. lease debit, opening the typed pending state.
11//!
12//! Nothing in this crate performs I/O, takes a blocking lock on the request
13//! path, or reads a wall/business clock for a policy decision: `now` is an
14//! argument. Misses deny — resolution is the background plane's job
15//! (INVARIANTS.md GL-5).
16//!
17//! Two dependencies do their own bookkeeping underneath that, and the budget
18//! counts it rather than pretending it away. `governor` reads its own
19//! monotonic clock for bucket arithmetic. [`MokaSnapshotMap`] reads one too,
20//! and roughly every sixty-fourth lookup its housekeeper takes a
21//! *non-blocking* `try_lock` and drains its read log inline — updating the
22//! frequency sketch, and evicting when the cache is at capacity. Neither is a
23//! source of snapshot or lease truth, and neither can block a request; both
24//! are measured mechanism costs, carried by the `admission/snapshot_lookup_*`
25//! rows and by `moka_reads_stay_within_their_amortized_allocation_budget`.
26//! [`ArcSwapSnapshotMap`] takes no lock on a read at all.
27//!
28//! That prohibition covers logging too, so what this plane reports about
29//! itself is a tally rather than an event stream: every outcome lands in
30//! [`AdmissionCounters`], indexed by reason, and an embedder exports it from
31//! off the request path.
32//!
33//! [`AdmissionEngine::begin`] owns the lookup and returns a generation-pinned
34//! [`RequestContext`]; [`RequestContext::admit`] consumes it after body
35//! decoding without another map lookup.
36//!
37//! Two interchangeable snapshot-map implementations exist behind
38//! [`SnapshotMap`] — [`MokaSnapshotMap`] and [`ArcSwapSnapshotMap`] — because
39//! the design review deliberately treats the cache choice as an empirical
40//! question for the perf gate, not a foregone conclusion.
41
42pub mod capacity;
43pub mod counters;
44pub mod engine;
45pub mod generation_model;
46mod history;
47pub mod maps;
48pub mod state;
49
50pub use capacity::{
51 CapacityConfigError, CapacityEvidence, CapacityGate, CapacityOccupancy, CapacityPermit,
52 ExecutionCapacityGate, ExecutionCapacityMode, ExecutionPermit, NoCapacityPermit, NoGate,
53};
54pub use counters::{AdmissionCounters, CommitRefusal, CountersSnapshot};
55pub use engine::{AdmissionEngine, Committed, Pending, ReadyToStart, Released, RequestContext};
56pub use generation_model::{Watermark, accept_positive, accept_revoked, accept_unknown};
57pub use history::{
58 PublicationError, RefreshBatch, Refreshed, SnapshotHistoryStats, SnapshotRefresh,
59};
60pub use maps::{ArcSwapSnapshotMap, MokaSnapshotMap};
61pub use state::{
62 AccountAdmissionState, LeaseSlot, MapEntry, Principal, PublishableSnapshotUpdate, SnapshotMap,
63 SnapshotUpdate,
64};
65#[doc(inline)]
66pub use tollgate_core::CancelHandle;
67
68// Compiles and runs the README's examples as doctests without adding them to
69// the rendered documentation, so the README cannot drift from the API.
70#[doc = include_str!("../README.md")]
71#[cfg(doctest)]
72pub struct ReadmeDoctests;