2017-12-28 21:14:04 -08:00
|
|
|
use std::collections::VecDeque;
|
2021-03-21 23:50:26 +01:00
|
|
|
use std::net::SocketAddr;
|
2017-12-28 21:14:04 -08:00
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
use redis_async::client::{paired_connect, PairedConnection};
|
|
|
|
use redis_async::resp::RespValue;
|
|
|
|
use tokio::sync::Mutex;
|
|
|
|
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
|
|
|
|
use trust_dns_resolver::TokioAsyncResolver as AsyncResolver;
|
2017-12-28 21:14:04 -08:00
|
|
|
|
2019-03-29 11:31:48 -07:00
|
|
|
use crate::Error;
|
2017-12-28 21:14:04 -08:00
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
pub struct RedisClient {
|
2018-01-22 00:40:50 -08:00
|
|
|
addr: String,
|
2021-03-21 23:50:26 +01:00
|
|
|
connection: Mutex<Option<PairedConnection>>,
|
2017-12-28 21:14:04 -08:00
|
|
|
}
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
impl RedisClient {
|
|
|
|
pub fn new(addr: impl Into<String>) -> Self {
|
|
|
|
Self {
|
|
|
|
addr: addr.into(),
|
|
|
|
connection: Mutex::new(None),
|
|
|
|
}
|
2017-12-28 21:14:04 -08:00
|
|
|
}
|
2018-02-15 16:53:05 -08:00
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
async fn get_connection(&self) -> Result<PairedConnection, Error> {
|
|
|
|
let mut connection = self.connection.lock().await;
|
|
|
|
if let Some(ref connection) = *connection {
|
|
|
|
return Ok(connection.clone());
|
|
|
|
}
|
2018-02-15 16:53:05 -08:00
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let mut addrs = resolve(&self.addr).await?;
|
|
|
|
loop {
|
|
|
|
// try to connect
|
|
|
|
let socket_addr = addrs.pop_front().ok_or_else(|| {
|
|
|
|
log::warn!("Cannot connect to {}.", self.addr);
|
|
|
|
Error::NotConnected
|
|
|
|
})?;
|
|
|
|
match paired_connect(socket_addr).await {
|
|
|
|
Ok(conn) => {
|
|
|
|
*connection = Some(conn.clone());
|
|
|
|
return Ok(conn);
|
2018-02-15 16:53:05 -08:00
|
|
|
}
|
2021-03-21 23:50:26 +01:00
|
|
|
Err(err) => log::warn!(
|
|
|
|
"Attempt to connect to {} as {} failed: {}.",
|
|
|
|
self.addr,
|
|
|
|
socket_addr,
|
|
|
|
err
|
|
|
|
),
|
|
|
|
}
|
2018-01-22 00:40:50 -08:00
|
|
|
}
|
|
|
|
}
|
2017-12-28 21:14:04 -08:00
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
pub async fn send(&self, req: RespValue) -> Result<RespValue, Error> {
|
|
|
|
let res = self.get_connection().await?.send(req).await?;
|
|
|
|
Ok(res)
|
2018-02-15 16:53:05 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
fn parse_addr(addr: &str, default_port: u16) -> Option<(&str, u16)> {
|
|
|
|
// split the string by ':' and convert the second part to u16
|
|
|
|
let mut parts_iter = addr.splitn(2, ':');
|
|
|
|
let host = parts_iter.next()?;
|
|
|
|
let port_str = parts_iter.next().unwrap_or("");
|
|
|
|
let port: u16 = port_str.parse().unwrap_or(default_port);
|
|
|
|
Some((host, port))
|
2017-12-28 21:14:04 -08:00
|
|
|
}
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
async fn resolve(addr: &str) -> Result<VecDeque<SocketAddr>, Error> {
|
|
|
|
// try to parse as a regular SocketAddr first
|
|
|
|
if let Ok(addr) = addr.parse::<SocketAddr>() {
|
|
|
|
let mut addrs = VecDeque::new();
|
|
|
|
addrs.push_back(addr);
|
|
|
|
return Ok(addrs);
|
|
|
|
}
|
2018-01-05 14:52:07 -08:00
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let (host, port) = parse_addr(addr, 6379).ok_or(Error::InvalidAddress)?;
|
2017-12-28 21:14:04 -08:00
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
// we need to do dns resolution
|
|
|
|
let resolver = AsyncResolver::tokio_from_system_conf()
|
|
|
|
.or_else(|err| {
|
|
|
|
log::warn!("Cannot create system DNS resolver: {}", err);
|
|
|
|
AsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default())
|
|
|
|
})
|
|
|
|
.map_err(|err| {
|
|
|
|
log::error!("Cannot create DNS resolver: {}", err);
|
|
|
|
Error::ResolveError
|
|
|
|
})?;
|
|
|
|
|
|
|
|
let addrs = resolver
|
|
|
|
.lookup_ip(host)
|
|
|
|
.await
|
|
|
|
.map_err(|_| Error::ResolveError)?
|
|
|
|
.into_iter()
|
|
|
|
.map(|ip| SocketAddr::new(ip, port))
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
Ok(addrs)
|
2017-12-28 21:14:04 -08:00
|
|
|
}
|