use serde::{Deserialize, Serialize};
pub const STREAM_SUBSCRIBE: &str = "max/stream.subscribe";
pub const STREAM_UNSUBSCRIBE: &str = "max/stream.unsubscribe";
pub const STREAM_EVENT: &str = "max/stream.event";
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StreamSubscribeParams {
pub subscription_id: String,
pub event_kinds: Vec<StreamEventKind>,
pub uri_filter: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StreamSubscribeResult {
pub subscription_id: String,
pub status: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StreamUnsubscribeParams {
pub subscription_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StreamUnsubscribeResult {
pub subscription_id: String,
pub events_received: u64,
pub status: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum StreamEventKind {
Diagnostic,
ConformanceChange,
GateChange,
ReceiptAdmission,
LawViolation,
BrokerDecision,
QueuePositionChange,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(tag = "kind", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum AdmissionDecision {
Admitted,
Refused,
Queued { position: u32 },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BrokerDecisionPayload {
pub op: String,
pub decision: AdmissionDecision,
pub receipt_hash: Option<String>,
pub refusal_reason: Option<String>,
}
impl BrokerDecisionPayload {
pub fn admitted(op: impl Into<String>, receipt_hash: impl Into<String>) -> Self {
Self {
op: op.into(),
decision: AdmissionDecision::Admitted,
receipt_hash: Some(receipt_hash.into()),
refusal_reason: None,
}
}
pub fn refused(op: impl Into<String>, reason: impl Into<String>) -> Self {
Self {
op: op.into(),
decision: AdmissionDecision::Refused,
receipt_hash: None,
refusal_reason: Some(reason.into()),
}
}
pub fn queued(op: impl Into<String>, position: u32) -> Self {
Self {
op: op.into(),
decision: AdmissionDecision::Queued { position },
receipt_hash: None,
refusal_reason: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QueuePositionPayload {
pub op: String,
pub position: u32,
pub queue_depth: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StreamEvent {
pub subscription_id: String,
pub sequence: u64,
pub kind: StreamEventKind,
pub payload: serde_json::Value,
pub status: String,
pub timestamp_secs: u64,
}
pub struct StreamBus {
sender: tokio::sync::broadcast::Sender<StreamEvent>,
}
impl StreamBus {
pub fn new(capacity: usize) -> Self {
let (sender, _) = tokio::sync::broadcast::channel(capacity);
Self { sender }
}
pub fn subscribe(&self) -> tokio::sync::broadcast::Receiver<StreamEvent> {
self.sender.subscribe()
}
pub fn publish(&self, event: StreamEvent) -> usize {
self.sender.send(event).unwrap_or(0)
}
pub fn subscriber_count(&self) -> usize {
self.sender.receiver_count()
}
}