glide/executor.rs
1// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
2//! The command dispatch trait.
3//!
4//! [`CommandExecutor`] is the single trait every command family builds on. Both
5//! [`crate::GlideClient`] and [`crate::GlideClusterClient`] implement it. All the
6//! typed command methods live in extension traits with blanket impls over
7//! `CommandExecutor`, so a single implementation of this trait unlocks the entire
8//! command surface.
9
10use crate::ValkeyResult;
11use crate::cmd::Cmd;
12use crate::routes::Route;
13use crate::value::ValkeyValue;
14use crate::write::ToValkeyArgs;
15use async_trait::async_trait;
16
17/// The low-level command execution interface.
18///
19/// Implementors forward a fully-built [`Cmd`] to `glide-core` and return the
20/// decoded [`ValkeyValue`] reply.
21#[async_trait]
22pub trait CommandExecutor: Send + Sync {
23 /// Execute `cmd`, optionally routed to a specific node/set of nodes (cluster).
24 /// Standalone implementations ignore `route`.
25 async fn execute_command(&self, cmd: Cmd, route: Option<Route>) -> ValkeyResult<ValkeyValue>;
26}
27
28/// Convenience helpers layered on top of [`CommandExecutor`], available on every
29/// client. These are the "escape hatches" that guarantee 100% functional command
30/// coverage regardless of which typed wrappers exist.
31#[async_trait]
32pub trait CustomCommand: CommandExecutor {
33 /// Execute an arbitrary command given its already-encoded arguments, e.g.
34 /// `client.custom_command(&["SET", "key", "value"]).await`.
35 ///
36 /// The first argument is the command keyword; the rest are its arguments.
37 async fn custom_command<A>(&self, args: &[A]) -> ValkeyResult<ValkeyValue>
38 where
39 A: ToValkeyArgs + Sync,
40 {
41 let mut cmd = Cmd::new();
42 for a in args {
43 cmd.arg(a);
44 }
45 self.execute_command(cmd, None).await
46 }
47
48 /// Like [`CustomCommand::custom_command`] but routed (cluster). Ignored for
49 /// standalone clients.
50 async fn custom_command_with_route<A>(
51 &self,
52 args: &[A],
53 route: Route,
54 ) -> ValkeyResult<ValkeyValue>
55 where
56 A: ToValkeyArgs + Sync,
57 {
58 let mut cmd = Cmd::new();
59 for a in args {
60 cmd.arg(a);
61 }
62 self.execute_command(cmd, Some(route)).await
63 }
64}
65
66impl<T: CommandExecutor + ?Sized> CustomCommand for T {}