rsiot/components_config/http_client/
request_periodic.rs

1use std::fmt::Debug;
2use std::time::Duration;
3
4use tracing::warn;
5
6use crate::{
7    components_config::http_general::HttpDataBound,
8    message::MsgDataBound,
9    serde_utils::{SerdeAlg, SerdeAlgKind},
10};
11
12use super::{
13    msg_request::MsgRequest, FnProcessResponseError, FnProcessResponseSuccess, MsgResponse,
14    RequestKind,
15};
16
17/// Параметры периодического запроса
18#[derive(Clone, Debug)]
19pub struct RequestPeriodicConfig<TMsg, TServerToClient, TClientToServer> {
20    /// Алгоритм сериализации / десериализации
21    pub serde_alg: SerdeAlgKind,
22    /// Тип HTTP-запроса
23    pub request_kind: RequestKind,
24    /// Путь к ресурсу
25    pub endpoint: String,
26    /// Периодичность вызова
27    pub period: Duration,
28    /// Параметры запроса
29    pub request_body: TClientToServer,
30    /// Функция обработки корректного ответа
31    pub fn_process_response_success: FnProcessResponseSuccess<TMsg, TServerToClient>,
32    /// Функция обработки ошибки ответа
33    pub fn_process_response_error: FnProcessResponseError<TMsg>,
34}
35
36/// Трейт для реализации периодических запросов
37pub trait RequestPeriodic<TMsg>
38where
39    Self: Debug + Send + Sync,
40{
41    /// Создание запроса
42    fn create_request(&self) -> Option<MsgRequest>;
43
44    /// Обработка ответа
45    fn process_response(&self, msg_response: &MsgResponse) -> Option<Vec<TMsg>>;
46
47    /// Получить периодичность вызова
48    fn get_period(&self) -> Duration;
49
50    /// Поддержка клонирования
51    fn clone_dyn(&self) -> Box<dyn RequestPeriodic<TMsg>>;
52}
53
54impl<TMsg, TServerToClient, TClientToServer> RequestPeriodic<TMsg>
55    for RequestPeriodicConfig<TMsg, TServerToClient, TClientToServer>
56where
57    TMsg: 'static + MsgDataBound,
58    TClientToServer: 'static + HttpDataBound,
59    TServerToClient: 'static + HttpDataBound,
60{
61    fn create_request(&self) -> Option<MsgRequest> {
62        let serde_alg = SerdeAlg::new(self.serde_alg);
63        let body_bytes = serde_alg.serialize(&self.request_body);
64        let body_bytes = match body_bytes {
65            Ok(v) => v,
66            Err(e) => {
67                warn!("Error serializing http request: {}", e);
68                return None;
69            }
70        };
71
72        let msg_request = MsgRequest::new(self.request_kind, self.endpoint.clone(), body_bytes);
73        Some(msg_request)
74    }
75
76    fn process_response(&self, msg_response: &MsgResponse) -> Option<Vec<TMsg>> {
77        if msg_response.get_endpoint() != &self.endpoint {
78            return None;
79        }
80
81        super::process_response::process_response(
82            self.serde_alg,
83            self.fn_process_response_success,
84            self.fn_process_response_error,
85            msg_response,
86        )
87    }
88
89    fn get_period(&self) -> Duration {
90        self.period
91    }
92
93    fn clone_dyn(&self) -> Box<dyn RequestPeriodic<TMsg>> {
94        Box::new(self.clone())
95    }
96}
97
98impl<TMsg> Clone for Box<dyn RequestPeriodic<TMsg>> {
99    fn clone(&self) -> Self {
100        self.clone_dyn()
101    }
102}