use std::{collections::HashMap, sync::atomic::AtomicU32};
use serde_json::Value;
use tokio::sync::{
Mutex,
oneshot::{Receiver, Sender, channel},
};
pub enum Response {
Success(Value),
Error(Value),
}
pub struct RpcHelper {
max: AtomicU32,
ongoing: Mutex<HashMap<u32, Sender<Response>>>,
}
impl RpcHelper {
pub fn new() -> RpcHelper {
RpcHelper {
max: AtomicU32::new(1),
ongoing: Mutex::new(HashMap::new()),
}
}
pub async fn add(&self) -> (Receiver<Response>, u32) {
let mut ongoing: tokio::sync::MutexGuard<'_, HashMap<u32, Sender<Response>>> =
self.ongoing.lock().await;
let id = self.max.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
let (tx, rx) = channel::<Response>();
ongoing.insert(id, tx);
(rx, id)
}
pub async fn complete(&self, id: u32, response: Response) -> bool {
let mut ongoing: tokio::sync::MutexGuard<'_, HashMap<u32, Sender<Response>>> =
self.ongoing.lock().await;
let response_sender = ongoing.remove(&id);
if let Some(sender) = response_sender {
sender.send(response).is_ok()
} else {
false
}
}
}