hyperstack_sdk/
subscription.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5#[serde(tag = "type", rename_all = "lowercase")]
6pub enum ClientMessage {
7    Subscribe(Subscription),
8    Unsubscribe(Unsubscription),
9    Ping,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
13pub struct Subscription {
14    pub view: String,
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub key: Option<String>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub partition: Option<String>,
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub filters: Option<HashMap<String, String>>,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
24pub struct Unsubscription {
25    pub view: String,
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub key: Option<String>,
28}
29
30impl Unsubscription {
31    pub fn new(view: impl Into<String>) -> Self {
32        Self {
33            view: view.into(),
34            key: None,
35        }
36    }
37
38    pub fn with_key(mut self, key: impl Into<String>) -> Self {
39        self.key = Some(key.into());
40        self
41    }
42
43    pub fn sub_key(&self) -> String {
44        format!("{}:{}", self.view, self.key.as_deref().unwrap_or("*"),)
45    }
46}
47
48impl From<&Subscription> for Unsubscription {
49    fn from(sub: &Subscription) -> Self {
50        Self {
51            view: sub.view.clone(),
52            key: sub.key.clone(),
53        }
54    }
55}
56
57impl Subscription {
58    pub fn new(view: impl Into<String>) -> Self {
59        Self {
60            view: view.into(),
61            key: None,
62            partition: None,
63            filters: None,
64        }
65    }
66
67    pub fn with_key(mut self, key: impl Into<String>) -> Self {
68        self.key = Some(key.into());
69        self
70    }
71
72    pub fn with_filters(mut self, filters: HashMap<String, String>) -> Self {
73        self.filters = Some(filters);
74        self
75    }
76
77    pub fn sub_key(&self) -> String {
78        let filters_str = self
79            .filters
80            .as_ref()
81            .map(|f| serde_json::to_string(f).unwrap_or_default())
82            .unwrap_or_default();
83        format!(
84            "{}:{}:{}:{}",
85            self.view,
86            self.key.as_deref().unwrap_or("*"),
87            self.partition.as_deref().unwrap_or(""),
88            filters_str
89        )
90    }
91}
92
93#[derive(Debug, Default)]
94pub struct SubscriptionRegistry {
95    subscriptions: HashMap<String, Subscription>,
96}
97
98impl SubscriptionRegistry {
99    pub fn new() -> Self {
100        Self::default()
101    }
102
103    pub fn add(&mut self, sub: Subscription) {
104        let key = sub.sub_key();
105        self.subscriptions.insert(key, sub);
106    }
107
108    pub fn remove(&mut self, sub: &Subscription) {
109        let key = sub.sub_key();
110        self.subscriptions.remove(&key);
111    }
112
113    pub fn contains(&self, sub: &Subscription) -> bool {
114        let key = sub.sub_key();
115        self.subscriptions.contains_key(&key)
116    }
117
118    pub fn all(&self) -> Vec<Subscription> {
119        self.subscriptions.values().cloned().collect()
120    }
121
122    #[allow(dead_code)]
123    pub fn clear(&mut self) {
124        self.subscriptions.clear();
125    }
126}