1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//! Rolling-deploy drain gate (multi-instance-ha A9).
//!
//! Before this existed the two serve paths disagreed: TLS stopped accepting
//! the instant a signal arrived (LB still routing here → connection refused),
//! while plain HTTP kept accepting for the whole drain window but never told
//! the LB anything — `/readyz` stayed 200 throughout. Both now share one
//! sequence: withdraw readiness first, keep serving while the LB reacts,
//! then stop accepting and drain in-flight work.
use Future;
use Arc;
use ;
use Duration;
/// Resolves when the server should stop accepting new connections.
///
/// On `shutdown` firing:
/// 1. `ready` flips to `false` immediately — `/readyz` starts returning 503
/// and the load balancer pulls this node from rotation.
/// 2. Accepting and serving continues for `accept_grace` — requests the LB
/// still routes here during its own poll interval must succeed.
/// 3. The future resolves — the caller stops accepting and drains in-flight
/// requests (bounded by `server.shutdown_force_timeout_secs`).
///
/// The shutdown trigger is a generic future (not hardwired to process
/// signals) so tests can drive the sequence with a channel.
pub async