Skip to main content

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 {}