Temporary use nostr-db as a db backend due to breaking API change
    in the library
		
	
			
		
			
				
	
	
		
			157 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
use crate::{
 | 
						|
    noose::user::{User, UserRow},
 | 
						|
    noose::sled::BanInfo,
 | 
						|
    utils::{error::Error, structs::Subscription},
 | 
						|
};
 | 
						|
use nostr::secp256k1::XOnlyPublicKey;
 | 
						|
use std::{collections::HashMap, fmt::Debug};
 | 
						|
use tokio::sync::{broadcast, Mutex};
 | 
						|
 | 
						|
pub mod channels {
 | 
						|
    pub static MSG_NOOSE: &str = "MSG_NOOSE";
 | 
						|
    pub static MSG_NIP05: &str = "MSG_NIP05";
 | 
						|
    pub static MSG_RELAY: &str = "MSG_RELAY";
 | 
						|
    pub static MSG_PIPELINE: &str = "MSG_PIPELINE";
 | 
						|
    pub static MSG_SLED: &str = "MSG_SLED";
 | 
						|
}
 | 
						|
 | 
						|
#[derive(Debug, Clone, PartialEq)]
 | 
						|
pub enum Command {
 | 
						|
    // DbRequest
 | 
						|
    DbReqWriteEvent(/* client_id */ uuid::Uuid, Box<nostr::Event>),
 | 
						|
    DbReqFindEvent(/* client_id*/ uuid::Uuid, Subscription),
 | 
						|
    DbReqDeleteEvents(/* client_id*/ uuid::Uuid, Box<nostr::Event>),
 | 
						|
    DbReqEventCounts(/* client_id*/ uuid::Uuid, Subscription),
 | 
						|
 | 
						|
    // Old messages
 | 
						|
    DbReqInsertUser(UserRow),
 | 
						|
    DbReqGetUser(User),
 | 
						|
    DbReqCreateAccount(XOnlyPublicKey, String, String),
 | 
						|
    DbReqGetAccount(String),
 | 
						|
    DbReqClear,
 | 
						|
    // DbResponse
 | 
						|
    DbResRelayMessages(
 | 
						|
        /* client_id*/ uuid::Uuid,
 | 
						|
        /* Vec<RelayMessage::Event> */ Vec<nostr::RelayMessage>,
 | 
						|
    ),
 | 
						|
    DbResInfo,
 | 
						|
    DbResOk,
 | 
						|
    DbResOkWithStatus(/* client_id */ uuid::Uuid, nostr::RelayMessage),
 | 
						|
    DbResAccount, // TODO: Add Account DTO as a param
 | 
						|
    DbResUser(UserRow),
 | 
						|
    DbResEventCounts(/* client_id */ uuid::Uuid, nostr::RelayMessage),
 | 
						|
    // Event Pipeline
 | 
						|
    PipelineReqEvent(/* client_id */ uuid::Uuid, Box<nostr::Event>),
 | 
						|
    PipelineResRelayMessageOk(/* client_id */ uuid::Uuid, nostr::RelayMessage),
 | 
						|
    PipelineResStreamOutEvent(Box<nostr::Event>),
 | 
						|
    PipelineResOk,
 | 
						|
    // Subscription Errors
 | 
						|
    ClientSubscriptionError(/* error message */ String),
 | 
						|
    // Sled
 | 
						|
    SledReqBanUser(Box<BanInfo>),
 | 
						|
    SledReqBanInfo(/* pubkey */ String),
 | 
						|
    SledReqUnbanUser(/* pubkey */ String),
 | 
						|
    SledReqGetBans,
 | 
						|
    SledResBan(Option<BanInfo>),
 | 
						|
    SledResBans(Vec<BanInfo>),
 | 
						|
    SledResSuccess(bool),
 | 
						|
    // Other
 | 
						|
    Str(String),
 | 
						|
    ServiceError(Error),
 | 
						|
    Noop,
 | 
						|
}
 | 
						|
 | 
						|
#[derive(Debug, Clone)]
 | 
						|
pub struct Message {
 | 
						|
    pub source: &'static str,
 | 
						|
    pub content: Command,
 | 
						|
}
 | 
						|
 | 
						|
#[derive(Debug)]
 | 
						|
pub struct PubSub {
 | 
						|
    subscribers: Mutex<HashMap<String, Vec<broadcast::Sender<Message>>>>,
 | 
						|
}
 | 
						|
 | 
						|
impl Default for PubSub {
 | 
						|
    fn default() -> Self {
 | 
						|
        panic!("Use PubSub::new() to initialize PubSub");
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
impl PubSub {
 | 
						|
    pub fn new() -> Self {
 | 
						|
        PubSub {
 | 
						|
            subscribers: Mutex::new(HashMap::new()),
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    pub async fn subscribe(&self, topic: &str) -> broadcast::Receiver<Message> {
 | 
						|
        let (tx, _rx) = broadcast::channel(32); // 32 is the channel capacity
 | 
						|
        let mut subscribers = self.subscribers.lock().await;
 | 
						|
        subscribers
 | 
						|
            .entry(topic.to_string())
 | 
						|
            .or_insert_with(Vec::new)
 | 
						|
            .push(tx.clone());
 | 
						|
        tx.subscribe()
 | 
						|
    }
 | 
						|
 | 
						|
    pub async fn publish(&self, topic: &str, message: Message) {
 | 
						|
        let mut subscribers = self.subscribers.lock().await;
 | 
						|
        if let Some(queue) = subscribers.get_mut(topic) {
 | 
						|
            for sender in queue.iter() {
 | 
						|
                sender.send(message.clone()).ok();
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// #[cfg(test)]
 | 
						|
// mod tests {
 | 
						|
//     use super::channels;
 | 
						|
//     use crate::bussy::{Command, Message, PubSub};
 | 
						|
//     use std::sync::Arc;
 | 
						|
 | 
						|
//     #[tokio::test]
 | 
						|
//     async fn create_bus() {
 | 
						|
//         let pubsub = Arc::new(PubSub::new());
 | 
						|
 | 
						|
//         let mut subscriber1 = pubsub.subscribe(channels::MSG_NIP05).await;
 | 
						|
//         let mut subscriber2 = pubsub.subscribe(channels::MSG_NOOSE).await;
 | 
						|
 | 
						|
//         tokio::spawn(async move {
 | 
						|
//             while let Ok(message) = subscriber1.recv().await {
 | 
						|
//                 println!("Subscriber1 received: {:?}", message);
 | 
						|
//             }
 | 
						|
//         });
 | 
						|
 | 
						|
//         tokio::spawn(async move {
 | 
						|
//             while let Ok(message) = subscriber2.recv().await {
 | 
						|
//                 println!("Subscriber2 received: {:?}", message);
 | 
						|
//             }
 | 
						|
//         });
 | 
						|
 | 
						|
//         pubsub
 | 
						|
//             .publish(
 | 
						|
//                 channels::MSG_NIP05,
 | 
						|
//                 Message {
 | 
						|
//                     source: "test",
 | 
						|
//                     content: Command::Str("Hello S1".to_string()),
 | 
						|
//                 },
 | 
						|
//             )
 | 
						|
//             .await;
 | 
						|
//         pubsub
 | 
						|
//             .publish(
 | 
						|
//                 channels::MSG_NOOSE,
 | 
						|
//                 Message {
 | 
						|
//                     source: "test",
 | 
						|
//                     content: Command::Str("Hello S2".to_string()),
 | 
						|
//                 },
 | 
						|
//             )
 | 
						|
//             .await;
 | 
						|
 | 
						|
//         dbg!(pubsub);
 | 
						|
 | 
						|
//         // Sleep to keep the main thread alive while messages are processed in the background.
 | 
						|
//         tokio::time::sleep(std::time::Duration::from_secs(1)).await;
 | 
						|
//     }
 | 
						|
// }
 |