#![doc(html_root_url = "https://docs.rs/redis_r2d2")]
pub extern crate r2d2;
pub extern crate redis;
use redis::ConnectionLike;
use std::time::Duration;
#[derive(Debug)]
pub struct RedisConnectionManager {
connection_info: redis::ConnectionInfo,
timeout: Option<Duration>,
}
impl RedisConnectionManager {
pub fn new<T: redis::IntoConnectionInfo>(
params: T,
) -> Result<RedisConnectionManager, redis::RedisError> {
RedisConnectionManager::with_timeout(params, None)
}
pub fn with_timeout<T: redis::IntoConnectionInfo>(
params: T,
timeout: Option<Duration>,
) -> Result<RedisConnectionManager, redis::RedisError> {
Ok(RedisConnectionManager {
connection_info: params.into_connection_info()?,
timeout,
})
}
}
impl r2d2::ManageConnection for RedisConnectionManager {
type Connection = redis::Connection;
type Error = redis::RedisError;
fn connect(&self) -> Result<redis::Connection, Self::Error> {
redis::Client::open(self.connection_info.clone()).and_then(|client| {
if let Some(timeout) = self.timeout {
client.get_connection_with_timeout(timeout)
} else {
client.get_connection()
}
})
}
fn is_valid(&self, conn: &mut redis::Connection) -> Result<(), Self::Error> {
redis::cmd("PING").query(conn)
}
fn has_broken(&self, conn: &mut redis::Connection) -> bool {
!conn.is_open()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::mpsc;
use std::thread;
#[test]
fn test_basic() {
let manager = RedisConnectionManager::new("redis://localhost").unwrap();
let pool = r2d2::Pool::builder().max_size(2).build(manager).unwrap();
let (s1, r1) = mpsc::channel();
let (s2, r2) = mpsc::channel();
let pool1 = pool.clone();
let t1 = thread::spawn(move || {
let conn = pool1.get().unwrap();
s1.send(()).unwrap();
r2.recv().unwrap();
drop(conn);
});
let pool2 = pool.clone();
let t2 = thread::spawn(move || {
let conn = pool2.get().unwrap();
s2.send(()).unwrap();
r1.recv().unwrap();
drop(conn);
});
t1.join().unwrap();
t2.join().unwrap();
pool.get().unwrap();
}
#[test]
fn test_is_valid() {
let manager = RedisConnectionManager::new("redis://localhost").unwrap();
let pool = r2d2::Pool::builder()
.max_size(1)
.test_on_check_out(true)
.build(manager)
.unwrap();
pool.get().unwrap();
}
}