Skip to main content

awsim_core/
request_event.rs

1use serde::Serialize;
2use tokio::sync::broadcast;
3
4#[derive(Debug, Clone, Serialize)]
5pub struct RequestEvent {
6    pub id: String,
7    pub ts: f64,
8    pub method: String,
9    pub path: String,
10    pub service: String,
11    pub operation: Option<String>,
12    pub account_id: String,
13    pub region: String,
14    pub principal_arn: Option<String>,
15    pub status_code: u16,
16    pub duration_ms: f64,
17    pub request_size: u64,
18    pub response_size: u64,
19    pub error_code: Option<String>,
20}
21
22#[derive(Clone, Debug)]
23pub struct RequestEventBus {
24    sender: broadcast::Sender<RequestEvent>,
25}
26
27impl RequestEventBus {
28    pub fn new() -> Self {
29        let (sender, _) = broadcast::channel(256);
30        Self { sender }
31    }
32
33    pub fn publish(&self, event: RequestEvent) {
34        let _ = self.sender.send(event);
35    }
36
37    pub fn subscribe(&self) -> broadcast::Receiver<RequestEvent> {
38        self.sender.subscribe()
39    }
40
41    pub fn sender(&self) -> &broadcast::Sender<RequestEvent> {
42        &self.sender
43    }
44}
45
46impl Default for RequestEventBus {
47    fn default() -> Self {
48        Self::new()
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55
56    #[tokio::test]
57    async fn broadcast_round_trip() {
58        let bus = RequestEventBus::new();
59        let mut rx = bus.subscribe();
60        let event = RequestEvent {
61            id: "req-1".to_string(),
62            ts: 1735041600.123,
63            method: "POST".to_string(),
64            path: "/".to_string(),
65            service: "s3".to_string(),
66            operation: Some("PutObject".to_string()),
67            account_id: "000000000000".to_string(),
68            region: "us-east-1".to_string(),
69            principal_arn: None,
70            status_code: 200,
71            duration_ms: 12.5,
72            request_size: 1024,
73            response_size: 256,
74            error_code: None,
75        };
76        bus.publish(event.clone());
77        let received = rx.recv().await.expect("receive event");
78        assert_eq!(received.id, event.id);
79        assert_eq!(received.service, "s3");
80        assert_eq!(received.operation.as_deref(), Some("PutObject"));
81        assert_eq!(received.status_code, 200);
82    }
83}