hyperstack_sdk/
subscription.rs1use 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}