use crate::service::{self, Service, ServiceError};
use dashmap::DashMap;
use std::sync::{Arc, OnceLock};
use tokio::sync::oneshot;
static SERVICE_ID_KVS: OnceLock<usize> = OnceLock::new();
pub fn dispatch(command: Command) -> Result<(), ServiceError> {
let service_id = *SERVICE_ID_KVS.get_or_init(|| service::get_service_id("kvs").unwrap());
service::dispatch(service_id, command)
}
#[derive(Debug)]
pub enum Command {
Get {
key: String,
response: oneshot::Sender<Option<String>>,
},
Set { key: String, value: String },
Delete { key: String },
Exists {
key: String,
response: oneshot::Sender<bool>,
},
ListKeys {
response: oneshot::Sender<Vec<String>>,
},
}
#[derive(Debug, Clone)]
pub struct KeyValueStore {
store: Arc<DashMap<String, String>>,
}
impl KeyValueStore {
pub fn new() -> Self {
KeyValueStore {
store: Arc::new(DashMap::new()),
}
}
}
impl Default for KeyValueStore {
fn default() -> Self {
Self::new()
}
}
impl Service for KeyValueStore {
type Command = Command;
async fn handle(&mut self, cmd: Self::Command) {
match cmd {
Command::Get { key, response } => {
let value = self.store.get(&key).map(|v| v.value().clone());
let _ = response.send(value);
}
Command::Set { key, value } => {
self.store.insert(key, value);
}
Command::Delete { key } => {
self.store.remove(&key);
}
Command::Exists { key, response } => {
let exists = self.store.contains_key(&key);
let _ = response.send(exists);
}
Command::ListKeys { response } => {
let keys: Vec<String> =
self.store.iter().map(|entry| entry.key().clone()).collect();
let _ = response.send(keys);
}
}
}
}