flippico_cache/types/
channels.rs

1use redis::{FromRedisValue, RedisResult, ToRedisArgs, Value};
2use serde::{Deserialize, Serialize};
3
4#[derive(Serialize, PartialEq, Debug, Deserialize)]
5pub enum SubscriptionChannel {
6    Amadeus,
7    Notifica,
8    BajkomatApi,
9    Shopify,
10}
11
12impl SubscriptionChannel {
13    pub fn get_channel(&self) -> &'static str {
14        match self {
15            SubscriptionChannel::Amadeus => "AMADEUS_CHANNEL",
16            SubscriptionChannel::Notifica => "NOTIFICA_CHANNEL",
17            SubscriptionChannel::BajkomatApi => "BAJKOMAT_API_CHANNEL",
18            SubscriptionChannel::Shopify => "SHOPIFY_CHANNEL",
19        }
20    }
21
22    pub fn from_channel(value: &str) -> Option<Self> {
23        [
24            SubscriptionChannel::Amadeus,
25            SubscriptionChannel::BajkomatApi,
26            SubscriptionChannel::Notifica,
27            SubscriptionChannel::Shopify,
28        ]
29        .into_iter()
30        .find(|variant| variant.get_channel() == value)
31    }
32}
33
34#[derive(Serialize, PartialEq, Debug, Deserialize)]
35pub enum ListChannel {
36    Amadeus,
37    Notifica,
38    BajkomatApi,
39    Shopify,
40}
41
42impl ListChannel {
43    pub fn get_channel(&self) -> &'static str {
44        match self {
45            ListChannel::Amadeus => "AMADEUS_LIST",
46            ListChannel::Notifica => "NOTIFICA_LIST",
47            ListChannel::BajkomatApi => "BAJKOMAT_API_LIST",
48            ListChannel::Shopify => "SHOPIFY_LIST",
49        }
50    }
51    pub fn from_channel(value: &str) -> Option<Self> {
52        [
53            ListChannel::Amadeus,
54            ListChannel::BajkomatApi,
55            ListChannel::Notifica,
56            ListChannel::Shopify,
57        ]
58        .into_iter()
59        .find(|variant| variant.get_channel() == value)
60    }
61}
62
63pub enum CacheSpace {
64    Amadeus,
65    Notifica,
66    BajkomatApi,
67    Shopify,
68}
69
70impl CacheSpace {
71    pub fn get_space(&self) -> &'static str {
72        match self {
73            CacheSpace::Amadeus => "AMADEUS_CACHE",
74            CacheSpace::Notifica => "NOTIFICA_CACHE",
75            CacheSpace::BajkomatApi => "BAJKOMAT_API_CACHE",
76            CacheSpace::Shopify => "SHOPIFY_CACHE",
77        }
78    }
79}
80
81#[derive(Serialize, PartialEq, Debug, Deserialize)]
82pub struct ChannelMessage {
83    pub meta: Option<MessageMeta>,
84    pub channel: SubscriptionChannel,
85    pub body: Option<serde_json::Value>,
86}
87
88#[derive(Serialize, PartialEq, Debug, Deserialize)]
89pub struct MessageMeta {
90    pub app_name: String,
91}
92
93#[derive(Serialize, PartialEq, Debug, Deserialize)]
94pub struct ListMessage {
95    pub meta: Option<MessageMeta>,
96    pub body: Option<serde_json::Value>,
97}
98
99#[derive(Serialize, PartialEq, Debug, Deserialize)]
100pub struct CacheValue<T> {
101    pub meta: Option<MessageMeta>,
102    pub value: Option<T>,
103}
104
105impl From<String> for SubscriptionChannel {
106    fn from(value: String) -> Self {
107        SubscriptionChannel::from_channel(&value).expect("Invalid channel string")
108    }
109}
110
111impl FromRedisValue for ChannelMessage {
112    fn from_redis_value(v: &Value) -> RedisResult<Self> {
113        match v {
114            Value::Array(items) => {
115                if items.len() < 2 {
116                    return Err((redis::ErrorKind::TypeError, "Not enough items").into());
117                }
118                let channel: String = redis::from_redis_value(&items[0])?;
119                let mut body: Option<String> = None;
120                for chunk in items[1..].chunks(2) {
121                    if chunk.len() == 2 {
122                        // let key: String = redis::from_redis_value(&chunk[0])?;
123                        let val = redis::from_redis_value(&chunk[1])?;
124                        body = Some(val)
125                    }
126                }
127
128                Ok(ChannelMessage {
129                    channel: SubscriptionChannel::from(channel),
130                    // TODO to check if body is Some
131                    meta: None,
132                    body: serde_json::from_str(&body.unwrap()).unwrap(),
133                })
134            }
135            _ => Err((redis::ErrorKind::TypeError, "Unexpected Redis value").into()),
136        }
137    }
138}
139
140impl ToRedisArgs for ChannelMessage {
141    fn write_redis_args<W>(&self, out: &mut W)
142    where
143        W: ?Sized + redis::RedisWrite,
144    {
145        let msg = serde_json::to_vec(&self);
146        if let Ok(message) = msg {
147            out.write_arg(&message);
148        }
149    }
150}