1use crate::context::{ActorContext, CorrelationId, TenantId, TraceContext};
2use crate::error::AppResult;
3use async_trait::async_trait;
4use chrono::{DateTime, Utc};
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7use std::fmt::Debug;
8
9pub type EventPayload = Value;
10
11#[derive(Debug, Clone, Deserialize, Serialize)]
12pub struct EventEnvelope {
13 pub event_id: String,
14 pub event_name: String,
15 pub event_version: u16,
16 pub source_module: String,
17 pub subject: String,
18 pub tenant_id: Option<TenantId>,
19 pub actor: ActorContext,
20 pub occurred_at: DateTime<Utc>,
21 pub correlation_id: CorrelationId,
22 pub causation_id: Option<String>,
23 pub trace: TraceContext,
24 pub payload: EventPayload,
25 pub schema_ref: String,
26}
27
28#[async_trait]
29pub trait EventPublisher: Debug + Send + Sync {
30 async fn publish(&self, event: EventEnvelope) -> AppResult<()>;
31}
32
33#[derive(Debug, Default)]
34pub struct NoopEventPublisher;
35
36#[async_trait]
37impl EventPublisher for NoopEventPublisher {
38 async fn publish(&self, _event: EventEnvelope) -> AppResult<()> {
39 Ok(())
40 }
41}
42
43#[derive(Debug, Default)]
44pub struct LoggingEventPublisher;
45
46#[async_trait]
47impl EventPublisher for LoggingEventPublisher {
48 async fn publish(&self, event: EventEnvelope) -> AppResult<()> {
49 tracing::info!(
50 event_id = %event.event_id,
51 event_name = %event.event_name,
52 source_module = %event.source_module,
53 subject = %event.subject,
54 correlation_id = %event.correlation_id.0,
55 "module event published"
56 );
57 Ok(())
58 }
59}