zopp_events/
lib.rs

1//! Event bus abstraction for zopp secret change notifications.
2//!
3//! This crate defines the EventBus trait that allows different implementations
4//! for event broadcasting across server replicas:
5//! - Memory (single server, tokio broadcast channels)
6//! - Redis (multi-server, Redis pub/sub)
7//! - Postgres (multi-server, PostgreSQL LISTEN/NOTIFY)
8
9use async_trait::async_trait;
10use futures::Stream;
11use std::pin::Pin;
12use thiserror::Error;
13use zopp_storage::EnvironmentId;
14
15/// Type of secret change event
16#[derive(Clone, Debug, PartialEq, Eq)]
17pub enum EventType {
18    Created,
19    Updated,
20    Deleted,
21}
22
23/// Event representing a change to a secret in an environment
24#[derive(Clone, Debug)]
25pub struct SecretChangeEvent {
26    pub event_type: EventType,
27    pub key: String,
28    pub version: i64,
29    pub timestamp: i64,
30}
31
32/// Error type for event bus operations
33#[derive(Debug, Error)]
34pub enum EventBusError {
35    #[error("backend error: {0}")]
36    Backend(String),
37}
38
39/// Stream of secret change events
40pub type EventStream = Pin<Box<dyn Stream<Item = SecretChangeEvent> + Send>>;
41
42/// Event bus trait for publishing and subscribing to secret change events.
43///
44/// Implementations can be:
45/// - In-memory (single server): tokio broadcast channels
46/// - Redis: Redis pub/sub
47/// - Postgres: PostgreSQL LISTEN/NOTIFY
48#[async_trait]
49pub trait EventBus: Send + Sync {
50    /// Publish a secret change event to all watchers of this environment.
51    ///
52    /// This is called after a secret is created, updated, or deleted.
53    /// The event is broadcast to all active subscribers for this environment.
54    async fn publish(
55        &self,
56        env_id: &EnvironmentId,
57        event: SecretChangeEvent,
58    ) -> Result<(), EventBusError>;
59
60    /// Subscribe to secret change events for an environment.
61    ///
62    /// Returns a stream that yields events as they occur.
63    /// The stream will continue until dropped or the connection is closed.
64    async fn subscribe(&self, env_id: &EnvironmentId) -> Result<EventStream, EventBusError>;
65}