1use crate::AsyncTypedCommands;
16use crate::client::{GlideClient, GlideClusterClient};
17use crate::config::{GlideClientConfiguration, GlideClusterClientConfiguration};
18use crate::executor::CustomCommand;
19use crate::pipeline_options::PipelineOptions;
20use crate::routes::Route;
21use crate::write::ToValkeyArgs;
22use crate::{ValkeyResult, ValkeyValue};
23use std::future::Future;
24use std::sync::OnceLock;
25use tokio::runtime::{Builder, Runtime};
26
27mod pipeline;
28pub use pipeline::PipelineExt;
29
30fn runtime() -> &'static Runtime {
31 static RUNTIME: OnceLock<Runtime> = OnceLock::new();
32 RUNTIME.get_or_init(|| {
33 Builder::new_multi_thread()
34 .enable_all()
35 .thread_name("glide-sync")
36 .build()
37 .expect("failed to build the shared GLIDE sync runtime")
38 })
39}
40
41pub fn block_on<F: Future>(future: F) -> F::Output {
46 runtime().block_on(future)
47}
48
49#[derive(Clone)]
51pub struct SyncGlideClient {
52 inner: GlideClient,
53}
54
55impl SyncGlideClient {
56 pub fn connect(config: GlideClientConfiguration) -> ValkeyResult<Self> {
58 let inner = runtime().block_on(GlideClient::connect(config))?;
59 Ok(SyncGlideClient { inner })
60 }
61
62 pub fn async_client(&self) -> &GlideClient {
64 &self.inner
65 }
66
67 pub fn run<F, Fut, T>(&self, f: F) -> T
78 where
79 F: FnOnce(GlideClient) -> Fut,
80 Fut: Future<Output = T>,
81 {
82 runtime().block_on(f(self.inner.clone()))
83 }
84
85 pub fn update_connection_password(
88 &self,
89 password: Option<String>,
90 immediate_auth: bool,
91 ) -> ValkeyResult<()> {
92 runtime().block_on(
93 self.inner
94 .update_connection_password(password, immediate_auth),
95 )
96 }
97
98 pub fn custom_command<A: ToValkeyArgs + Sync>(&self, args: &[A]) -> ValkeyResult<ValkeyValue> {
100 runtime().block_on(self.inner.custom_command(args))
101 }
102
103 pub fn exec(
107 &self,
108 pipeline: &crate::pipeline::Pipeline,
109 raise_on_error: bool,
110 options: &PipelineOptions,
111 ) -> ValkeyResult<Vec<ValkeyValue>> {
112 runtime().block_on(self.inner.exec(pipeline, raise_on_error, options))
113 }
114
115 pub fn ping(&self) -> ValkeyResult<String> {
117 runtime().block_on(AsyncTypedCommands::ping(&self.inner))
118 }
119}
120
121#[derive(Clone)]
123pub struct SyncGlideClusterClient {
124 inner: GlideClusterClient,
125}
126
127impl SyncGlideClusterClient {
128 pub fn connect(config: GlideClusterClientConfiguration) -> ValkeyResult<Self> {
130 let inner = runtime().block_on(GlideClusterClient::connect(config))?;
131 Ok(SyncGlideClusterClient { inner })
132 }
133
134 pub fn async_client(&self) -> &GlideClusterClient {
136 &self.inner
137 }
138
139 pub fn run<F, Fut, T>(&self, f: F) -> T
141 where
142 F: FnOnce(GlideClusterClient) -> Fut,
143 Fut: Future<Output = T>,
144 {
145 runtime().block_on(f(self.inner.clone()))
146 }
147
148 pub fn custom_command<A: ToValkeyArgs + Sync>(&self, args: &[A]) -> ValkeyResult<ValkeyValue> {
150 runtime().block_on(self.inner.custom_command(args))
151 }
152
153 pub fn custom_command_with_route<A: ToValkeyArgs + Sync>(
155 &self,
156 args: &[A],
157 route: Route,
158 ) -> ValkeyResult<ValkeyValue> {
159 runtime().block_on(self.inner.custom_command_with_route(args, route))
160 }
161
162 pub fn update_connection_password(
165 &self,
166 password: Option<String>,
167 immediate_auth: bool,
168 ) -> ValkeyResult<()> {
169 runtime().block_on(
170 self.inner
171 .update_connection_password(password, immediate_auth),
172 )
173 }
174
175 pub fn exec(
179 &self,
180 pipeline: &crate::pipeline::Pipeline,
181 raise_on_error: bool,
182 route: Option<crate::Route>,
183 options: &PipelineOptions,
184 ) -> ValkeyResult<Vec<ValkeyValue>> {
185 runtime().block_on(self.inner.exec(pipeline, raise_on_error, route, options))
186 }
187
188 pub fn ping(&self) -> ValkeyResult<String> {
190 runtime().block_on(AsyncTypedCommands::ping(&self.inner))
191 }
192}
193
194macro_rules! impl_sync_command_dispatch {
197 ($ty:ty) => {
198 #[::sealed::sealed]
199 impl crate::commands::core::SyncCommandDispatch for $ty {
200 fn glide_dispatch_command(&self, cmd: crate::cmd::Cmd) -> ValkeyResult<ValkeyValue> {
201 runtime().block_on(
202 crate::commands::core::CommandDispatch::glide_dispatch_command(
203 &self.inner,
204 cmd,
205 ),
206 )
207 }
208 }
209 };
210}
211
212impl_sync_command_dispatch!(SyncGlideClient);
213impl_sync_command_dispatch!(SyncGlideClusterClient);
214
215macro_rules! impl_sync_script_invoke {
218 ($ty:ty) => {
219 #[::sealed::sealed]
220 impl crate::script::ScriptInvokeSync for $ty {
221 fn glide_invoke_script(
222 &self,
223 hash: &str,
224 keys: &[Vec<u8>],
225 args: &[Vec<u8>],
226 ) -> ValkeyResult<ValkeyValue> {
227 runtime().block_on(crate::script::ScriptInvoke::glide_invoke_script(
228 &self.inner,
229 hash,
230 keys,
231 args,
232 ))
233 }
234 }
235 };
236}
237
238impl_sync_script_invoke!(SyncGlideClient);
239impl_sync_script_invoke!(SyncGlideClusterClient);
240
241macro_rules! impl_sync_pipeline_dispatch {
244 ($ty:ty) => {
245 #[::sealed::sealed]
246 impl pipeline::SyncPipelineDispatch for $ty {
247 fn glide_dispatch_pipeline<T: crate::value::FromValkeyValue + Send>(
248 &self,
249 pipeline: &crate::pipeline::Pipeline,
250 ) -> ValkeyResult<T> {
251 let async_conn = self.inner.clone();
252 runtime().block_on(crate::client::PipelineExt::query_async(
253 pipeline,
254 &async_conn,
255 ))
256 }
257 }
258 };
259}
260
261impl_sync_pipeline_dispatch!(SyncGlideClient);
262impl_sync_pipeline_dispatch!(SyncGlideClusterClient);