8080//! [`AsyncWrite`]: tokio::io::AsyncWrite
8181//! [`Connection`]: Connection
8282use std:: fmt;
83+ use std:: fmt:: { Debug , Formatter } ;
84+ use std:: sync:: atomic:: { AtomicBool , Ordering } ;
85+ use std:: sync:: Arc ;
8386
8487use :: http:: Extensions ;
8588
@@ -113,6 +116,34 @@ pub struct Connected {
113116 pub ( super ) alpn : Alpn ,
114117 pub ( super ) is_proxied : bool ,
115118 pub ( super ) extra : Option < Extra > ,
119+ pub ( super ) poisoned : PoisonPill ,
120+ }
121+
122+ #[ derive( Clone ) ]
123+ pub ( crate ) struct PoisonPill {
124+ poisoned : Arc < AtomicBool > ,
125+ }
126+
127+ impl Debug for PoisonPill {
128+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
129+ // print the address of the pill—this makes debugging issues much easier
130+ write ! ( f, "PoisonPill@{:p} {{ poisoned: {} }}" , self . poisoned, self . poisoned. load( Ordering :: Relaxed ) )
131+ }
132+ }
133+
134+ impl PoisonPill {
135+ pub ( crate ) fn healthy ( ) -> Self {
136+ Self {
137+ poisoned : Arc :: new ( AtomicBool :: new ( false ) ) ,
138+ }
139+ }
140+ pub ( crate ) fn poison ( & self ) {
141+ self . poisoned . store ( true , Ordering :: Relaxed )
142+ }
143+
144+ pub ( crate ) fn poisoned ( & self ) -> bool {
145+ self . poisoned . load ( Ordering :: Relaxed )
146+ }
116147}
117148
118149pub ( super ) struct Extra ( Box < dyn ExtraInner > ) ;
@@ -130,6 +161,7 @@ impl Connected {
130161 alpn : Alpn :: None ,
131162 is_proxied : false ,
132163 extra : None ,
164+ poisoned : PoisonPill :: healthy ( ) ,
133165 }
134166 }
135167
@@ -189,6 +221,16 @@ impl Connected {
189221 self . alpn == Alpn :: H2
190222 }
191223
224+ /// Poison this connection
225+ ///
226+ /// A poisoned connection will not be reused for subsequent requests by the pool
227+ pub fn poison ( & self ) {
228+ self . poisoned . poison ( ) ;
229+ tracing:: debug!(
230+ poison_pill = ?self . poisoned, "connection was poisoned"
231+ ) ;
232+ }
233+
192234 // Don't public expose that `Connected` is `Clone`, unsure if we want to
193235 // keep that contract...
194236 #[ cfg( feature = "http2" ) ]
@@ -197,6 +239,7 @@ impl Connected {
197239 alpn : self . alpn . clone ( ) ,
198240 is_proxied : self . is_proxied ,
199241 extra : self . extra . clone ( ) ,
242+ poisoned : self . poisoned . clone ( ) ,
200243 }
201244 }
202245}
0 commit comments