use acty::{Actor, ActorExt, AsyncClose};
use futures::{Stream, StreamExt};
use std::collections::HashMap;
use std::pin::pin;
use std::time::Duration;
use tokio::sync::oneshot;
struct DbActor;
enum DbMessage {
Set {
key: String,
value: String,
responder: oneshot::Sender<()>,
},
Get {
key: String,
responder: oneshot::Sender<Option<String>>,
},
}
impl Actor for DbActor {
type Message = DbMessage;
async fn run(self, inbox: impl Stream<Item = Self::Message> + Send) {
let mut inbox = pin!(inbox);
let mut storage = HashMap::new();
println!("DbActor: Online. Ready to serve requests.");
while let Some(msg) = inbox.next().await {
match msg {
DbMessage::Set {
key,
value,
responder,
} => {
println!(
"DbActor: Received SET for key '{}'. Simulating write delay...",
key
);
tokio::time::sleep(Duration::from_millis(100)).await;
storage.insert(key.clone(), value);
println!("DbActor: Key '{}' set successfully.", key);
responder.send(()).unwrap_or(());
}
DbMessage::Get { key, responder } => {
println!(
"DbActor: Received GET for key '{}'. Simulating read delay...",
key
);
tokio::time::sleep(Duration::from_millis(50)).await;
let value = storage.get(&key).cloned();
println!("DbActor: Responding for key '{}'.", key);
responder.send(value).unwrap_or(());
}
}
}
println!("DbActor: Shutting down.");
}
}
#[tokio::main]
async fn main() {
let db = DbActor.start();
let (tx1, rx1) = oneshot::channel();
let set_msg = DbMessage::Set {
key: "name".to_string(),
value: "acty".to_string(),
responder: tx1,
};
db.send(set_msg).unwrap_or(());
rx1.await.unwrap();
println!("Main: SET operation confirmed.\n");
let (tx2, rx2) = oneshot::channel();
let get_msg_1 = DbMessage::Get {
key: "name".to_string(),
responder: tx2,
};
db.send(get_msg_1).unwrap_or(());
let value1 = rx2.await.unwrap();
println!("Main: Got value: {:?}", value1);
assert_eq!(value1, Some("acty".to_string()));
println!();
let (tx3, rx3) = oneshot::channel();
let get_msg_2 = DbMessage::Get {
key: "version".to_string(),
responder: tx3,
};
db.send(get_msg_2).unwrap_or(());
let value2 = rx3.await.unwrap();
println!("Main: Got value: {:?}", value2);
assert_eq!(value2, None);
println!();
db.close().await;
println!("Main: Actor closed gracefully.");
}