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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//! Graceful shutdown coordination.
//!
//! Draining a grpc-webnext server means four different things on four surfaces, so rather
//! than a per-surface mechanism there is one primitive here that all of them share: a
//! broadcast *"start draining"* signal, plus a liveness token every live connection holds
//! until it is finished.
//!
//! * **Fetch / native gRPC** — hyper's own `graceful_shutdown`: HTTP/2 sends `GOAWAY`,
//! HTTP/1 stops reading new requests; in-flight requests still complete.
//! * **h2ts tunnels (in-process)** — the same thing, because the server owns the inner
//! HTTP/2 connection: a real `GOAWAY` down the tunnel.
//! * **Custom-`Frame` WebSockets** — a socket carries exactly one stream, so "stop
//! accepting new streams" is "close the ones that have not opened one yet"; a socket with
//! a live stream runs to its terminal frame, which closes the socket anyway.
//! * **h2ts tunnels (proxy)** — byte-transparent, so there is no `GOAWAY` to inject without
//! parsing the traffic the proxy exists not to parse. Those run until the caller's
//! deadline.
//!
//! The token is what makes "wait for the last one" work without a registry: every task that
//! matters holds a [`crate::Runtime`], which holds a [`Drain`], which holds an
//! `mpsc::Sender`. When the last one drops, the controller's `recv()` resolves.
use ;
/// The drain handle carried by every connection (inside [`crate::Runtime`]).
pub
/// The server side of the drain: starts it, then waits for the last connection.
pub
/// Build a linked (controller, handle) pair.
pub
/// Drive a hyper connection to completion, asking it to shut down gracefully — `GOAWAY` on
/// HTTP/2, no-more-requests on HTTP/1 — as soon as draining starts. In-flight requests still
/// finish; only *new* ones are refused. Evaluates to the connection's `Result`.
///
/// This is a macro rather than a generic `fn` on purpose. Written as
/// `fn serve<C: GracefulConnection>(…) -> impl Future`, the body's `async` block makes the
/// compiler try to prove `From<Box<dyn Error + Send + Sync + '_>>` for *every* lifetime,
/// which does not hold — so it does not compile. (hyper-util dodges this by hand-writing a
/// `Future` impl rather than using an `async` block.) Expanding at the call site keeps the
/// connection type concrete and sidesteps the inference entirely.
pub use serve_graceful;