/* * mCaptcha - A proof of work based DoS protection system * Copyright © 2021 Aravinth Manivannan * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ use std::cell::RefCell; use std::rc::Rc; use redis::cluster::ClusterClient; use redis::FromRedisValue; //use redis::cluster::ClusterConnection; use redis::Client; //use redis::Connection; use redis::{aio::Connection, cluster::ClusterConnection}; use crate::errors::*; #[derive(Clone)] pub enum RedisConfig { Single(String), Cluster(Vec), } impl RedisConfig { pub fn connect(&self) -> RedisClient { match self { Self::Single(url) => { let client = Client::open(url.as_str()).unwrap(); RedisClient::Single(client) } Self::Cluster(nodes) => { let cluster_client = ClusterClient::open(nodes.to_owned()).unwrap(); RedisClient::Cluster(cluster_client) } } } } pub enum RedisConnection { Single(Rc>), Cluster(Rc>), } impl RedisConnection { #[inline] pub fn get_client(&self) -> Self { match self { Self::Single(con) => Self::Single(Rc::clone(&con)), Self::Cluster(con) => Self::Cluster(Rc::clone(&con)), } } #[inline] pub async fn exec(&self, cmd: &mut redis::Cmd) -> redis::RedisResult { match self { RedisConnection::Single(con) => cmd.query_async(&mut *con.borrow_mut()).await, RedisConnection::Cluster(con) => cmd.query(&mut *con.borrow_mut()), } } } #[derive(Clone)] pub enum RedisClient { Single(Client), Cluster(ClusterClient), } pub struct Redis { _client: RedisClient, connection: RedisConnection, } impl Redis { pub async fn new(redis: RedisConfig) -> CaptchaResult { let (_client, connection) = Self::connect(redis).await; let master = Self { _client, connection, }; Ok(master) } pub fn get_client(&self) -> RedisConnection { self.connection.get_client() } async fn connect(redis: RedisConfig) -> (RedisClient, RedisConnection) { let redis = redis.connect(); let client = match &redis { RedisClient::Single(c) => { let con = c.get_async_connection().await.unwrap(); RedisConnection::Single(Rc::new(RefCell::new(con))) } RedisClient::Cluster(c) => { let con = c.get_connection().unwrap(); RedisConnection::Cluster(Rc::new(RefCell::new(con))) } }; (redis, client) } }