66// option. All files in the project carrying such notice may not be copied,
77// modified, or distributed except according to those terms.
88
9- use std:: {
10- fmt,
11- future:: Future ,
12- pin:: Pin ,
13- task:: { Context , Poll } ,
14- } ;
15-
16- use futures_core:: ready;
17- #[ cfg( feature = "tracing" ) ]
18- use {
19- std:: sync:: Arc ,
20- tracing:: { debug_span, Span } ,
21- } ;
9+ use std:: { fmt, future:: poll_fn, task:: Context } ;
2210
2311use crate :: {
2412 conn:: {
@@ -55,35 +43,14 @@ impl fmt::Debug for GetConnInner {
5543 }
5644}
5745
58- /// This future will take connection from a pool and resolve to [`Conn`].
5946#[ derive( Debug ) ]
60- #[ must_use = "futures do nothing unless you `.await` or poll them" ]
61- struct GetConn {
47+ struct GetConnState {
6248 queue_id : QueueId ,
6349 pool : Option < Pool > ,
6450 inner : GetConnInner ,
65- reset_upon_returning_to_a_pool : bool ,
66- #[ cfg( feature = "tracing" ) ]
67- span : Arc < Span > ,
68- }
69-
70- pub ( crate ) async fn get_conn ( pool : Pool ) -> Result < Conn > {
71- let reset_connection = pool. opts . pool_opts ( ) . reset_connection ( ) ;
72- GetConn :: new ( pool, reset_connection) . await
7351}
7452
75- impl GetConn {
76- fn new ( pool : Pool , reset_upon_returning_to_a_pool : bool ) -> GetConn {
77- GetConn {
78- queue_id : QueueId :: next ( ) ,
79- pool : Some ( pool) ,
80- inner : GetConnInner :: New ,
81- reset_upon_returning_to_a_pool,
82- #[ cfg( feature = "tracing" ) ]
83- span : Arc :: new ( debug_span ! ( "mysql_async::get_conn" ) ) ,
84- }
85- }
86-
53+ impl GetConnState {
8754 fn pool_mut ( & mut self ) -> & mut Pool {
8855 self . pool
8956 . as_mut ( )
@@ -97,86 +64,84 @@ impl GetConn {
9764 }
9865}
9966
100- // this manual implementation of Future may seem stupid, but we sort
101- // of need it to get the dropping behavior we want.
102- impl Future for GetConn {
103- type Output = Result < Conn > ;
104-
105- fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
106- #[ cfg( feature = "tracing" ) ]
107- let span = self . span . clone ( ) ;
108- #[ cfg( feature = "tracing" ) ]
109- let _span_guard = span. enter ( ) ;
110- loop {
111- match self . inner {
112- GetConnInner :: New => {
113- let queue_id = self . queue_id ;
114- let next = ready ! ( self . pool_mut( ) . poll_new_conn( cx, queue_id) ) ?;
115- match next {
116- GetConnInner :: Connecting ( conn_fut) => {
117- self . inner = GetConnInner :: Connecting ( conn_fut) ;
118- }
119- GetConnInner :: Checking ( conn_fut) => {
120- self . inner = GetConnInner :: Checking ( conn_fut) ;
121- }
122- GetConnInner :: Done => unreachable ! (
123- "Pool::poll_new_conn never gives out already-consumed GetConns"
124- ) ,
125- GetConnInner :: New => {
126- unreachable ! ( "Pool::poll_new_conn never gives out GetConnInner::New" )
127- }
67+ /// This future will take connection from a pool and resolve to [`Conn`].
68+ #[ cfg_attr( feature = "tracing" , tracing:: instrument( level = "debug" , skip_all) ) ]
69+ pub ( crate ) async fn get_conn ( pool : Pool ) -> Result < Conn > {
70+ let reset_upon_returning_to_a_pool = pool. opts . pool_opts ( ) . reset_connection ( ) ;
71+ let queue_id = QueueId :: next ( ) ;
72+ let mut state = GetConnState {
73+ queue_id,
74+ pool : Some ( pool) ,
75+ inner : GetConnInner :: New ,
76+ } ;
77+
78+ loop {
79+ match state. inner {
80+ GetConnInner :: New => {
81+ let pool = state. pool_mut ( ) ;
82+ let poll_new = |cx : & mut Context < ' _ > | pool. poll_new_conn ( cx, queue_id) ;
83+ let next = poll_fn ( poll_new) . await ?;
84+ match next {
85+ GetConnInner :: Connecting ( conn_fut) => {
86+ state. inner = GetConnInner :: Connecting ( conn_fut) ;
87+ }
88+ GetConnInner :: Checking ( conn_fut) => {
89+ state. inner = GetConnInner :: Checking ( conn_fut) ;
90+ }
91+ GetConnInner :: Done => unreachable ! (
92+ "Pool::poll_new_conn never gives out already-consumed GetConns"
93+ ) ,
94+ GetConnInner :: New => {
95+ unreachable ! ( "Pool::poll_new_conn never gives out GetConnInner::New" )
12896 }
12997 }
130- GetConnInner :: Done => {
131- unreachable ! ( "GetConn::poll polled after returning Async::Ready" ) ;
132- }
133- GetConnInner :: Connecting ( ref mut f) => {
134- let result = ready ! ( Pin :: new( f) . poll( cx) ) ;
135- let pool = self . pool_take ( ) ;
136-
137- self . inner = GetConnInner :: Done ;
138-
139- return match result {
140- Ok ( mut c) => {
141- c. inner . pool = Some ( pool) ;
142- c. inner . reset_upon_returning_to_a_pool =
143- self . reset_upon_returning_to_a_pool ;
144- Poll :: Ready ( Ok ( c) )
145- }
146- Err ( e) => {
147- pool. cancel_connection ( ) ;
148- Poll :: Ready ( Err ( e) )
149- }
150- } ;
151- }
152- GetConnInner :: Checking ( ref mut f) => {
153- let result = ready ! ( Pin :: new( f) . poll( cx) ) ;
154- match result {
155- Ok ( mut c) => {
156- self . inner = GetConnInner :: Done ;
157-
158- let pool = self . pool_take ( ) ;
159- c. inner . pool = Some ( pool) ;
160- c. inner . reset_upon_returning_to_a_pool =
161- self . reset_upon_returning_to_a_pool ;
162- return Poll :: Ready ( Ok ( c) ) ;
163- }
164- Err ( _) => {
165- // Idling connection is broken. We'll drop it and try again.
166- self . inner = GetConnInner :: New ;
98+ }
99+ GetConnInner :: Done => {
100+ unreachable ! ( "GetConn::poll polled after returning Async::Ready" ) ;
101+ }
102+ GetConnInner :: Connecting ( ref mut f) => {
103+ let result = f. await ;
104+ let pool = state. pool_take ( ) ;
105+ state. inner = GetConnInner :: Done ;
106+
107+ return match result {
108+ Ok ( mut c) => {
109+ c. inner . pool = Some ( pool) ;
110+ c. inner . reset_upon_returning_to_a_pool = reset_upon_returning_to_a_pool;
111+ Ok ( c)
112+ }
113+ Err ( e) => {
114+ pool. cancel_connection ( ) ;
115+ Err ( e)
116+ }
117+ } ;
118+ }
119+ GetConnInner :: Checking ( ref mut f) => {
120+ let result = f. await ;
121+ match result {
122+ Ok ( mut c) => {
123+ state. inner = GetConnInner :: Done ;
124+
125+ let pool = state. pool_take ( ) ;
126+ c. inner . pool = Some ( pool) ;
127+ c. inner . reset_upon_returning_to_a_pool = reset_upon_returning_to_a_pool;
128+ return Ok ( c) ;
129+ }
130+ Err ( _) => {
131+ // Idling connection is broken. We'll drop it and try again.
132+ state. inner = GetConnInner :: New ;
167133
168- let pool = self . pool_mut ( ) ;
169- pool. cancel_connection ( ) ;
170- continue ;
171- }
134+ let pool = state. pool_mut ( ) ;
135+ pool. cancel_connection ( ) ;
136+ continue ;
172137 }
173138 }
174139 }
175140 }
176141 }
177142}
178143
179- impl Drop for GetConn {
144+ impl Drop for GetConnState {
180145 fn drop ( & mut self ) {
181146 // We drop a connection before it can be resolved, a.k.a. cancelling it.
182147 // Make sure we maintain the necessary invariants towards the pool.
0 commit comments