support PING command for easy testing (#90)
Signed-off-by: tison <wander4096@gmail.com>
This commit is contained in:
@@ -10,6 +10,9 @@ pub use set::Set;
|
|||||||
mod subscribe;
|
mod subscribe;
|
||||||
pub use subscribe::{Subscribe, Unsubscribe};
|
pub use subscribe::{Subscribe, Unsubscribe};
|
||||||
|
|
||||||
|
mod ping;
|
||||||
|
pub use ping::Ping;
|
||||||
|
|
||||||
mod unknown;
|
mod unknown;
|
||||||
pub use unknown::Unknown;
|
pub use unknown::Unknown;
|
||||||
|
|
||||||
@@ -25,6 +28,7 @@ pub enum Command {
|
|||||||
Set(Set),
|
Set(Set),
|
||||||
Subscribe(Subscribe),
|
Subscribe(Subscribe),
|
||||||
Unsubscribe(Unsubscribe),
|
Unsubscribe(Unsubscribe),
|
||||||
|
Ping(Ping),
|
||||||
Unknown(Unknown),
|
Unknown(Unknown),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +62,7 @@ impl Command {
|
|||||||
"set" => Command::Set(Set::parse_frames(&mut parse)?),
|
"set" => Command::Set(Set::parse_frames(&mut parse)?),
|
||||||
"subscribe" => Command::Subscribe(Subscribe::parse_frames(&mut parse)?),
|
"subscribe" => Command::Subscribe(Subscribe::parse_frames(&mut parse)?),
|
||||||
"unsubscribe" => Command::Unsubscribe(Unsubscribe::parse_frames(&mut parse)?),
|
"unsubscribe" => Command::Unsubscribe(Unsubscribe::parse_frames(&mut parse)?),
|
||||||
|
"ping" => Command::Ping(Ping::parse_frames(&mut parse)?),
|
||||||
_ => {
|
_ => {
|
||||||
// The command is not recognized and an Unknown command is
|
// The command is not recognized and an Unknown command is
|
||||||
// returned.
|
// returned.
|
||||||
@@ -95,6 +100,7 @@ impl Command {
|
|||||||
Publish(cmd) => cmd.apply(db, dst).await,
|
Publish(cmd) => cmd.apply(db, dst).await,
|
||||||
Set(cmd) => cmd.apply(db, dst).await,
|
Set(cmd) => cmd.apply(db, dst).await,
|
||||||
Subscribe(cmd) => cmd.apply(db, dst, shutdown).await,
|
Subscribe(cmd) => cmd.apply(db, dst, shutdown).await,
|
||||||
|
Ping(cmd) => cmd.apply(dst).await,
|
||||||
Unknown(cmd) => cmd.apply(dst).await,
|
Unknown(cmd) => cmd.apply(dst).await,
|
||||||
// `Unsubscribe` cannot be applied. It may only be received from the
|
// `Unsubscribe` cannot be applied. It may only be received from the
|
||||||
// context of a `Subscribe` command.
|
// context of a `Subscribe` command.
|
||||||
@@ -110,6 +116,7 @@ impl Command {
|
|||||||
Command::Set(_) => "set",
|
Command::Set(_) => "set",
|
||||||
Command::Subscribe(_) => "subscribe",
|
Command::Subscribe(_) => "subscribe",
|
||||||
Command::Unsubscribe(_) => "unsubscribe",
|
Command::Unsubscribe(_) => "unsubscribe",
|
||||||
|
Command::Ping(_) => "ping",
|
||||||
Command::Unknown(cmd) => cmd.get_name(),
|
Command::Unknown(cmd) => cmd.get_name(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
66
src/cmd/ping.rs
Normal file
66
src/cmd/ping.rs
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
use crate::{Connection, Frame, Parse, ParseError};
|
||||||
|
use bytes::Bytes;
|
||||||
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
|
/// Returns PONG if no argument is provided, otherwise
|
||||||
|
/// return a copy of the argument as a bulk.
|
||||||
|
///
|
||||||
|
/// This command is often used to test if a connection
|
||||||
|
/// is still alive, or to measure latency.
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Ping {
|
||||||
|
/// optional message to be returned
|
||||||
|
msg: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ping {
|
||||||
|
/// Create a new `Ping` command with optional `msg`.
|
||||||
|
pub fn new(msg: Option<String>) -> Ping {
|
||||||
|
Ping { msg }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a `Ping` instance from a received frame.
|
||||||
|
///
|
||||||
|
/// The `Parse` argument provides a cursor-like API to read fields from the
|
||||||
|
/// `Frame`. At this point, the entire frame has already been received from
|
||||||
|
/// the socket.
|
||||||
|
///
|
||||||
|
/// The `PING` string has already been consumed.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// Returns the `Ping` value on success. If the frame is malformed, `Err` is
|
||||||
|
/// returned.
|
||||||
|
///
|
||||||
|
/// # Format
|
||||||
|
///
|
||||||
|
/// Expects an array frame containing `PING` and an optional message.
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// PING [message]
|
||||||
|
/// ```
|
||||||
|
pub(crate) fn parse_frames(parse: &mut Parse) -> crate::Result<Ping> {
|
||||||
|
match parse.next_string() {
|
||||||
|
Ok(msg) => Ok(Ping::new(Some(msg))),
|
||||||
|
Err(ParseError::EndOfStream) => Ok(Ping::default()),
|
||||||
|
Err(e) => Err(e.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Apply the `Ping` command and return the message.
|
||||||
|
///
|
||||||
|
/// The response is written to `dst`. This is called by the server in order
|
||||||
|
/// to execute a received command.
|
||||||
|
#[instrument(skip(self, dst))]
|
||||||
|
pub(crate) async fn apply(self, dst: &mut Connection) -> crate::Result<()> {
|
||||||
|
let response = match self.msg {
|
||||||
|
None => Frame::Simple("PONG".to_string()),
|
||||||
|
Some(msg) => Frame::Bulk(Bytes::from(msg)),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write the response back to the client
|
||||||
|
dst.write_frame(&response).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user