Skip to content

Commit cd17426

Browse files
authored
Merge pull request #3 from ntex-rs/ntex-io
upgrade to ntex 0.5
2 parents 412f5bb + 41005e2 commit cd17426

File tree

6 files changed

+104
-108
lines changed

6 files changed

+104
-108
lines changed

CHANGES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changes
22

3+
## [0.3.0-b.0] - 2021-12-19
4+
5+
* upgrade to ntex 0.5
6+
37
## [0.2.4] - 2021-12-02
48

59
* Add memory pools support

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ntex-redis"
3-
version = "0.2.4"
3+
version = "0.3.0-b.0"
44
authors = ["ntex contributors <[email protected]>"]
55
description = "Redis client"
66
documentation = "https://docs.rs/ntex-redis"
@@ -21,7 +21,7 @@ openssl = ["ntex/openssl"]
2121
rustls = ["ntex/rustls"]
2222

2323
[dependencies]
24-
ntex = "0.4.11"
24+
ntex = "0.5.0-b.1"
2525
itoa = "0.4.5"
2626
btoi = "0.4.2"
2727
log = "0.4"

src/client.rs

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use std::collections::VecDeque;
22
use std::{cell::RefCell, fmt, future::Future, pin::Pin, rc::Rc, task::Context, task::Poll};
33

4-
use ntex::util::{poll_fn, Either, Ready};
5-
use ntex::{channel::pool, framed::State, service::Service};
4+
use ntex::io::{IoBoxed, IoRef, OnDisconnect};
5+
use ntex::util::{poll_fn, ready, Either, Ready};
6+
use ntex::{channel::pool, service::Service};
67

78
use super::cmd::Command;
89
use super::codec::{Codec, Request, Response};
@@ -13,55 +14,58 @@ type Queue = Rc<RefCell<VecDeque<pool::Sender<Result<Response, Error>>>>>;
1314
#[derive(Clone)]
1415
/// Shared redis client
1516
pub struct Client {
16-
state: State,
17+
io: IoRef,
1718
queue: Queue,
19+
disconnect: OnDisconnect,
1820
pool: pool::Pool<Result<Response, Error>>,
1921
}
2022

2123
impl Client {
22-
pub(crate) fn new(state: State) -> Self {
24+
pub(crate) fn new(io: IoBoxed) -> Self {
2325
let queue: Queue = Rc::new(RefCell::new(VecDeque::new()));
2426

2527
// read redis response task
26-
let state2 = state.clone();
28+
let io_ref = io.get_ref();
2729
let queue2 = queue.clone();
2830
ntex::rt::spawn(async move {
29-
let read = state2.read();
30-
31-
poll_fn(|cx| {
32-
loop {
33-
match read.decode(&Codec) {
34-
Err(e) => {
35-
if let Some(tx) = queue2.borrow_mut().pop_front() {
36-
let _ = tx.send(Err(e));
37-
}
38-
queue2.borrow_mut().clear();
39-
state2.shutdown_io();
40-
return Poll::Ready(());
31+
poll_fn(|cx| loop {
32+
match ready!(io.poll_read_next(&Codec, cx)) {
33+
Some(Ok(item)) => {
34+
if let Some(tx) = queue2.borrow_mut().pop_front() {
35+
let _ = tx.send(Ok(item));
36+
} else {
37+
log::error!("Unexpected redis response: {:?}", item);
4138
}
42-
Ok(Some(item)) => {
43-
if let Some(tx) = queue2.borrow_mut().pop_front() {
44-
let _ = tx.send(Ok(item));
45-
} else {
46-
log::error!("Unexpected redis response: {:?}", item);
47-
}
39+
continue;
40+
}
41+
Some(Err(Either::Left(e))) => {
42+
if let Some(tx) = queue2.borrow_mut().pop_front() {
43+
let _ = tx.send(Err(e));
4844
}
49-
Ok(None) => break,
45+
queue2.borrow_mut().clear();
46+
let _ = ready!(io.poll_shutdown(cx));
47+
return Poll::Ready(());
5048
}
49+
Some(Err(Either::Right(e))) => {
50+
if let Some(tx) = queue2.borrow_mut().pop_front() {
51+
let _ = tx.send(Err(e.into()));
52+
}
53+
queue2.borrow_mut().clear();
54+
let _ = ready!(io.poll_shutdown(cx));
55+
return Poll::Ready(());
56+
}
57+
None => return Poll::Ready(()),
5158
}
52-
53-
if !state2.is_open() {
54-
return Poll::Ready(());
55-
}
56-
state2.register_dispatcher(cx.waker());
57-
Poll::Pending
5859
})
5960
.await
6061
});
6162

63+
let disconnect = io_ref.on_disconnect();
64+
6265
Client {
63-
state,
6466
queue,
67+
disconnect,
68+
io: io_ref,
6569
pool: pool::new(),
6670
}
6771
}
@@ -71,7 +75,7 @@ impl Client {
7175
where
7276
T: Command,
7377
{
74-
let is_open = self.state.is_open();
78+
let is_open = !self.io.is_closed();
7579
let fut = self.call(cmd.to_request());
7680

7781
async move {
@@ -93,7 +97,7 @@ impl Client {
9397

9498
/// Returns true if underlying transport is connected to redis
9599
pub fn is_connected(&self) -> bool {
96-
self.state.is_open()
100+
!self.io.is_closed()
97101
}
98102
}
99103

@@ -103,16 +107,16 @@ impl Service for Client {
103107
type Error = Error;
104108
type Future = Either<CommandResult, Ready<Response, Error>>;
105109

106-
fn poll_ready(&self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
107-
if !self.state.is_open() {
110+
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
111+
if self.disconnect.poll_ready(cx).is_ready() {
108112
Poll::Ready(Err(Error::Disconnected))
109113
} else {
110114
Poll::Ready(Ok(()))
111115
}
112116
}
113117

114118
fn call(&self, req: Request) -> Self::Future {
115-
if let Err(e) = self.state.write().encode(req, &Codec) {
119+
if let Err(e) = self.io.encode(req, &Codec) {
116120
Either::Right(Ready::Err(e))
117121
} else {
118122
let (tx, rx) = self.pool.channel();
@@ -125,7 +129,7 @@ impl Service for Client {
125129
impl fmt::Debug for Client {
126130
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127131
f.debug_struct("Client")
128-
.field("connected", &self.state.is_open())
132+
.field("connected", &!self.io.is_closed())
129133
.finish()
130134
}
131135
}

src/connector.rs

Lines changed: 42 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
use std::{cell::RefCell, future::Future, rc::Rc};
1+
use std::future::Future;
22

3-
use ntex::codec::{AsyncRead, AsyncWrite};
43
use ntex::connect::{self, Address, Connect, Connector};
5-
use ntex::framed::{ReadTask, State, WriteTask};
4+
use ntex::io::{Filter, Io, IoBoxed};
65
use ntex::{service::Service, time::Seconds, util::ByteString, util::PoolId, util::PoolRef};
76

87
#[cfg(feature = "openssl")]
9-
use ntex::connect::openssl::{OpensslConnector, SslConnector};
8+
use ntex::connect::openssl::{self, SslConnector};
109

1110
#[cfg(feature = "rustls")]
12-
use ntex::connect::rustls::{ClientConfig, RustlsConnector};
11+
use ntex::connect::rustls::{self, ClientConfig};
1312

1413
use super::errors::ConnectError;
1514
use super::{cmd, Client, SimpleClient};
@@ -28,11 +27,16 @@ where
2827
{
2928
#[allow(clippy::new_ret_no_self)]
3029
/// Create new redis connector
31-
pub fn new(address: A) -> RedisConnector<A, Connector<A>> {
30+
pub fn new(
31+
address: A,
32+
) -> RedisConnector<
33+
A,
34+
impl Service<Request = Connect<A>, Response = IoBoxed, Error = connect::ConnectError>,
35+
> {
3236
RedisConnector {
3337
address,
3438
passwords: Vec::new(),
35-
connector: Connector::default(),
39+
connector: Connector::default().map(|io| io.into_boxed()),
3640
pool: PoolId::P7.pool_ref(),
3741
}
3842
}
@@ -41,8 +45,7 @@ where
4145
impl<A, T> RedisConnector<A, T>
4246
where
4347
A: Address + Clone,
44-
T: Service<Request = Connect<A>, Error = connect::ConnectError>,
45-
T::Response: AsyncRead + AsyncWrite + Unpin + 'static,
48+
T: Service<Request = Connect<A>, Response = IoBoxed, Error = connect::ConnectError>,
4649
{
4750
/// Add redis auth password
4851
pub fn password<U>(mut self, password: U) -> Self
@@ -63,29 +66,20 @@ where
6366
self
6467
}
6568

66-
#[doc(hidden)]
67-
#[deprecated(since = "0.2.4", note = "Use memory pool config")]
68-
#[inline]
69-
/// Set read/write buffer params
70-
///
71-
/// By default read buffer is 16kb, write buffer is 16kb
72-
pub fn buffer_params(
73-
self,
74-
_max_read_buf_size: u16,
75-
_max_write_buf_size: u16,
76-
_min_buf_size: u16,
77-
) -> Self {
78-
self
79-
}
80-
8169
/// Use custom connector
82-
pub fn connector<U>(self, connector: U) -> RedisConnector<A, U>
70+
pub fn connector<U, F>(
71+
self,
72+
connector: U,
73+
) -> RedisConnector<
74+
A,
75+
impl Service<Request = Connect<A>, Response = IoBoxed, Error = connect::ConnectError>,
76+
>
8377
where
84-
U: Service<Request = Connect<A>, Error = connect::ConnectError>,
85-
U::Response: AsyncRead + AsyncWrite + Unpin + 'static,
78+
F: Filter,
79+
U: Service<Request = Connect<A>, Response = Io<F>, Error = connect::ConnectError>,
8680
{
8781
RedisConnector {
88-
connector,
82+
connector: connector.map(|io| io.into_boxed()),
8983
address: self.address,
9084
passwords: self.passwords,
9185
pool: self.pool,
@@ -94,11 +88,17 @@ where
9488

9589
#[cfg(feature = "openssl")]
9690
/// Use openssl connector.
97-
pub fn openssl(self, connector: SslConnector) -> RedisConnector<A, OpensslConnector<A>> {
91+
pub fn openssl(
92+
self,
93+
connector: SslConnector,
94+
) -> RedisConnector<
95+
A,
96+
impl Service<Request = Connect<A>, Response = IoBoxed, Error = connect::ConnectError>,
97+
> {
9898
RedisConnector {
9999
address: self.address,
100100
passwords: self.passwords,
101-
connector: OpensslConnector::new(connector),
101+
connector: openssl::Connector::new(connector).map(|io| io.into_boxed()),
102102
pool: self.pool,
103103
}
104104
}
@@ -107,12 +107,15 @@ where
107107
/// Use rustls connector.
108108
pub fn rustls(
109109
self,
110-
config: std::sync::Arc<ClientConfig>,
111-
) -> RedisConnector<A, RustlsConnector<A>> {
110+
config: ClientConfig,
111+
) -> RedisConnector<
112+
A,
113+
impl Service<Request = Connect<A>, Response = IoBoxed, Error = connect::ConnectError>,
114+
> {
112115
RedisConnector {
113116
address: self.address,
114117
passwords: self.passwords,
115-
connector: RustlsConnector::new(config),
118+
connector: rustls::Connector::new(config).map(|io| io.into_boxed()),
116119
pool: self.pool,
117120
}
118121
}
@@ -125,14 +128,10 @@ where
125128

126129
async move {
127130
let io = fut.await?;
131+
io.set_memory_pool(pool);
132+
io.set_disconnect_timeout(Seconds::ZERO.into());
128133

129-
let state = State::with_memory_pool(pool);
130-
state.set_disconnect_timeout(Seconds::ZERO);
131-
let io = Rc::new(RefCell::new(io));
132-
ntex::rt::spawn(ReadTask::new(io.clone(), state.clone()));
133-
ntex::rt::spawn(WriteTask::new(io, state.clone()));
134-
135-
let client = Client::new(state);
134+
let client = Client::new(io);
136135

137136
if passwords.is_empty() {
138137
Ok(client)
@@ -155,14 +154,10 @@ where
155154

156155
async move {
157156
let io = fut.await?;
157+
io.set_memory_pool(pool);
158+
io.set_disconnect_timeout(Seconds::ZERO.into());
158159

159-
let state = State::with_memory_pool(pool);
160-
state.set_disconnect_timeout(Seconds::ZERO);
161-
let io = Rc::new(RefCell::new(io));
162-
ntex::rt::spawn(ReadTask::new(io.clone(), state.clone()));
163-
ntex::rt::spawn(WriteTask::new(io, state.clone()));
164-
165-
let mut client = SimpleClient::new(state);
160+
let client = SimpleClient::new(io);
166161

167162
if passwords.is_empty() {
168163
Ok(client)

src/simple.rs

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,36 @@
11
use std::task::Poll;
22

3-
use ntex::{framed::State, util::poll_fn};
3+
use ntex::{io::IoBoxed, util::poll_fn, util::ready, util::Either};
44

55
use super::cmd::Command;
66
use super::codec::Codec;
77
use super::errors::{CommandError, Error};
88

99
/// Redis client
1010
pub struct SimpleClient {
11-
state: State,
11+
io: IoBoxed,
1212
}
1313

1414
impl SimpleClient {
1515
/// Create new simple client
16-
pub(crate) fn new(state: State) -> Self {
17-
SimpleClient { state }
16+
pub(crate) fn new(io: IoBoxed) -> Self {
17+
SimpleClient { io }
1818
}
1919

2020
/// Execute redis command
21-
pub async fn exec<U>(&mut self, cmd: U) -> Result<U::Output, CommandError>
21+
pub async fn exec<U>(&self, cmd: U) -> Result<U::Output, CommandError>
2222
where
2323
U: Command,
2424
{
25-
self.state.write().encode(cmd.to_request(), &Codec)?;
26-
27-
let read = self.state.read();
28-
poll_fn(|cx| {
29-
if let Some(item) = read.decode(&Codec)? {
30-
return Poll::Ready(U::to_output(
31-
item.into_result().map_err(CommandError::Error)?,
32-
));
33-
}
34-
35-
if !self.state.is_open() {
36-
return Poll::Ready(Err(CommandError::Protocol(Error::Disconnected)));
37-
}
38-
39-
self.state.register_dispatcher(cx.waker());
40-
Poll::Pending
25+
self.io.encode(cmd.to_request(), &Codec)?;
26+
27+
poll_fn(|cx| match ready!(self.io.poll_read_next(&Codec, cx)) {
28+
Some(Ok(item)) => Poll::Ready(U::to_output(
29+
item.into_result().map_err(CommandError::Error)?,
30+
)),
31+
Some(Err(Either::Left(err))) => Poll::Ready(Err(CommandError::Protocol(err))),
32+
Some(Err(Either::Right(err))) => Poll::Ready(Err(CommandError::Protocol(err.into()))),
33+
None => Poll::Ready(Err(CommandError::Protocol(Error::Disconnected))),
4134
})
4235
.await
4336
}

0 commit comments

Comments
 (0)