Skip to main content

glide/commands/
server_management.rs

1// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
2//! Server-management commands. Mirrors Python's server-management surface.
3
4use crate::ValkeyResult;
5use crate::cmd::Cmd;
6use crate::commands::options::ClientPauseMode;
7use crate::executor::CommandExecutor;
8use crate::value::FromValkeyValue;
9use crate::value::ValkeyValue;
10use crate::value::to_glide_error;
11use crate::write::ToValkeyArgs;
12use async_trait::async_trait;
13use bytes::Bytes;
14use std::collections::HashMap;
15
16/// Server-management commands (`INFO`, `DBSIZE`, `FLUSHALL`, `CONFIG ...`, `TIME`).
17#[async_trait]
18pub trait ServerManagementCommands: CommandExecutor {
19    /// Get server information and statistics (`INFO`).
20    async fn info(&self) -> ValkeyResult<String> {
21        let mut cmd = Cmd::new();
22        cmd.arg("INFO");
23        String::from_owned_valkey_value(self.execute_command(cmd, None).await?)
24    }
25
26    /// Get server information for specific sections (`INFO section...`).
27    async fn info_sections<S: ToValkeyArgs + Send + Sync>(
28        &self,
29        sections: &[S],
30    ) -> ValkeyResult<String> {
31        let mut cmd = Cmd::new();
32        cmd.arg("INFO");
33        for s in sections {
34            cmd.arg(s);
35        }
36        String::from_owned_valkey_value(self.execute_command(cmd, None).await?)
37    }
38
39    /// Get the number of keys in the current database (`DBSIZE`).
40    async fn dbsize(&self) -> ValkeyResult<i64> {
41        let mut cmd = Cmd::new();
42        cmd.arg("DBSIZE");
43        i64::from_owned_valkey_value(self.execute_command(cmd, None).await?)
44    }
45
46    /// Get configuration parameters matching `parameter` (`CONFIG GET`).
47    async fn config_get<P: ToValkeyArgs + Send>(
48        &self,
49        parameter: P,
50    ) -> ValkeyResult<HashMap<String, Bytes>> {
51        let mut cmd = Cmd::new();
52        cmd.arg("CONFIG").arg("GET").arg(parameter);
53        let map: HashMap<String, Vec<u8>> =
54            FromValkeyValue::from_owned_valkey_value(self.execute_command(cmd, None).await?)?;
55        Ok(map.into_iter().map(|(k, v)| (k, Bytes::from(v))).collect())
56    }
57
58    /// Set a configuration parameter (`CONFIG SET`).
59    async fn config_set<P: ToValkeyArgs + Send, V: ToValkeyArgs + Send>(
60        &self,
61        parameter: P,
62        value: V,
63    ) -> ValkeyResult<()> {
64        let mut cmd = Cmd::new();
65        cmd.arg("CONFIG").arg("SET").arg(parameter).arg(value);
66        <()>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
67    }
68
69    /// Reset configuration statistics (`CONFIG RESETSTAT`).
70    async fn config_resetstat(&self) -> ValkeyResult<()> {
71        let mut cmd = Cmd::new();
72        cmd.arg("CONFIG").arg("RESETSTAT");
73        <()>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
74    }
75
76    /// Get the server time as `(unix_seconds, microseconds)` (`TIME`).
77    async fn time(&self) -> ValkeyResult<(i64, i64)> {
78        let mut cmd = Cmd::new();
79        cmd.arg("TIME");
80        match self.execute_command(cmd, None).await? {
81            ValkeyValue::Array(mut parts) if parts.len() == 2 => {
82                let micros = String::from_owned_valkey_value(parts.pop().unwrap())?;
83                let secs = String::from_owned_valkey_value(parts.pop().unwrap())?;
84                Ok((
85                    secs.parse().unwrap_or_default(),
86                    micros.parse().unwrap_or_default(),
87                ))
88            }
89            other => Err(to_glide_error(other, "Unexpected TIME reply.")),
90        }
91    }
92
93    /// Get the Unix time of the last successful save to disk (`LASTSAVE`).
94    async fn lastsave(&self) -> ValkeyResult<i64> {
95        let mut cmd = Cmd::new();
96        cmd.arg("LASTSAVE");
97        i64::from_owned_valkey_value(self.execute_command(cmd, None).await?)
98    }
99
100    /// Rewrite the configuration file with the in-memory configuration
101    /// (`CONFIG REWRITE`).
102    async fn config_rewrite(&self) -> ValkeyResult<()> {
103        let mut cmd = Cmd::new();
104        cmd.arg("CONFIG").arg("REWRITE");
105        <()>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
106    }
107
108    /// Display a piece of generative art and the server version (`LOLWUT`),
109    /// optionally selecting a rendering `version`.
110    async fn lolwut(&self, version: Option<i64>) -> ValkeyResult<String> {
111        let mut cmd = Cmd::new();
112        cmd.arg("LOLWUT");
113        if let Some(v) = version {
114            cmd.arg("VERSION").arg(v);
115        }
116        String::from_owned_valkey_value(self.execute_command(cmd, None).await?)
117    }
118
119    /// Asynchronously rewrite the append-only file (`BGREWRITEAOF`). Returns the
120    /// server's status message.
121    async fn bgrewriteaof(&self) -> ValkeyResult<String> {
122        let mut cmd = Cmd::new();
123        cmd.arg("BGREWRITEAOF");
124        String::from_owned_valkey_value(self.execute_command(cmd, None).await?)
125    }
126
127    /// Asynchronously save the dataset to disk (`BGSAVE`). Set `schedule` to defer
128    /// until no other save is running. Returns the server's status message.
129    async fn bgsave(&self, schedule: bool) -> ValkeyResult<String> {
130        let mut cmd = Cmd::new();
131        cmd.arg("BGSAVE");
132        if schedule {
133            cmd.arg("SCHEDULE");
134        }
135        String::from_owned_valkey_value(self.execute_command(cmd, None).await?)
136    }
137
138    /// Synchronously save the dataset to disk (`SAVE`).
139    async fn save(&self) -> ValkeyResult<()> {
140        let mut cmd = Cmd::new();
141        cmd.arg("SAVE");
142        <()>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
143    }
144
145    /// Make the server a replica of another instance (`REPLICAOF host port`).
146    async fn replicaof<H: ToValkeyArgs + Send>(&self, host: H, port: i64) -> ValkeyResult<()> {
147        let mut cmd = Cmd::new();
148        cmd.arg("REPLICAOF").arg(host).arg(port);
149        <()>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
150    }
151
152    /// Promote the server to a primary (`REPLICAOF NO ONE`).
153    async fn replicaof_no_one(&self) -> ValkeyResult<()> {
154        let mut cmd = Cmd::new();
155        cmd.arg("REPLICAOF").arg("NO").arg("ONE");
156        <()>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
157    }
158
159    /// Start a coordinated failover between the primary and a replica
160    /// (`FAILOVER`).
161    async fn failover<H: ToValkeyArgs + Send>(
162        &self,
163        to: Option<(H, i64)>,
164        force: bool,
165        timeout_ms: Option<i64>,
166    ) -> ValkeyResult<()> {
167        let mut cmd = Cmd::new();
168        cmd.arg("FAILOVER");
169        if let Some((host, port)) = to {
170            cmd.arg("TO").arg(host).arg(port);
171            if force {
172                cmd.arg("FORCE");
173            }
174        }
175        if let Some(t) = timeout_ms {
176            cmd.arg("TIMEOUT").arg(t);
177        }
178        <()>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
179    }
180
181    /// Abort an in-progress coordinated failover (`FAILOVER ABORT`).
182    async fn failover_abort(&self) -> ValkeyResult<()> {
183        let mut cmd = Cmd::new();
184        cmd.arg("FAILOVER").arg("ABORT");
185        <()>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
186    }
187
188    /// Suspend client commands for up to `timeout_ms` (`CLIENT PAUSE`).
189    async fn client_pause(
190        &self,
191        timeout_ms: i64,
192        mode: Option<ClientPauseMode>,
193    ) -> ValkeyResult<()> {
194        let mut cmd = Cmd::new();
195        cmd.arg("CLIENT").arg("PAUSE").arg(timeout_ms);
196        if let Some(m) = mode {
197            cmd.arg(m.as_arg());
198        }
199        <()>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
200    }
201
202    /// Resume paused clients (`CLIENT UNPAUSE`).
203    async fn client_unpause(&self) -> ValkeyResult<()> {
204        let mut cmd = Cmd::new();
205        cmd.arg("CLIENT").arg("UNPAUSE");
206        <()>::from_owned_valkey_value(self.execute_command(cmd, None).await?)
207    }
208
209    /// Get latency time series for an event (`LATENCY HISTORY`).
210    async fn latency_history<E: ToValkeyArgs + Send>(&self, event: E) -> ValkeyResult<ValkeyValue> {
211        let mut cmd = Cmd::new();
212        cmd.arg("LATENCY").arg("HISTORY").arg(event);
213        self.execute_command(cmd, None).await
214    }
215
216    /// Get the latest latency samples for all events (`LATENCY LATEST`).
217    async fn latency_latest(&self) -> ValkeyResult<ValkeyValue> {
218        let mut cmd = Cmd::new();
219        cmd.arg("LATENCY").arg("LATEST");
220        self.execute_command(cmd, None).await
221    }
222
223    /// Reset latency data, returning the number of event time series reset
224    /// (`LATENCY RESET`).
225    async fn latency_reset<E: ToValkeyArgs + Send + Sync>(
226        &self,
227        events: &[E],
228    ) -> ValkeyResult<i64> {
229        let mut cmd = Cmd::new();
230        cmd.arg("LATENCY").arg("RESET");
231        for e in events {
232            cmd.arg(e);
233        }
234        i64::from_owned_valkey_value(self.execute_command(cmd, None).await?)
235    }
236
237    /// Get a human-readable latency diagnosis report (`LATENCY DOCTOR`).
238    async fn latency_doctor(&self) -> ValkeyResult<String> {
239        let mut cmd = Cmd::new();
240        cmd.arg("LATENCY").arg("DOCTOR");
241        String::from_owned_valkey_value(self.execute_command(cmd, None).await?)
242    }
243
244    /// Get a latency graph for an event (`LATENCY GRAPH`).
245    async fn latency_graph<E: ToValkeyArgs + Send>(&self, event: E) -> ValkeyResult<String> {
246        let mut cmd = Cmd::new();
247        cmd.arg("LATENCY").arg("GRAPH").arg(event);
248        String::from_owned_valkey_value(self.execute_command(cmd, None).await?)
249    }
250}
251
252impl<T: CommandExecutor + ?Sized> ServerManagementCommands for T {}