1 use std::collections::HashMap;
3 use std::sync::{Arc, Mutex};
6 use mini_redis::{Connection, Frame};
7 use mini_redis::Command::{self, Get, Set};
8 use tokio::net::{TcpListener, TcpStream};
10 type Db = Arc<Mutex<HashMap<String, Bytes>>>;
12 const LISTEN: &str = "127.0.0.1:6379";
16 env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init();
18 let listener = TcpListener::bind(LISTEN).await.unwrap();
19 log::info!("Listening on {}", LISTEN);
20 let db: Db = Arc::new(Mutex::new(HashMap::new()));
23 match listener.accept().await {
24 Ok((socket, addr)) => {
25 log::debug!("got connection from {:?}", addr);
26 let db_i = db.clone();
27 tokio::spawn(async move {
28 if let Err(e) = process(socket, db_i).await {
29 log::warn!("failed: {:?}", e);
33 Err(e) => log::warn!("Failed to accept connection: {}", e),
38 async fn process(socket: TcpStream, db: Db) -> Result<(), Box<dyn Error + Send + Sync>> {
39 let mut connection = Connection::new(socket);
41 while let Some(frame) = connection.read_frame().await? {
42 let response = match Command::from_frame(frame)? {
44 // The value is stored as `Vec<u8>`
45 db.lock().unwrap().insert(cmd.key().to_string(), cmd.value().clone());
46 log::debug!("Set {} → {:?}", &cmd.key(), &cmd.value());
47 Frame::Simple("OK".to_string())
50 if let Some(value) = db.lock().unwrap().get(cmd.key()) {
51 log::debug!("Get {} → {:?}", &cmd.key(), &value);
52 Frame::Bulk(value.clone())
54 log::debug!("Get {} unknown key", &cmd.key());
58 cmd => panic!("unimplemented {:?}", cmd),
61 // Write the response to the client
62 connection.write_frame(&response).await?;