use async_trait::async_trait;
use serde_json::Value;
use std::{collections::HashMap, sync::Arc};
use tokio::sync::RwLock;
struct CustomPubSubAdapter {
subscriptions: Arc<RwLock<HashMap<String, Vec<(String, String)>>>>,
engine: Arc<Engine>,
}
#[async_trait]
impl PubSubAdapter for CustomPubSubAdapter {
async fn publish(&self, topic: &str, event_data: Value) {
let subs = self.subscriptions.read().await;
if let Some(subscribers) = subs.get(topic) {
for (id, function_id) in subscribers {
let engine = Arc::clone(&self.engine);
let function_id = function_id.clone();
let event_data = event_data.clone();
// Spawn async task to invoke function
tokio::spawn(async move {
let _ = engine.call(&function_id, event_data).await;
});
}
}
}
async fn subscribe(&self, topic: &str, id: &str, function_id: &str) {
let mut subs = self.subscriptions.write().await;
subs.entry(topic.to_string())
.or_insert_with(Vec::new)
.push((id.to_string(), function_id.to_string()));
}
async fn unsubscribe(&self, topic: &str, id: &str) {
let mut subs = self.subscriptions.write().await;
if let Some(subscribers) = subs.get_mut(topic) {
subscribers.retain(|(sub_id, _)| sub_id != id);
// Clean up empty topics
if subscribers.is_empty() {
subs.remove(topic);
}
}
}
}