Skip to main content

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