flippico_cache/types/
channels.rs

1use std::collections::HashMap;
2
3use redis::{FromRedisValue, RedisResult, ToRedisArgs, Value};
4use serde::{Deserialize, Serialize};
5
6#[derive(Serialize, PartialEq, Debug, Deserialize)]
7pub enum SubscriptionChannel {
8    Amadeus,
9    Notifica,
10    BajkomatApi,
11}
12
13impl SubscriptionChannel {
14    pub fn get_channel(&self) -> &'static str {
15        match self {
16            SubscriptionChannel::Amadeus => "AMADEUS_CHANNEL",
17            SubscriptionChannel::Notifica => "NOTIFICA_CHANNEL",
18            SubscriptionChannel::BajkomatApi => "BAJKOMAT_API_CHANNEL",
19        }
20    }
21
22    pub fn from_channel(value: &str) -> Option<Self> {
23        [
24            SubscriptionChannel::Amadeus,
25            SubscriptionChannel::BajkomatApi,
26            SubscriptionChannel::Notifica,
27        ]
28        .into_iter()
29        .find(|variant| variant.get_channel() == value)
30    }
31}
32
33#[derive(Serialize, PartialEq, Debug, Deserialize)]
34pub struct ChannelMessage {
35    pub channel: SubscriptionChannel,
36    pub body: HashMap<String, String>,
37}
38
39impl From<String> for SubscriptionChannel {
40    fn from(value: String) -> Self {
41        SubscriptionChannel::from_channel(&value).expect("Invalid channel string")
42    }
43}
44
45impl FromRedisValue for ChannelMessage {
46    fn from_redis_value(v: &Value) -> RedisResult<Self> {
47        match v {
48            Value::Array(items) => {
49                if items.len() < 2 {
50                    return Err((redis::ErrorKind::TypeError, "Not enough items").into());
51                }
52                let channel: String = redis::from_redis_value(&items[0])?;
53                let mut body = HashMap::new();
54                for chunk in items[1..].chunks(2) {
55                    if chunk.len() == 2 {
56                        let key: String = redis::from_redis_value(&chunk[0])?;
57                        let val: String = redis::from_redis_value(&chunk[1])?;
58                        body.insert(key, val);
59                    }
60                }
61
62                Ok(ChannelMessage {
63                    channel: SubscriptionChannel::from(channel),
64                    body,
65                })
66            }
67            _ => Err((redis::ErrorKind::TypeError, "Unexpected Redis value").into()),
68        }
69    }
70}
71
72impl ToRedisArgs for ChannelMessage {
73    fn write_redis_args<W>(&self, out: &mut W)
74    where
75        W: ?Sized + redis::RedisWrite,
76    {
77        let msg = serde_json::to_vec(&self);
78        if let Ok(message) = msg {
79            out.write_arg(&message);
80        }
81    }
82}