bevy_event_bus 0.1.0

A Bevy plugin that connects Bevy's event system to external message brokers like Kafka
Documentation
use async_trait::async_trait;
use bevy::prelude::*;
use serde::{Serialize, de::DeserializeOwned};
use std::collections::HashMap;
use std::time::Duration;

use crate::{BusEvent, EventBusBackend, EventBusError};

/// Configuration for Kafka backend
#[derive(Clone)]
pub struct KafkaConfig {
    /// List of Kafka broker addresses
    pub brokers: Vec<String>,
    /// Client ID for Kafka
    pub client_id: String,
    /// Group ID for consumer
    pub group_id: String,
    /// Connection timeout
    pub timeout: Duration,
    /// Additional configuration parameters
    pub properties: HashMap<String, String>,
}

impl Default for KafkaConfig {
    fn default() -> Self {
        Self {
            brokers: vec!["localhost:9092".to_string()],
            client_id: "bevy_event_bus".to_string(),
            group_id: "bevy_event_bus_consumer".to_string(),
            timeout: Duration::from_secs(10),
            properties: HashMap::new(),
        }
    }
}

/// Kafka implementation of the EventBusBackend
pub struct KafkaEventBusBackend {
    config: KafkaConfig,
    // These would be the actual Kafka client libraries in a real implementation
    // producer: KafkaProducer,
    // consumer: KafkaConsumer,
    // Here we're just creating a mock implementation for demonstration
    connected: bool,
    subscriptions: Vec<String>,
}

#[async_trait]
impl EventBusBackend for KafkaEventBusBackend {
    type Config = KafkaConfig;
    
    fn new(config: Self::Config) -> Self {
        // In a real implementation, we'd create the Kafka producer and consumer here
        Self {
            config,
            connected: false,
            subscriptions: Vec::new(),
        }
    }
    
    async fn connect(&mut self) -> Result<(), EventBusError> {
        // In a real implementation, we'd establish connections to Kafka
        info!("Connecting to Kafka brokers: {:?}", self.config.brokers);
        
        // Simulate connection success
        self.connected = true;
        
        Ok(())
    }
    
    async fn disconnect(&mut self) -> Result<(), EventBusError> {
        // In a real implementation, we'd close Kafka connections
        info!("Disconnecting from Kafka");
        
        self.connected = false;
        
        Ok(())
    }
    
    async fn send<T: BusEvent>(&self, event: &T, topic: &str) -> Result<(), EventBusError> {
        if !self.connected {
            return Err(EventBusError::NotConfigured("Kafka not connected".to_string()));
        }
        
        // In a real implementation, we'd serialize and send the event to Kafka
        info!("Sending event to Kafka topic: {}", topic);
        
        // For now, just log that we would send it
        Ok(())
    }
    
    async fn receive<T: BusEvent>(&self, topic: &str) -> Result<Vec<T>, EventBusError> {
        if !self.connected {
            return Err(EventBusError::NotConfigured("Kafka not connected".to_string()));
        }
        
        if !self.subscriptions.contains(&topic.to_string()) {
            return Err(EventBusError::Topic(format!("Not subscribed to topic: {}", topic)));
        }
        
        // In a real implementation, we'd poll Kafka for messages on the topic
        info!("Polling Kafka topic for messages: {}", topic);
        
        // For now, return an empty vector
        Ok(Vec::new())
    }
    
    async fn subscribe(&mut self, topic: &str) -> Result<(), EventBusError> {
        if !self.connected {
            return Err(EventBusError::NotConfigured("Kafka not connected".to_string()));
        }
        
        // In a real implementation, we'd subscribe the consumer to the topic
        info!("Subscribing to Kafka topic: {}", topic);
        
        if !self.subscriptions.contains(&topic.to_string()) {
            self.subscriptions.push(topic.to_string());
        }
        
        Ok(())
    }
    
    async fn unsubscribe(&mut self, topic: &str) -> Result<(), EventBusError> {
        if !self.connected {
            return Err(EventBusError::NotConfigured("Kafka not connected".to_string()));
        }
        
        // In a real implementation, we'd unsubscribe from the topic
        info!("Unsubscribing from Kafka topic: {}", topic);
        
        self.subscriptions.retain(|t| t != topic);
        
        Ok(())
    }
}