Skip to main content

fredis/commands/interfaces/
lua.rs

1use crate::{
2  commands,
3  error::Error,
4  interfaces::{ClientLike, FredResult},
5  types::{
6    FromValue,
7    MultipleKeys,
8    MultipleStrings,
9    MultipleValues,
10    scripts::{FnPolicy, ScriptDebugFlag},
11  },
12};
13use bytes::Bytes;
14use bytes_utils::Str;
15use fred_macros::rm_send_if;
16use futures::Future;
17use std::convert::TryInto;
18
19/// Functions that implement the [lua](https://redis.io/commands#lua) interface.
20#[rm_send_if(any(feature = "glommio", feature = "cloudflare"))]
21pub trait LuaInterface: ClientLike + Sized {
22  /// Load a script into the scripts cache, without executing it. After the specified command is loaded into the
23  /// script cache it will be callable using EVALSHA with the correct SHA1 digest of the script.
24  ///
25  /// Returns the SHA-1 hash of the script.
26  ///
27  /// <https://redis.io/commands/script-load>
28  fn script_load<R, S>(&self, script: S) -> impl Future<Output = FredResult<R>> + Send
29  where
30    R: FromValue,
31    S: Into<Str> + Send,
32  {
33    async move {
34      into!(script);
35      commands::lua::script_load(self, script).await?.convert()
36    }
37  }
38
39  /// A clustered variant of [script_load](Self::script_load) that loads the script on all primary nodes in a cluster.
40  ///
41  /// Returns the SHA-1 hash of the script.
42  #[cfg(feature = "sha-1")]
43  #[cfg_attr(docsrs, doc(cfg(feature = "sha-1")))]
44  fn script_load_cluster<R, S>(&self, script: S) -> impl Future<Output = FredResult<R>> + Send
45  where
46    R: FromValue,
47    S: Into<Str> + Send,
48  {
49    async move {
50      into!(script);
51      commands::lua::script_load_cluster(self, script).await?.convert()
52    }
53  }
54
55  /// Kills the currently executing Lua script, assuming no write operation was yet performed by the script.
56  ///
57  /// <https://redis.io/commands/script-kill>
58  fn script_kill(&self) -> impl Future<Output = FredResult<()>> + Send {
59    async move { commands::lua::script_kill(self).await }
60  }
61
62  /// A clustered variant of the [script_kill](Self::script_kill) command that issues the command to all primary nodes
63  /// in the cluster.
64  fn script_kill_cluster(&self) -> impl Future<Output = FredResult<()>> + Send {
65    async move { commands::lua::script_kill_cluster(self).await }
66  }
67
68  /// Flush the Lua scripts cache.
69  ///
70  /// <https://redis.io/commands/script-flush>
71  fn script_flush(&self, r#async: bool) -> impl Future<Output = FredResult<()>> + Send {
72    async move { commands::lua::script_flush(self, r#async).await }
73  }
74
75  /// A clustered variant of [script_flush](Self::script_flush) that flushes the script cache on all primary nodes in
76  /// the cluster.
77  fn script_flush_cluster(&self, r#async: bool) -> impl Future<Output = FredResult<()>> + Send {
78    async move { commands::lua::script_flush_cluster(self, r#async).await }
79  }
80
81  /// Returns information about the existence of the scripts in the script cache.
82  ///
83  /// <https://redis.io/commands/script-exists>
84  fn script_exists<R, H>(&self, hashes: H) -> impl Future<Output = FredResult<R>> + Send
85  where
86    R: FromValue,
87    H: Into<MultipleStrings> + Send,
88  {
89    async move {
90      into!(hashes);
91      commands::lua::script_exists(self, hashes).await?.convert()
92    }
93  }
94
95  /// Set the debug mode for subsequent scripts executed with EVAL.
96  ///
97  /// <https://redis.io/commands/script-debug>
98  fn script_debug(&self, flag: ScriptDebugFlag) -> impl Future<Output = FredResult<()>> + Send {
99    async move { commands::lua::script_debug(self, flag).await }
100  }
101
102  /// Evaluates a script cached on the server side by its SHA1 digest.
103  ///
104  /// <https://redis.io/commands/evalsha>
105  ///
106  /// **Note: Use `None` to represent an empty set of keys or args.**
107  fn evalsha<R, S, K, V>(&self, hash: S, keys: K, args: V) -> impl Future<Output = FredResult<R>> + Send
108  where
109    R: FromValue,
110    S: Into<Str> + Send,
111    K: Into<MultipleKeys> + Send,
112    V: TryInto<MultipleValues> + Send,
113    V::Error: Into<Error> + Send,
114  {
115    async move {
116      into!(hash, keys);
117      try_into!(args);
118      commands::lua::evalsha(self, hash, keys, args).await?.convert()
119    }
120  }
121
122  /// Evaluate a Lua script on the server.
123  ///
124  /// <https://redis.io/commands/eval>
125  ///
126  /// **Note: Use `None` to represent an empty set of keys or args.**
127  fn eval<R, S, K, V>(&self, script: S, keys: K, args: V) -> impl Future<Output = FredResult<R>> + Send
128  where
129    R: FromValue,
130    S: Into<Str> + Send,
131    K: Into<MultipleKeys> + Send,
132    V: TryInto<MultipleValues> + Send,
133    V::Error: Into<Error> + Send,
134  {
135    async move {
136      into!(script, keys);
137      try_into!(args);
138      commands::lua::eval(self, script, keys, args).await?.convert()
139    }
140  }
141}
142
143/// Functions that implement the [function](https://redis.io/docs/manual/programmability/functions-intro/) interface.
144#[rm_send_if(any(feature = "glommio", feature = "cloudflare"))]
145pub trait FunctionInterface: ClientLike + Sized {
146  /// Invoke a function.
147  ///
148  /// <https://redis.io/commands/fcall/>
149  fn fcall<R, F, K, V>(&self, func: F, keys: K, args: V) -> impl Future<Output = FredResult<R>> + Send
150  where
151    R: FromValue,
152    F: Into<Str> + Send,
153    K: Into<MultipleKeys> + Send,
154    V: TryInto<MultipleValues> + Send,
155    V::Error: Into<Error> + Send,
156  {
157    async move {
158      into!(func);
159      try_into!(keys, args);
160      commands::lua::fcall(self, func, keys, args).await?.convert()
161    }
162  }
163
164  /// This is a read-only variant of the FCALL command that cannot execute commands that modify data.
165  ///
166  /// <https://redis.io/commands/fcall_ro/>
167  fn fcall_ro<R, F, K, V>(&self, func: F, keys: K, args: V) -> impl Future<Output = FredResult<R>> + Send
168  where
169    R: FromValue,
170    F: Into<Str> + Send,
171    K: Into<MultipleKeys> + Send,
172    V: TryInto<MultipleValues> + Send,
173    V::Error: Into<Error> + Send,
174  {
175    async move {
176      into!(func);
177      try_into!(keys, args);
178      commands::lua::fcall_ro(self, func, keys, args).await?.convert()
179    }
180  }
181
182  /// Delete a library and all its functions.
183  ///
184  /// <https://redis.io/commands/function-delete/>
185  fn function_delete<R, S>(&self, library_name: S) -> impl Future<Output = FredResult<R>> + Send
186  where
187    R: FromValue,
188    S: Into<Str> + Send,
189  {
190    async move {
191      into!(library_name);
192      commands::lua::function_delete(self, library_name).await?.convert()
193    }
194  }
195
196  /// Delete a library and all its functions from each cluster node concurrently.
197  ///
198  /// <https://redis.io/commands/function-delete/>
199  fn function_delete_cluster<S>(&self, library_name: S) -> impl Future<Output = FredResult<()>> + Send
200  where
201    S: Into<Str> + Send,
202  {
203    async move {
204      into!(library_name);
205      commands::lua::function_delete_cluster(self, library_name).await
206    }
207  }
208
209  /// Return the serialized payload of loaded libraries.
210  ///
211  /// <https://redis.io/commands/function-dump/>
212  fn function_dump<R>(&self) -> impl Future<Output = FredResult<R>> + Send
213  where
214    R: FromValue,
215  {
216    async move { commands::lua::function_dump(self).await?.convert() }
217  }
218
219  /// Deletes all the libraries.
220  ///
221  /// <https://redis.io/commands/function-flush/>
222  fn function_flush<R>(&self, r#async: bool) -> impl Future<Output = FredResult<R>> + Send
223  where
224    R: FromValue,
225  {
226    async move { commands::lua::function_flush(self, r#async).await?.convert() }
227  }
228
229  /// Deletes all the libraries on all cluster nodes concurrently.
230  ///
231  /// <https://redis.io/commands/function-flush/>
232  fn function_flush_cluster(&self, r#async: bool) -> impl Future<Output = FredResult<()>> + Send {
233    async move { commands::lua::function_flush_cluster(self, r#async).await }
234  }
235
236  /// Kill a function that is currently executing.
237  ///
238  /// Note: This command runs on a backchannel connection to the server in order to take effect as quickly as
239  /// possible.
240  ///
241  /// <https://redis.io/commands/function-kill/>
242  fn function_kill<R>(&self) -> impl Future<Output = FredResult<R>> + Send
243  where
244    R: FromValue,
245  {
246    async move { commands::lua::function_kill(self).await?.convert() }
247  }
248
249  /// Return information about the functions and libraries.
250  ///
251  /// <https://redis.io/commands/function-list/>
252  fn function_list<R, S>(&self, library_name: Option<S>, withcode: bool) -> impl Future<Output = FredResult<R>> + Send
253  where
254    R: FromValue,
255    S: Into<Str> + Send,
256  {
257    async move {
258      let library_name = library_name.map(|l| l.into());
259      commands::lua::function_list(self, library_name, withcode)
260        .await?
261        .convert()
262    }
263  }
264
265  /// Load a library to Redis.
266  ///
267  /// <https://redis.io/commands/function-load/>
268  fn function_load<R, S>(&self, replace: bool, code: S) -> impl Future<Output = FredResult<R>> + Send
269  where
270    R: FromValue,
271    S: Into<Str> + Send,
272  {
273    async move {
274      into!(code);
275      commands::lua::function_load(self, replace, code).await?.convert()
276    }
277  }
278
279  /// Load a library to Redis on all cluster nodes concurrently.
280  ///
281  /// <https://redis.io/commands/function-load/>
282  fn function_load_cluster<R, S>(&self, replace: bool, code: S) -> impl Future<Output = FredResult<R>> + Send
283  where
284    R: FromValue,
285    S: Into<Str> + Send,
286  {
287    async move {
288      into!(code);
289      commands::lua::function_load_cluster(self, replace, code)
290        .await?
291        .convert()
292    }
293  }
294
295  /// Restore libraries from the serialized payload.
296  ///
297  /// <https://redis.io/commands/function-restore/>
298  ///
299  /// Note: Use `FnPolicy::default()` to use the default function restore policy (`"APPEND"`).
300  fn function_restore<R, B, P>(&self, serialized: B, policy: P) -> impl Future<Output = FredResult<R>> + Send
301  where
302    R: FromValue,
303    B: Into<Bytes> + Send,
304    P: TryInto<FnPolicy> + Send,
305    P::Error: Into<Error> + Send,
306  {
307    async move {
308      into!(serialized);
309      try_into!(policy);
310      commands::lua::function_restore(self, serialized, policy)
311        .await?
312        .convert()
313    }
314  }
315
316  /// Restore libraries from the serialized payload on all cluster nodes concurrently.
317  ///
318  /// <https://redis.io/commands/function-restore/>
319  ///
320  /// Note: Use `FnPolicy::default()` to use the default function restore policy (`"APPEND"`).
321  fn function_restore_cluster<B, P>(&self, serialized: B, policy: P) -> impl Future<Output = FredResult<()>> + Send
322  where
323    B: Into<Bytes> + Send,
324    P: TryInto<FnPolicy> + Send,
325    P::Error: Into<Error> + Send,
326  {
327    async move {
328      into!(serialized);
329      try_into!(policy);
330      commands::lua::function_restore_cluster(self, serialized, policy).await
331    }
332  }
333
334  /// Return information about the function that's currently running and information about the available execution
335  /// engines.
336  ///
337  /// Note: This command runs on a backchannel connection to the server.
338  ///
339  /// <https://redis.io/commands/function-stats/>
340  fn function_stats<R>(&self) -> impl Future<Output = FredResult<R>> + Send
341  where
342    R: FromValue,
343  {
344    async move { commands::lua::function_stats(self).await?.convert() }
345  }
346}