From 098305fcbcb11b65b55f5969b346ba8fc77cd13c Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Fri, 16 Sep 2022 13:49:23 +0200 Subject: [PATCH] tokio-tutorial-mini-redis: Initial protocol Implement GET/SET, without shared state yet. Move the original API demo as an example. Run it with cargo run --example hello-redis --- .../examples/hello-redis.rs | 17 +++++++ tokio-tutorial-mini-redis/src/main.rs | 48 +++++++++++++++---- 2 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 tokio-tutorial-mini-redis/examples/hello-redis.rs diff --git a/tokio-tutorial-mini-redis/examples/hello-redis.rs b/tokio-tutorial-mini-redis/examples/hello-redis.rs new file mode 100644 index 0000000..a498655 --- /dev/null +++ b/tokio-tutorial-mini-redis/examples/hello-redis.rs @@ -0,0 +1,17 @@ +use mini_redis::{client, Result}; + +#[tokio::main] +async fn main() -> Result<()> { + // Open a connection to the mini-redis address. + let mut client = client::connect("127.0.0.1:6379").await?; + + // Set the key "hello" with value "world" + client.set("hello", "world".into()).await?; + + // Get key "hello" + let result = client.get("hello").await?; + + println!("got value from the server; result={:?}", result); + + Ok(()) +} diff --git a/tokio-tutorial-mini-redis/src/main.rs b/tokio-tutorial-mini-redis/src/main.rs index a498655..d255ab3 100644 --- a/tokio-tutorial-mini-redis/src/main.rs +++ b/tokio-tutorial-mini-redis/src/main.rs @@ -1,17 +1,45 @@ -use mini_redis::{client, Result}; +use std::collections::HashMap; + +use mini_redis::{Connection, Frame}; +use mini_redis::Command::{self, Get, Set}; +use tokio::net::{TcpListener, TcpStream}; #[tokio::main] -async fn main() -> Result<()> { - // Open a connection to the mini-redis address. - let mut client = client::connect("127.0.0.1:6379").await?; +async fn main() { + let listener = TcpListener::bind("127.0.0.1:6379").await.unwrap(); - // Set the key "hello" with value "world" - client.set("hello", "world".into()).await?; + loop { + // The second item contains the IP and port of the new connection + let (socket, _) = listener.accept().await.unwrap(); + tokio::spawn(async move { process(socket).await }); + } +} - // Get key "hello" - let result = client.get("hello").await?; +async fn process(socket: TcpStream) { + let mut db = HashMap::new(); + let mut connection = Connection::new(socket); - println!("got value from the server; result={:?}", result); + while let Some(frame) = connection.read_frame().await.unwrap() { + let response = match Command::from_frame(frame).unwrap() { + Set(cmd) => { + // The value is stored as `Vec` + db.insert(cmd.key().to_string(), cmd.value().to_vec()); + Frame::Simple("OK".to_string()) + } + Get(cmd) => { + if let Some(value) = db.get(cmd.key()) { + // `Frame::Bulk` expects data to be of type `Bytes`. This + // type will be covered later in the tutorial. For now, + // `&Vec` is converted to `Bytes` using `into()`. + Frame::Bulk(value.clone().into()) + } else { + Frame::Null + } + } + cmd => panic!("unimplemented {:?}", cmd), + }; - Ok(()) + // Write the response to the client + connection.write_frame(&response).await.unwrap(); + } } -- 2.39.5