bb8_redis/
lib.rs

1//! Redis support for the `bb8` connection pool.
2//!
3//! # Example
4//!
5//! ```
6//! use futures_util::future::join_all;
7//! use bb8_redis::{
8//!     bb8,
9//!     redis::{cmd, AsyncCommands},
10//!     RedisConnectionManager
11//! };
12//!
13//! #[tokio::main]
14//! async fn main() {
15//!     let manager = RedisConnectionManager::new("redis://localhost").unwrap();
16//!     let pool = bb8::Pool::builder().build(manager).await.unwrap();
17//!
18//!     let mut handles = vec![];
19//!
20//!     for _i in 0..10 {
21//!         let pool = pool.clone();
22//!
23//!         handles.push(tokio::spawn(async move {
24//!             let mut conn = pool.get().await.unwrap();
25//!
26//!             let reply: String = cmd("PING").query_async(&mut *conn).await.unwrap();
27//!
28//!             assert_eq!("PONG", reply);
29//!         }));
30//!     }
31//!
32//!     join_all(handles).await;
33//! }
34//! ```
35#![allow(clippy::needless_doctest_main)]
36#![deny(missing_docs, missing_debug_implementations)]
37
38pub use bb8;
39pub use redis;
40
41use redis::{aio::MultiplexedConnection, ErrorKind};
42use redis::{Client, IntoConnectionInfo, RedisError};
43
44/// A `bb8::ManageConnection` for `redis::Client::get_async_connection`.
45#[derive(Clone, Debug)]
46pub struct RedisConnectionManager {
47    client: Client,
48}
49
50impl RedisConnectionManager {
51    /// Create a new `RedisConnectionManager`.
52    /// See `redis::Client::open` for a description of the parameter types.
53    pub fn new<T: IntoConnectionInfo>(info: T) -> Result<Self, RedisError> {
54        Ok(Self {
55            client: Client::open(info.into_connection_info()?)?,
56        })
57    }
58}
59
60impl bb8::ManageConnection for RedisConnectionManager {
61    type Connection = MultiplexedConnection;
62    type Error = RedisError;
63
64    async fn connect(&self) -> Result<Self::Connection, Self::Error> {
65        self.client.get_multiplexed_async_connection().await
66    }
67
68    async fn is_valid(&self, conn: &mut Self::Connection) -> Result<(), Self::Error> {
69        let pong: String = redis::cmd("PING").query_async(conn).await?;
70        match pong.as_str() {
71            "PONG" => Ok(()),
72            _ => Err((ErrorKind::ResponseError, "ping request").into()),
73        }
74    }
75
76    fn has_broken(&self, _: &mut Self::Connection) -> bool {
77        false
78    }
79}