Skip to content

Commit 99cc739

Browse files
Markus WesterlindMarwes
Markus Westerlind
authored andcommitted
refactor: Avoid using async fn so &self does not get captured
Avoids rust-lang/rust#63778
1 parent 1562fe2 commit 99cc739

File tree

8 files changed

+148
-132
lines changed

8 files changed

+148
-132
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ tokio-net = "0.2.0-alpha.2"
2727
[features]
2828
default = [ "geospatial" ]
2929

30+
executor = []
3031
geospatial = []
3132

3233
[dev-dependencies]

src/aio.rs

Lines changed: 66 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use tokio::net::tcp::TcpStream;
1414
use tokio::sync::{mpsc, oneshot};
1515

1616
use futures::{
17-
future::Either,
1817
prelude::*,
1918
ready, task,
2019
task::{Spawn, SpawnExt},
@@ -188,6 +187,7 @@ impl ActualConnection {
188187
}
189188
}
190189

190+
/// Opens a connection.
191191
pub async fn connect(connection_info: ConnectionInfo) -> RedisResult<Connection> {
192192
let con = match *connection_info.addr {
193193
ConnectionAddr::Tcp(ref host, port) => {
@@ -204,61 +204,64 @@ pub async fn connect(connection_info: ConnectionInfo) -> RedisResult<Connection>
204204
Err(err) => return Err(err.into()),
205205
};
206206

207-
TcpStream::connect(&socket_addr)
208-
.map_ok(|con| ActualConnection::Tcp(WriteWrapper(BufReader::new(con))))
209-
.await?
207+
TcpStream::connect(&socket_addr)
208+
.map_ok(|con| ActualConnection::Tcp(WriteWrapper(BufReader::new(con))))
209+
.await?
210210
}
211211
#[cfg(unix)]
212-
ConnectionAddr::Unix(ref path) =>
212+
ConnectionAddr::Unix(ref path) => {
213213
UnixStream::connect(path.clone())
214-
.map_ok(|stream| ActualConnection::Unix(WriteWrapper(BufReader::new(stream)))).await?,
215-
214+
.map_ok(|stream| ActualConnection::Unix(WriteWrapper(BufReader::new(stream))))
215+
.await?
216+
}
217+
216218
#[cfg(not(unix))]
217-
ConnectionAddr::Unix(_) => return Err(RedisError::from((
218-
ErrorKind::InvalidClientConfig,
219-
"Cannot connect to unix sockets \
220-
on this platform",
221-
))),
219+
ConnectionAddr::Unix(_) => {
220+
return Err(RedisError::from((
221+
ErrorKind::InvalidClientConfig,
222+
"Cannot connect to unix sockets \
223+
on this platform",
224+
)))
225+
}
222226
};
223227

224-
let mut rv = Connection {
225-
con,
226-
db: connection_info.db,
227-
};
228-
229-
match connection_info.passwd {
230-
Some(ref passwd) => {
231-
let mut cmd = cmd("AUTH");
232-
cmd.arg(&**passwd);
233-
let x = cmd.query_async::<_, Value>(&mut rv).await;
234-
match x {
235-
Ok(Value::Okay) => (),
236-
_ => {
237-
fail!((
238-
ErrorKind::AuthenticationFailed,
239-
"Password authentication failed"
240-
));
241-
}
242-
}
243-
}
244-
None => (),
245-
}
228+
let mut rv = Connection {
229+
con,
230+
db: connection_info.db,
231+
};
246232

247-
if connection_info.db != 0 {
248-
let mut cmd = cmd("SELECT");
249-
cmd.arg(connection_info.db);
250-
let result = cmd.query_async::<_, Value>(&mut rv).await;
251-
match result {
252-
Ok(Value::Okay) => Ok(rv),
253-
_ => fail!((
254-
ErrorKind::ResponseError,
255-
"Redis server refused to switch database"
256-
)),
233+
match connection_info.passwd {
234+
Some(ref passwd) => {
235+
let mut cmd = cmd("AUTH");
236+
cmd.arg(&**passwd);
237+
let x = cmd.query_async::<_, Value>(&mut rv).await;
238+
match x {
239+
Ok(Value::Okay) => (),
240+
_ => {
241+
fail!((
242+
ErrorKind::AuthenticationFailed,
243+
"Password authentication failed"
244+
));
257245
}
258-
} else {
259-
Ok(rv)
260246
}
261-
}).await
247+
}
248+
None => (),
249+
}
250+
251+
if connection_info.db != 0 {
252+
let mut cmd = cmd("SELECT");
253+
cmd.arg(connection_info.db);
254+
let result = cmd.query_async::<_, Value>(&mut rv).await;
255+
match result {
256+
Ok(Value::Okay) => Ok(rv),
257+
_ => fail!((
258+
ErrorKind::ResponseError,
259+
"Redis server refused to switch database"
260+
)),
261+
}
262+
} else {
263+
Ok(rv)
264+
}
262265
}
263266

264267
/// An async abstraction over connections.
@@ -563,6 +566,7 @@ where
563566
}
564567
}
565568

569+
/// A connection object bound to an executor.
566570
#[derive(Clone)]
567571
pub struct SharedConnection {
568572
pipeline: Pipeline<Vec<u8>, Value, RedisError>,
@@ -571,26 +575,24 @@ pub struct SharedConnection {
571575

572576
impl SharedConnection {
573577
/// Creates a shared connection from a connection and executor.
574-
pub fn new<E>(con: Connection, executor: E) -> impl Future<Output = RedisResult<Self>>
578+
pub fn new<E>(con: Connection, executor: E) -> RedisResult<Self>
575579
where
576580
E: Spawn,
577581
{
578-
future::lazy(|_| {
579-
let pipeline = match con.con {
580-
ActualConnection::Tcp(tcp) => {
581-
let codec = ValueCodec::default().framed(tcp.0.into_inner());
582-
Pipeline::new(codec, executor)
583-
}
584-
#[cfg(unix)]
585-
ActualConnection::Unix(unix) => {
586-
let codec = ValueCodec::default().framed(unix.0.into_inner());
587-
Pipeline::new(codec, executor)
588-
}
589-
};
590-
Ok(SharedConnection {
591-
pipeline,
592-
db: con.db,
593-
})
582+
let pipeline = match con.con {
583+
ActualConnection::Tcp(tcp) => {
584+
let codec = ValueCodec::default().framed(tcp.0.into_inner());
585+
Pipeline::new(codec, executor)
586+
}
587+
#[cfg(unix)]
588+
ActualConnection::Unix(unix) => {
589+
let codec = ValueCodec::default().framed(unix.0.into_inner());
590+
Pipeline::new(codec, executor)
591+
}
592+
};
593+
Ok(SharedConnection {
594+
pipeline,
595+
db: con.db,
594596
})
595597
}
596598
}

src/client.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ impl Client {
8080
}
8181
}
8282

83-
self.get_async_connection()
84-
.and_then(move |con| crate::aio::SharedConnection::new(con, TokioExecutor))
83+
self.get_async_connection().and_then(move |con| {
84+
future::ready(crate::aio::SharedConnection::new(con, TokioExecutor))
85+
})
8586
}
8687

8788
/// Returns a async shared connection with a specific executor.
@@ -93,7 +94,7 @@ impl Client {
9394
E: task::Spawn,
9495
{
9596
self.get_async_connection()
96-
.and_then(move |con| crate::aio::SharedConnection::new(con, executor))
97+
.and_then(move |con| future::ready(crate::aio::SharedConnection::new(con, executor)))
9798
}
9899
}
99100

src/cmd.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::types::{
33
from_redis_value, ErrorKind, FromRedisValue, RedisResult, RedisWrite, ToRedisArgs, Value,
44
};
55

6-
use futures::{future::Either, prelude::*};
6+
use futures::prelude::*;
77

88
#[derive(Clone)]
99
enum Arg<D> {
@@ -327,14 +327,19 @@ impl Cmd {
327327

328328
/// Async version of `query`.
329329
#[inline]
330-
pub async fn query_async<C, T: FromRedisValue>(&self, con: &mut C) -> RedisResult<T>
330+
pub fn query_async<'c, C, T: FromRedisValue>(
331+
&self,
332+
con: &'c mut C,
333+
) -> impl Future<Output = RedisResult<T>> + 'c
331334
where
332335
C: crate::aio::ConnectionLike + Send + 'static,
333336
T: Send + 'static,
334337
{
335338
let pcmd = self.get_packed_command();
336-
let val = con.req_packed_command(pcmd).await?;
337-
from_redis_value(&val)
339+
async move {
340+
let val = con.req_packed_command(pcmd).await?;
341+
from_redis_value(&val)
342+
}
338343
}
339344

340345
/// Similar to `query()` but returns an iterator over the items of the

src/lib.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -303,25 +303,20 @@
303303
//! # #[tokio::main]
304304
//! # async fn main() -> redis::RedisResult<()> {
305305
//! let client = redis::Client::open("redis://127.0.0.1/").unwrap();
306-
//! let con = client.get_async_connection().await?;
306+
//! let mut con = client.get_async_connection().await?;
307307
//!
308-
//! let (con, ()) = redis::cmd("SET")
308+
//! let () = redis::cmd("SET")
309309
//! .arg("key1")
310310
//! .arg(b"foo")
311-
//! // `query_async` acts in the same way as `query` but requires the connection to be
312-
//! // taken by value as the method returns a `Future` instead of `Result`.
313-
//! // This connection will be returned after the future has been completed allowing it to
314-
//! // be used again.
315-
//! .query_async(con)
311+
//! .query_async(&mut con)
316312
//! .await?;
317313
//!
318-
//! let (con, ()) = redis::cmd("SET").arg(&["key2", "bar"]).query_async(con).await?;
314+
//! let () = redis::cmd("SET").arg(&["key2", "bar"]).query_async(&mut con).await?;
319315
//!
320316
//! let result = redis::cmd("MGET")
321317
//! .arg(&["key1", "key2"])
322-
//! .query_async(con)
323-
//! .await
324-
//! .map(|t| t.1);
318+
//! .query_async(&mut con)
319+
//! .await;
325320
//! assert_eq!(result, Ok(("foo".to_string(), b"bar".to_vec())));
326321
//! Ok(())
327322
//! # }

src/parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ where
267267
match opt {
268268
Some(value) => {
269269
self.reader().consume(removed);
270-
let reader = self.reader.take().unwrap();
270+
self.reader.take().unwrap();
271271
return Ok(value?).into();
272272
}
273273
None => {

src/script.rs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -155,24 +155,23 @@ impl<'a> ScriptInvocation<'a> {
155155
/// Asynchronously invokes the script and returns the result.
156156
#[inline]
157157
pub fn invoke_async<'c, C, T: FromRedisValue + Send + 'static>(
158-
&'c self,
158+
&self,
159159
con: &'c mut C,
160160
) -> impl Future<Output = RedisResult<T>> + 'c
161161
where
162162
C: aio::ConnectionLike + Clone + Send + 'static,
163163
T: FromRedisValue + Send + 'static,
164164
{
165+
let mut eval_cmd = cmd("EVALSHA");
166+
eval_cmd
167+
.arg(self.script.hash.as_bytes())
168+
.arg(self.keys.len())
169+
.arg(&*self.keys)
170+
.arg(&*self.args);
171+
172+
let mut load_cmd = cmd("SCRIPT");
173+
load_cmd.arg("LOAD").arg(self.script.code.as_bytes());
165174
async move {
166-
let mut eval_cmd = cmd("EVALSHA");
167-
eval_cmd
168-
.arg(self.script.hash.as_bytes())
169-
.arg(self.keys.len())
170-
.arg(&*self.keys)
171-
.arg(&*self.args);
172-
173-
let mut load_cmd = cmd("SCRIPT");
174-
load_cmd.arg("LOAD").arg(self.script.code.as_bytes());
175-
176175
let future = {
177176
let mut con = con.clone();
178177
let eval_cmd = eval_cmd.clone();
@@ -182,7 +181,6 @@ impl<'a> ScriptInvocation<'a> {
182181
con: con.clone(),
183182
eval_cmd,
184183
load_cmd,
185-
status: ScriptStatus::NotLoaded,
186184
future,
187185
}
188186
.await
@@ -217,18 +215,25 @@ where
217215
self_.future = match self_.future {
218216
CmdFuture::Load(ref mut future) => {
219217
// When we're done loading the script into Redis, try eval'ing it again
220-
let (con, _hash) = ready!(future.as_mut().poll(cx))?;
221-
CmdFuture::Eval(self_.eval_cmd.query_async(con).boxed())
218+
let _hash = ready!(future.as_mut().poll(cx))?;
219+
220+
let mut con = self_.con.clone();
221+
let eval_cmd = self_.eval_cmd.clone();
222+
CmdFuture::Eval(async move { eval_cmd.query_async(&mut con).await }.boxed())
222223
}
223224
CmdFuture::Eval(ref mut future) => match ready!(future.as_mut().poll(cx)) {
224-
Ok((con, val)) => {
225+
Ok(val) => {
225226
// Return the value from the script evaluation
226-
return Ok((con, val)).into();
227+
return Ok(val).into();
227228
}
228229
Err(err) => {
229230
// Load the script into Redis if the script hash wasn't there already
230231
if err.kind() == ErrorKind::NoScriptError {
231-
CmdFuture::Load(self_.load_cmd.query_async(self_.con.clone()).boxed())
232+
let load_cmd = self_.load_cmd.clone();
233+
let mut con = self_.con.clone();
234+
CmdFuture::Load(
235+
async move { load_cmd.query_async(&mut con).await }.boxed(),
236+
)
232237
} else {
233238
return Err(err).into();
234239
}

0 commit comments

Comments
 (0)