#[cfg(test)]
#[path = "./client_test.rs"]
mod client_test;
use crate::connection;
use crate::subscriber;
use crate::types::{
Interrupts, Message, RedisBoolResult, RedisEmptyResult, RedisError, RedisResult,
RedisStringResult,
};
use std::str::FromStr;
pub struct Client {
client: redis::Client,
connection: connection::Connection,
subscriber: subscriber::Subscriber,
}
fn run_command_on_connection<T: redis::FromRedisValue>(
connection: &mut redis::Connection,
command: &str,
args: Vec<&str>,
) -> RedisResult<T> {
let mut cmd = redis::cmd(command);
for arg in args {
cmd.arg(arg);
}
let result: redis::RedisResult<T> = cmd.query(connection);
match result {
Err(error) => Err(RedisError::RedisError(error)),
Ok(output) => Ok(output),
}
}
impl Client {
pub fn is_connection_open(self: &mut Client) -> bool {
self.connection.is_connection_open()
}
pub fn quit(self: &mut Client) -> RedisEmptyResult {
let mut result = if self.is_connection_open() {
self.run_command_empty_response("QUIT", vec![])
} else {
Ok(())
};
if result.is_ok() {
result = self.unsubscribe_all();
}
result
}
pub fn run_command<T: redis::FromRedisValue>(
self: &mut Client,
command: &str,
args: Vec<&str>,
) -> RedisResult<T> {
match self.connection.get_redis_connection(&self.client) {
Ok(connection) => run_command_on_connection::<T>(connection, command, args),
Err(error) => Err(error),
}
}
pub fn run_command_from_string_response<T: FromStr>(
self: &mut Client,
command: &str,
args: Vec<&str>,
) -> RedisResult<T> {
match self.run_command::<String>(command, args) {
Ok(value) => match T::from_str(&value) {
Ok(typed_value) => Ok(typed_value),
_ => Err(RedisError::Description("Unable to parse output value.")),
},
Err(error) => Err(error),
}
}
pub fn run_command_empty_response(
self: &mut Client,
command: &str,
args: Vec<&str>,
) -> RedisEmptyResult {
self.run_command(command, args)
}
pub fn run_command_string_response(
self: &mut Client,
command: &str,
args: Vec<&str>,
) -> RedisStringResult {
self.run_command(command, args)
}
pub fn run_command_bool_response(
self: &mut Client,
command: &str,
args: Vec<&str>,
) -> RedisBoolResult {
self.run_command(command, args)
}
pub fn subscribe(self: &mut Client, channel: &str) -> RedisEmptyResult {
self.subscriber.subscribe(channel)
}
pub fn psubscribe(self: &mut Client, channel: &str) -> RedisEmptyResult {
self.subscriber.psubscribe(channel)
}
pub fn is_subscribed(self: &mut Client, channel: &str) -> bool {
self.subscriber.is_subscribed(channel)
}
pub fn is_psubscribed(self: &mut Client, channel: &str) -> bool {
self.subscriber.is_psubscribed(channel)
}
pub fn unsubscribe(self: &mut Client, channel: &str) -> RedisEmptyResult {
self.subscriber.unsubscribe(channel)
}
pub fn punsubscribe(self: &mut Client, channel: &str) -> RedisEmptyResult {
self.subscriber.punsubscribe(channel)
}
pub fn unsubscribe_all(self: &mut Client) -> RedisEmptyResult {
self.subscriber.unsubscribe_all()
}
pub fn fetch_messages(
self: &mut Client,
on_message: &mut dyn FnMut(Message) -> bool,
poll_interrupts: &mut dyn FnMut() -> Interrupts,
) -> RedisEmptyResult {
self.subscriber
.fetch_messages(&self.client, on_message, poll_interrupts)
}
}
pub fn create(connection_string: &str) -> Result<Client, RedisError> {
match redis::Client::open(connection_string) {
Ok(redis_client) => {
let redis_connection = connection::create();
let redis_pubsub = subscriber::create();
let client = Client {
client: redis_client,
connection: redis_connection,
subscriber: redis_pubsub,
};
Ok(client)
}
Err(error) => Err(RedisError::RedisError(error)),
}
}