rsiot/components_config/redis_client/
mod.rs

1//! Конфигурация Redis-клиента
2//!
3//! Тестирование:
4//!
5//! ```bash
6//! cargo test -p rsiot-components-config --doc redis_client
7//! ```
8
9use url::Url;
10
11use crate::message::*;
12
13pub type FnInput<TMsg, TMessageChannel> =
14    fn(&Message<TMsg>) -> anyhow::Result<Option<Vec<ConfigFnInputItem<TMessageChannel>>>>;
15pub type FnOutput<TMsg> = fn(&str) -> anyhow::Result<Option<Vec<Message<TMsg>>>>;
16
17/// Конфигурация cmp_redis_client
18#[derive(Clone, Debug)]
19pub struct Config<TMsg, TMessageChannel>
20where
21    TMessageChannel: IMessageChannel,
22{
23    /// Адрес сервера Redis
24    ///
25    /// # Примеры
26    ///
27    /// ```rust
28    /// # use rsiot_components_config::redis_client::Config;
29    /// # use rsiot_components_config::redis_client as cmp_redis_client;
30    /// # // insert from tests::stub
31    /// # use rsiot_messages_core::{example_message::*, *};
32    /// # use url::Url;
33    /// # Config::<Custom, ExampleMessageChannel> {
34    /// url: Url::parse("redis://redis:6379").unwrap(),
35    /// #     subscription_channel: ExampleMessageChannel::Output,
36    /// #     fn_input: |_| Ok(None),
37    /// #     fn_output: |_| Ok(None),
38    /// # };
39    /// ```
40    pub url: Url,
41
42    /// Название канала для подписки Pub/Sub и хеша, где хранятся сообщения
43    ///
44    /// # Примеры
45    ///
46    /// ```rust
47    /// # use rsiot_components_config::redis_client::Config;
48    /// # use rsiot_components_config::redis_client as cmp_redis_client;
49    /// # // insert from tests::stub
50    /// # use rsiot_messages_core::{example_message::*, *};
51    /// # use url::Url;
52    /// # Config::<Custom, ExampleMessageChannel> {
53    /// #     url: Url::parse("redis://redis:6379").unwrap(),
54    /// subscription_channel: ExampleMessageChannel::Output,
55    /// #     fn_input: |_| Ok(None),
56    /// #     fn_output: |_| Ok(None),
57    /// # };
58    /// ```
59    pub subscription_channel: TMessageChannel,
60
61    /// Функция преобразования входящего потока сообщений в данные для отправки в Redis
62    ///
63    /// # Примеры
64    ///
65    /// ## Заглушка
66    ///
67    /// ```rust
68    /// # use rsiot_components_config::redis_client::Config;
69    /// # use rsiot_components_config::redis_client as cmp_redis_client;
70    /// # // insert from tests::stub
71    /// # use rsiot_messages_core::{example_message::*, *};
72    /// # use url::Url;
73    /// # Config::<Custom, ExampleMessageChannel> {
74    /// #     url: Url::parse("redis://redis:6379").unwrap(),
75    /// #     subscription_channel: ExampleMessageChannel::Output,
76    /// fn_input: |_| Ok(None),
77    /// #     fn_output: |_| Ok(None),
78    /// # };
79    /// ```
80    ///
81    /// ## Сериализация в json
82    ///
83    /// ```rust
84    /// # use rsiot_components_config::redis_client::Config;
85    /// # use rsiot_components_config::redis_client as cmp_redis_client;
86    /// # // insert from tests::fn_input_json
87    /// # use rsiot_messages_core::{example_message::*, *};
88    /// # use url::Url;
89    /// # Config::<Custom, ExampleMessageChannel> {
90    /// #     url: Url::parse("redis://redis:6379").unwrap(),
91    /// #     subscription_channel: ExampleMessageChannel::Output,
92    /// fn_input: |msg: &Message<Custom>| {
93    ///     let channel = ExampleMessageChannel::Output;
94    ///     let key = msg.key.clone();
95    ///     let value = msg.serialize()?;
96    ///     Ok(Some(vec![cmp_redis_client::ConfigFnInputItem {
97    ///         channel,
98    ///         key,
99    ///         value,
100    ///     }]))
101    /// },
102    /// #     fn_output: |_| Ok(None),
103    /// # };
104    /// ```
105    ///
106    /// Возможность рассылки в несколько каналов нужна для организации роутинга сообщений
107    pub fn_input: FnInput<TMsg, TMessageChannel>,
108
109    /// Функция преобразования данных из Redis в исходящий поток сообщений
110    ///
111    /// # Примеры
112    ///
113    /// ## Заглушка
114    ///
115    /// ```rust
116    /// # use rsiot_components_config::redis_client::Config;
117    /// # use rsiot_components_config::redis_client as cmp_redis_client;
118    /// # // insert from tests::stub
119    /// # use rsiot_messages_core::{example_message::*, *};
120    /// # use url::Url;
121    /// # Config::<Custom, ExampleMessageChannel> {
122    /// #     url: Url::parse("redis://redis:6379").unwrap(),
123    /// #     subscription_channel: ExampleMessageChannel::Output,
124    /// #     fn_input: |_| Ok(None),
125    /// fn_output: |_| Ok(None),
126    /// # };
127    /// ```
128    ///
129    /// ## Десериализация из json
130    ///
131    /// ```rust
132    /// # use rsiot_components_config::redis_client::Config;
133    /// # use rsiot_components_config::redis_client as cmp_redis_client;
134    /// # // insert from tests::fn_output_json
135    /// # use rsiot_messages_core::{example_message::*, *};
136    /// # use url::Url;
137    /// # Config::<Custom, ExampleMessageChannel> {
138    /// #     url: Url::parse("redis://redis:6379").unwrap(),
139    /// #     subscription_channel: ExampleMessageChannel::Output,
140    /// #     fn_input: |_| Ok(None),
141    /// fn_output: |text: &str| {
142    ///     let msg = Message::deserialize(text)?;
143    ///     Ok(Some(vec![msg]))
144    /// },
145    /// # };
146    /// ```
147    pub fn_output: FnOutput<TMsg>,
148}
149
150/// Структура с информацией для отправки данных в Redis
151pub struct ConfigFnInputItem<TMessageChannel>
152where
153    TMessageChannel: IMessageChannel,
154{
155    /// Канал Pub/Sub, в котором опубликовать сообщение
156    pub channel: TMessageChannel,
157    /// Ключ для сохранения в кеше Redis
158    pub key: String,
159    /// Значение для сохранения - само сообщение
160    pub value: String,
161}
162
163#[cfg(test)]
164mod tests {
165    // use super::*;
166    use super::super::redis_client as cmp_redis_client;
167    use super::Config;
168
169    #[test]
170    pub fn stub() {
171        use crate::message::{example_message::*, *};
172        use url::Url;
173        let _ = Config::<Custom, ExampleMessageChannel> {
174            url: Url::parse("redis://redis:6379").unwrap(),
175            subscription_channel: ExampleMessageChannel::Output,
176            fn_input: |_| Ok(None),
177            fn_output: |_| Ok(None),
178        };
179    }
180
181    #[test]
182    pub fn fn_input_json() {
183        use crate::message::{example_message::*, *};
184        use url::Url;
185        let _ = Config::<Custom, ExampleMessageChannel> {
186            url: Url::parse("redis://redis:6379").unwrap(),
187            subscription_channel: ExampleMessageChannel::Output,
188            fn_input: |msg: &Message<Custom>| {
189                let channel = ExampleMessageChannel::Output;
190                let key = msg.key.clone();
191                let value = msg.serialize()?;
192                Ok(Some(vec![cmp_redis_client::ConfigFnInputItem {
193                    channel,
194                    key,
195                    value,
196                }]))
197            },
198            fn_output: |_| Ok(None),
199        };
200    }
201
202    #[test]
203    pub fn fn_output_json() {
204        use crate::message::{example_message::*, *};
205        use url::Url;
206        let _ = Config::<Custom, ExampleMessageChannel> {
207            url: Url::parse("redis://redis:6379").unwrap(),
208            subscription_channel: ExampleMessageChannel::Output,
209            fn_input: |_| Ok(None),
210            fn_output: |text: &str| {
211                let msg = Message::deserialize(text)?;
212                Ok(Some(vec![msg]))
213            },
214        };
215    }
216}