implement client ping (#108)
This commit is contained in:
@@ -26,6 +26,10 @@ struct Cli {
|
|||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum Command {
|
enum Command {
|
||||||
|
Ping {
|
||||||
|
/// Message to ping
|
||||||
|
msg: Option<String>,
|
||||||
|
},
|
||||||
/// Get the value of key.
|
/// Get the value of key.
|
||||||
Get {
|
Get {
|
||||||
/// Name of key to get
|
/// Name of key to get
|
||||||
@@ -85,6 +89,14 @@ async fn main() -> mini_redis::Result<()> {
|
|||||||
|
|
||||||
// Process the requested command
|
// Process the requested command
|
||||||
match cli.command {
|
match cli.command {
|
||||||
|
Command::Ping { msg } => {
|
||||||
|
let value = client.ping(msg).await?;
|
||||||
|
if let Ok(string) = str::from_utf8(&value) {
|
||||||
|
println!("\"{}\"", string);
|
||||||
|
} else {
|
||||||
|
println!("{:?}", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
Command::Get { key } => {
|
Command::Get { key } => {
|
||||||
if let Some(value) = client.get(&key).await? {
|
if let Some(value) = client.get(&key).await? {
|
||||||
if let Ok(string) = str::from_utf8(&value) {
|
if let Ok(string) = str::from_utf8(&value) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//!
|
//!
|
||||||
//! Provides an async connect and methods for issuing the supported commands.
|
//! Provides an async connect and methods for issuing the supported commands.
|
||||||
|
|
||||||
use crate::cmd::{Get, Publish, Set, Subscribe, Unsubscribe};
|
use crate::cmd::{Get, Ping, Publish, Set, Subscribe, Unsubscribe};
|
||||||
use crate::{Connection, Frame};
|
use crate::{Connection, Frame};
|
||||||
|
|
||||||
use async_stream::try_stream;
|
use async_stream::try_stream;
|
||||||
@@ -87,6 +87,42 @@ pub async fn connect<T: ToSocketAddrs>(addr: T) -> crate::Result<Client> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
|
/// Ping to the server.
|
||||||
|
///
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Demonstrates basic usage.
|
||||||
|
/// ```no_run
|
||||||
|
/// use mini_redis::client;
|
||||||
|
///
|
||||||
|
/// #[tokio::main]
|
||||||
|
/// async fn main() {
|
||||||
|
/// let mut client = client::connect("localhost:6379").await.unwrap();
|
||||||
|
///
|
||||||
|
/// let pong = client.ping(None).await.unwrap();
|
||||||
|
/// assert_eq!(b"PONG", &pong[..]);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[instrument(skip(self))]
|
||||||
|
pub async fn ping(&mut self, msg: Option<String>) -> crate::Result<Bytes> {
|
||||||
|
let frame = Ping::new(msg).into_frame();
|
||||||
|
debug!(request = ?frame);
|
||||||
|
|
||||||
|
self.connection.write_frame(&frame).await?;
|
||||||
|
|
||||||
|
match self.read_response().await? {
|
||||||
|
Frame::Simple(value) => Ok(value.into()),
|
||||||
|
Frame::Bulk(value) => Ok(value),
|
||||||
|
frame => Err(frame.to_error()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the value of key.
|
/// Get the value of key.
|
||||||
///
|
///
|
||||||
/// If the key does not exist the special value `None` is returned.
|
/// If the key does not exist the special value `None` is returned.
|
||||||
|
|||||||
@@ -63,4 +63,17 @@ impl Ping {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts the command into an equivalent `Frame`.
|
||||||
|
///
|
||||||
|
/// This is called by the client when encoding a `Ping` command to send
|
||||||
|
/// to the server.
|
||||||
|
pub(crate) fn into_frame(self) -> Frame {
|
||||||
|
let mut frame = Frame::array();
|
||||||
|
frame.push_bulk(Bytes::from("ping".as_bytes()));
|
||||||
|
if let Some(msg) = self.msg {
|
||||||
|
frame.push_bulk(Bytes::from(msg));
|
||||||
|
}
|
||||||
|
frame
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,28 @@ use std::net::SocketAddr;
|
|||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
|
||||||
|
/// A PING PONG test without message provided.
|
||||||
|
/// It should return "PONG".
|
||||||
|
#[tokio::test]
|
||||||
|
async fn ping_pong_without_message() {
|
||||||
|
let (addr, _) = start_server().await;
|
||||||
|
let mut client = client::connect(addr).await.unwrap();
|
||||||
|
|
||||||
|
let pong = client.ping(None).await.unwrap();
|
||||||
|
assert_eq!(b"PONG", &pong[..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A PING PONG test with message provided.
|
||||||
|
/// It should return the message.
|
||||||
|
#[tokio::test]
|
||||||
|
async fn ping_pong_with_message() {
|
||||||
|
let (addr, _) = start_server().await;
|
||||||
|
let mut client = client::connect(addr).await.unwrap();
|
||||||
|
|
||||||
|
let pong = client.ping(Some("你好世界".to_string())).await.unwrap();
|
||||||
|
assert_eq!("你好世界".as_bytes(), &pong[..]);
|
||||||
|
}
|
||||||
|
|
||||||
/// A basic "hello world" style test. A server instance is started in a
|
/// A basic "hello world" style test. A server instance is started in a
|
||||||
/// background task. A client instance is then established and set and get
|
/// background task. A client instance is then established and set and get
|
||||||
/// commands are sent to the server. The response is then evaluated
|
/// commands are sent to the server. The response is then evaluated
|
||||||
|
|||||||
Reference in New Issue
Block a user