pub struct Lifecycle { /* private fields */ }Expand description
The shared, cloneable lifecycle handle. One is created per server; the accept loop consults it per connection/request and an orchestrator flips readiness / requests drain through it.
Implementations§
Source§impl Lifecycle
impl Lifecycle
Sourcepub fn new(config: LifecycleConfig) -> Lifecycle
pub fn new(config: LifecycleConfig) -> Lifecycle
Create a lifecycle from config. The server starts NOT ready by default
— an orchestrator calls Lifecycle::set_ready once dependencies are
wired — EXCEPT the plain-serve config, whose readiness the entry sets to
true up front (there is no orchestrator on that path).
Sourcepub fn config(&self) -> &LifecycleConfig
pub fn config(&self) -> &LifecycleConfig
The config this lifecycle runs under (for the accept loop’s timeout / body cap / correlation-id policy).
Sourcepub fn set_ready(&self, ready: bool)
pub fn set_ready(&self, ready: bool)
Flip the readiness gate. false → new requests are shed with 503
(load balancers stop routing); true → traffic is served. Independent
of liveness (the loop stays up either way).
Sourcepub fn is_ready(&self) -> bool
pub fn is_ready(&self) -> bool
Whether the server is currently serving traffic (ready and not draining).
Sourcepub fn is_draining(&self) -> bool
pub fn is_draining(&self) -> bool
Whether a graceful drain is in progress.
Sourcepub fn admit(&self) -> Admission
pub fn admit(&self) -> Admission
THE admission decision — the one law both tiers apply per request:
- draining or not ready →
Admission::NotReady(503, no dispatch); - all slots busy →
Admission::Overloaded(503, promptly, no queue); - otherwise →
Admission::Admitholding a slot for the handler’s run.
try_acquire (never .await) is the backpressure keystone: admission
never blocks the accept loop, so an over-capacity flood is shed, not
buffered into a hang.
Sourcepub fn inflight(&self) -> usize
pub fn inflight(&self) -> usize
How many in-flight slots are currently occupied (a handler is running).
Sourcepub fn correlation_id(&self, client_supplied: Option<&str>) -> String
pub fn correlation_id(&self, client_supplied: Option<&str>) -> String
The correlation id for a response: the client’s X-Correlation-Id
(verbatim, when present and non-empty) else a freshly assigned one. Two
concurrent no-id requests get DISTINCT ids (the counter is atomic).
Sourcepub fn assign_correlation_id(&self) -> String
pub fn assign_correlation_id(&self) -> String
Assign a fresh, unique correlation id (monotonic counter + per-process nonce) — cheap and non-blocking, no RNG on the hot path.
Sourcepub fn drain_signal(&self) -> Arc<Notify>
pub fn drain_signal(&self) -> Arc<Notify>
The signal the accept loop select!s on so drain can stop it. Pinged
exactly once by Lifecycle::drain; combined with the is_draining
flag check in the loop, a stop can never be missed.
Sourcepub fn notify_slot_freed(&self)
pub fn notify_slot_freed(&self)
Call when a slot frees (a SlotGuard dropped) so a pending drain waiter
re-checks the in-flight count promptly rather than polling.
Sourcepub async fn drain(&self, deadline: Duration) -> DrainOutcome
pub async fn drain(&self, deadline: Duration) -> DrainOutcome
Begin a GRACEFUL drain and wait up to deadline for in-flight requests
to finish. Flips the draining flag (the accept loop stops taking new
connections; new requests are shed with 503), then awaits in-flight →
zero OR the deadline, returning the still-running count at the deadline
as DrainOutcome::dropped. Never hangs past deadline.
Source§impl Lifecycle
impl Lifecycle
Sourcepub fn probe_response(&self, path: &str) -> Option<HttpResponse>
pub fn probe_response(&self, path: &str) -> Option<HttpResponse>
The answer a configured probe path owes, or None when the path is the
program’s own.
Called BEFORE admission, so a probe is never shed by backpressure and never
consumes a slot — a monitor asking “are you alive” during an overload must
get an answer, not the overload. Readiness reports whether this server wants
traffic right now (503 once draining, so a load balancer stops sending
while in-flight work finishes); liveness reports only that the process is
answering, and deliberately stays 200 through a drain, because a draining
server is healthy and killing it would abandon the requests it is finishing.
Both paths are opt-in. With neither configured this returns None for every
path, so no route is taken away from the program and the byte-for-byte
cross-tier differential is unperturbed.