use crate::client::{GlideClient, GlideClusterClient};
use crate::commands::prelude::*;
use crate::config::{GlideClientConfiguration, GlideClusterClientConfiguration};
use crate::error::Result;
use crate::executor::CustomCommand;
use crate::pipeline_options::PipelineOptions;
use crate::routes::Route;
use redis::{ToRedisArgs, Value};
use std::future::Future;
use std::sync::OnceLock;
use tokio::runtime::{Builder, Runtime};
fn runtime() -> &'static Runtime {
static RUNTIME: OnceLock<Runtime> = OnceLock::new();
RUNTIME.get_or_init(|| {
Builder::new_multi_thread()
.enable_all()
.thread_name("glide-sync")
.build()
.expect("failed to build the shared GLIDE sync runtime")
})
}
pub fn block_on<F: Future>(future: F) -> F::Output {
runtime().block_on(future)
}
#[derive(Clone)]
pub struct SyncGlideClient {
inner: GlideClient,
}
impl SyncGlideClient {
pub fn connect(config: GlideClientConfiguration) -> Result<Self> {
let inner = runtime().block_on(GlideClient::connect(config))?;
Ok(SyncGlideClient { inner })
}
pub fn async_client(&self) -> &GlideClient {
&self.inner
}
pub fn run<F, Fut, T>(&self, f: F) -> T
where
F: FnOnce(GlideClient) -> Fut,
Fut: Future<Output = T>,
{
runtime().block_on(f(self.inner.clone()))
}
pub fn update_connection_password(
&self,
password: Option<String>,
immediate_auth: bool,
) -> Result<()> {
runtime().block_on(
self.inner
.update_connection_password(password, immediate_auth),
)
}
pub fn custom_command<A: ToRedisArgs + Sync>(&self, args: &[A]) -> Result<Value> {
runtime().block_on(self.inner.custom_command(args))
}
pub fn execute_pipeline(
&self,
pipeline: &redis::Pipeline,
raise_on_error: bool,
options: &PipelineOptions,
) -> Result<Vec<Value>> {
runtime().block_on(
self.inner
.execute_pipeline(pipeline, raise_on_error, options),
)
}
pub fn ping(&self) -> Result<String> {
runtime().block_on(self.inner.ping())
}
}
#[derive(Clone)]
pub struct SyncGlideClusterClient {
inner: GlideClusterClient,
}
impl SyncGlideClusterClient {
pub fn connect(config: GlideClusterClientConfiguration) -> Result<Self> {
let inner = runtime().block_on(GlideClusterClient::connect(config))?;
Ok(SyncGlideClusterClient { inner })
}
pub fn async_client(&self) -> &GlideClusterClient {
&self.inner
}
pub fn run<F, Fut, T>(&self, f: F) -> T
where
F: FnOnce(GlideClusterClient) -> Fut,
Fut: Future<Output = T>,
{
runtime().block_on(f(self.inner.clone()))
}
pub fn custom_command<A: ToRedisArgs + Sync>(&self, args: &[A]) -> Result<Value> {
runtime().block_on(self.inner.custom_command(args))
}
pub fn custom_command_with_route<A: ToRedisArgs + Sync>(
&self,
args: &[A],
route: Route,
) -> Result<Value> {
runtime().block_on(self.inner.custom_command_with_route(args, route))
}
pub fn update_connection_password(
&self,
password: Option<String>,
immediate_auth: bool,
) -> Result<()> {
runtime().block_on(
self.inner
.update_connection_password(password, immediate_auth),
)
}
pub fn execute_pipeline(
&self,
pipeline: &redis::Pipeline,
raise_on_error: bool,
route: Option<crate::Route>,
options: &PipelineOptions,
) -> Result<Vec<Value>> {
runtime().block_on(
self.inner
.execute_pipeline(pipeline, raise_on_error, route, options),
)
}
pub fn ping(&self) -> Result<String> {
runtime().block_on(self.inner.ping())
}
}
macro_rules! impl_sync_owned_send {
($sync_ty:ty) => {
impl crate::commands::core::Commands for $sync_ty {
fn glide_send_owned_sync(&self, cmd: redis::Cmd) -> redis::RedisResult<Value> {
runtime().block_on(crate::commands::core::AsyncCommands::glide_send_owned(
&self.inner,
cmd,
))
}
}
};
}
impl_sync_owned_send!(SyncGlideClient);
impl_sync_owned_send!(SyncGlideClusterClient);
pub trait SyncPipelineTarget: sealed::Sealed {
#[doc(hidden)]
type Async: crate::client::GlidePipelineTarget;
#[doc(hidden)]
fn async_conn(&self) -> Self::Async;
}
mod sealed {
pub trait Sealed {}
impl Sealed for super::SyncGlideClient {}
impl Sealed for super::SyncGlideClusterClient {}
}
impl SyncPipelineTarget for SyncGlideClient {
type Async = GlideClient;
fn async_conn(&self) -> GlideClient {
self.inner.clone()
}
}
impl SyncPipelineTarget for SyncGlideClusterClient {
type Async = GlideClusterClient;
fn async_conn(&self) -> GlideClusterClient {
self.inner.clone()
}
}
pub trait PipelineExt {
fn query_glide<C: SyncPipelineTarget, T: redis::FromRedisValue + Send>(
&self,
con: &C,
) -> redis::RedisResult<T>;
}
impl PipelineExt for redis::Pipeline {
fn query_glide<C: SyncPipelineTarget, T: redis::FromRedisValue + Send>(
&self,
con: &C,
) -> redis::RedisResult<T> {
let async_conn = con.async_conn();
runtime().block_on(crate::client::PipelineExt::query_glide(self, &async_conn))
}
}