Skip to content

Commit 0083217

Browse files
committed
add sync facade
1 parent 0f47685 commit 0083217

File tree

5 files changed

+197
-2
lines changed

5 files changed

+197
-2
lines changed

Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "rsmq_async"
3-
version = "11.0.0"
3+
version = "11.1.0"
44
authors = [
55
"David Bonet <webbonet@gmail.com>"
66
]
@@ -20,12 +20,14 @@ bb8 = "^0.8"
2020
thiserror = "^1"
2121
redis = { version = "^0.25", default-features = false, features = ["acl", "keep-alive", "script"] }
2222
async-trait = "^0.1"
23+
tokio = { version = "^1", optional = true}
2324

2425
[dev-dependencies]
2526
net2 = "^0.2"
2627
tokio = { version = "^1", features = ["rt-multi-thread"]}
2728

2829
[features]
29-
default = ["tokio-comp"]
30+
default = ["tokio-comp", "sync"]
31+
sync = ["tokio"]
3032
tokio-comp = ["redis/tokio-comp"]
3133
async-std-comp = ["redis/async-std-comp"]

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ and issue a `receiveMessage` then. However make sure not to listen with multiple
8787
workers for new messages with SUBSCRIBE to prevent multiple simultaneous
8888
`receiveMessage` calls.
8989

90+
## Sync option
91+
92+
If you enable the `sync` feature, you can import a `RsmqSync` object with sync
93+
versions of the methods.
94+
9095
## Guarantees
9196

9297
If you want to implement "at least one delivery" guarantee, you need to receive

src/error.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,21 @@ pub enum RsmqError {
4141
CannotParseMaxsize,
4242
#[error("The message received from Redis cannot be decoded into the expected type. Try to use Vec<u8> instead.")]
4343
CannotDecodeMessage(Vec<u8>),
44+
#[error("Cannot start tokio runtime for sync facade")]
45+
TokioStart(Different<std::io::Error>),
46+
}
47+
48+
#[derive(Debug)]
49+
pub struct Different<T>(pub T);
50+
51+
impl<T> PartialEq for Different<T> {
52+
fn eq(&self, _other: &Self) -> bool {
53+
false
54+
}
55+
}
56+
57+
impl<T> From<T> for Different<T> {
58+
fn from(value: T) -> Self {
59+
Different(value)
60+
}
4461
}

src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ mod error;
148148
mod functions;
149149
mod multiplexed_facade;
150150
mod pooled_facade;
151+
#[cfg(feature = "sync")]
152+
mod sync_facade;
151153
mod r#trait;
152154
mod types;
153155

@@ -156,6 +158,8 @@ pub use error::RsmqResult;
156158
pub use multiplexed_facade::Rsmq;
157159
pub use pooled_facade::{PoolOptions, PooledRsmq, RedisConnectionManager};
158160
pub use r#trait::RsmqConnection;
161+
#[cfg(feature = "sync")]
162+
pub use sync_facade::RsmqSync;
159163
pub use types::RedisBytes;
160164
pub use types::RsmqMessage;
161165
pub use types::RsmqOptions;

src/sync_facade.rs

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
use tokio::runtime::Runtime;
2+
3+
use crate::functions::RsmqFunctions;
4+
use crate::r#trait::RsmqConnection;
5+
use crate::types::{RedisBytes, RsmqMessage, RsmqOptions, RsmqQueueAttributes};
6+
use crate::{RsmqError, RsmqResult};
7+
use core::convert::TryFrom;
8+
use core::marker::PhantomData;
9+
use std::sync::Arc;
10+
use std::time::Duration;
11+
12+
#[derive(Clone)]
13+
struct RedisConnection(redis::aio::MultiplexedConnection);
14+
15+
impl std::fmt::Debug for RedisConnection {
16+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
17+
write!(f, "MultiplexedRedisAsyncConnnection")
18+
}
19+
}
20+
21+
#[derive(Debug, Clone)]
22+
pub struct RsmqSync {
23+
connection: RedisConnection,
24+
functions: RsmqFunctions<redis::aio::MultiplexedConnection>,
25+
runner: Arc<Runtime>,
26+
}
27+
28+
impl RsmqSync {
29+
/// Creates a new RSMQ instance, including its connection
30+
pub async fn new(options: RsmqOptions) -> RsmqResult<RsmqSync> {
31+
let runner = tokio::runtime::Builder::new_current_thread()
32+
.enable_all()
33+
.build()
34+
.map_err(|e| RsmqError::TokioStart(e.into()))?;
35+
36+
let conn_info = redis::ConnectionInfo {
37+
addr: redis::ConnectionAddr::Tcp(options.host, options.port),
38+
redis: redis::RedisConnectionInfo {
39+
db: options.db.into(),
40+
username: options.username,
41+
password: options.password,
42+
},
43+
};
44+
45+
let client = redis::Client::open(conn_info)?;
46+
47+
let connection =
48+
runner.block_on(async move { client.get_multiplexed_async_connection().await })?;
49+
50+
Ok(RsmqSync {
51+
connection: RedisConnection(connection),
52+
functions: RsmqFunctions {
53+
ns: options.ns,
54+
realtime: options.realtime,
55+
conn: PhantomData,
56+
},
57+
runner: Arc::new(runner),
58+
})
59+
}
60+
}
61+
62+
#[async_trait::async_trait]
63+
impl RsmqConnection for RsmqSync {
64+
async fn change_message_visibility(
65+
&mut self,
66+
qname: &str,
67+
message_id: &str,
68+
hidden: Duration,
69+
) -> RsmqResult<()> {
70+
self.runner.block_on(async {
71+
self.functions
72+
.change_message_visibility(&mut self.connection.0, qname, message_id, hidden)
73+
.await
74+
})
75+
}
76+
77+
async fn create_queue(
78+
&mut self,
79+
qname: &str,
80+
hidden: Option<Duration>,
81+
delay: Option<Duration>,
82+
maxsize: Option<i32>,
83+
) -> RsmqResult<()> {
84+
self.runner.block_on(async {
85+
self.functions
86+
.create_queue(&mut self.connection.0, qname, hidden, delay, maxsize)
87+
.await
88+
})
89+
}
90+
91+
async fn delete_message(&mut self, qname: &str, id: &str) -> RsmqResult<bool> {
92+
self.runner.block_on(async {
93+
self.functions
94+
.delete_message(&mut self.connection.0, qname, id)
95+
.await
96+
})
97+
}
98+
async fn delete_queue(&mut self, qname: &str) -> RsmqResult<()> {
99+
self.runner.block_on(async {
100+
self.functions
101+
.delete_queue(&mut self.connection.0, qname)
102+
.await
103+
})
104+
}
105+
async fn get_queue_attributes(&mut self, qname: &str) -> RsmqResult<RsmqQueueAttributes> {
106+
self.runner.block_on(async {
107+
self.functions
108+
.get_queue_attributes(&mut self.connection.0, qname)
109+
.await
110+
})
111+
}
112+
113+
async fn list_queues(&mut self) -> RsmqResult<Vec<String>> {
114+
self.runner
115+
.block_on(async { self.functions.list_queues(&mut self.connection.0).await })
116+
}
117+
118+
async fn pop_message<E: TryFrom<RedisBytes, Error = Vec<u8>>>(
119+
&mut self,
120+
qname: &str,
121+
) -> RsmqResult<Option<RsmqMessage<E>>> {
122+
self.runner.block_on(async {
123+
self.functions
124+
.pop_message::<E>(&mut self.connection.0, qname)
125+
.await
126+
})
127+
}
128+
129+
async fn receive_message<E: TryFrom<RedisBytes, Error = Vec<u8>>>(
130+
&mut self,
131+
qname: &str,
132+
hidden: Option<Duration>,
133+
) -> RsmqResult<Option<RsmqMessage<E>>> {
134+
self.runner.block_on(async {
135+
self.functions
136+
.receive_message::<E>(&mut self.connection.0, qname, hidden)
137+
.await
138+
})
139+
}
140+
141+
async fn send_message<E: Into<RedisBytes> + Send>(
142+
&mut self,
143+
qname: &str,
144+
message: E,
145+
delay: Option<Duration>,
146+
) -> RsmqResult<String> {
147+
self.runner.block_on(async {
148+
self.functions
149+
.send_message(&mut self.connection.0, qname, message, delay)
150+
.await
151+
})
152+
}
153+
154+
async fn set_queue_attributes(
155+
&mut self,
156+
qname: &str,
157+
hidden: Option<Duration>,
158+
delay: Option<Duration>,
159+
maxsize: Option<i64>,
160+
) -> RsmqResult<RsmqQueueAttributes> {
161+
self.runner.block_on(async {
162+
self.functions
163+
.set_queue_attributes(&mut self.connection.0, qname, hidden, delay, maxsize)
164+
.await
165+
})
166+
}
167+
}

0 commit comments

Comments
 (0)