use std::collections::HashMap;
+use std::error::Error;
use std::sync::{Arc, Mutex};
use bytes::Bytes;
type Db = Arc<Mutex<HashMap<String, Bytes>>>;
+const LISTEN: &str = "127.0.0.1:6379";
+
#[tokio::main]
async fn main() {
- let listener = TcpListener::bind("127.0.0.1:6379").await.unwrap();
+ env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init();
+
+ let listener = TcpListener::bind(LISTEN).await.unwrap();
+ log::info!("Listening on {}", LISTEN);
let db: Db = Arc::new(Mutex::new(HashMap::new()));
loop {
- // The second item contains the IP and port of the new connection
- let (socket, _) = listener.accept().await.unwrap();
- let db_i = db.clone();
- tokio::spawn(async move { process(socket, db_i).await });
+ match listener.accept().await {
+ Ok((socket, addr)) => {
+ log::debug!("got connection from {:?}", addr);
+ let db_i = db.clone();
+ tokio::spawn(async move {
+ if let Err(e) = process(socket, db_i).await {
+ log::warn!("failed: {:?}", e);
+ }
+ });
+ },
+ Err(e) => log::warn!("Failed to accept connection: {}", e),
+ };
}
}
-async fn process(socket: TcpStream, db: Db) {
+async fn process(socket: TcpStream, db: Db) -> Result<(), Box<dyn Error + Send + Sync>> {
let mut connection = Connection::new(socket);
- while let Some(frame) = connection.read_frame().await.unwrap() {
- let response = match Command::from_frame(frame).unwrap() {
+ while let Some(frame) = connection.read_frame().await? {
+ let response = match Command::from_frame(frame)? {
Set(cmd) => {
// The value is stored as `Vec<u8>`
db.lock().unwrap().insert(cmd.key().to_string(), cmd.value().clone());
+ log::debug!("Set {} → {:?}", &cmd.key(), &cmd.value());
Frame::Simple("OK".to_string())
}
Get(cmd) => {
if let Some(value) = db.lock().unwrap().get(cmd.key()) {
+ log::debug!("Get {} → {:?}", &cmd.key(), &value);
Frame::Bulk(value.clone())
} else {
+ log::debug!("Get {} unknown key", &cmd.key());
Frame::Null
}
}
};
// Write the response to the client
- connection.write_frame(&response).await.unwrap();
+ connection.write_frame(&response).await?;
}
+ Ok(())
}