autopush_common/db/redis/
mod.rs1mod redis_client;
15
16pub use redis_client::RedisClientImpl;
17
18use std::collections::HashMap;
19use std::time::Duration;
20
21use crate::db::error::DbError;
22use crate::notification::{default_ttl, Notification};
23use crate::util::deserialize_opt_u32_to_duration;
24
25use serde_derive::{Deserialize, Serialize};
26use uuid::Uuid;
27
28#[derive(Clone, Debug, Deserialize)]
30#[serde(default)]
31pub struct RedisDbSettings {
32 #[serde(deserialize_with = "deserialize_opt_u32_to_duration")]
33 pub create_timeout: Option<Duration>,
34 #[serde(deserialize_with = "deserialize_opt_u32_to_duration")]
35 pub router_ttl: Option<Duration>,
36 #[serde(deserialize_with = "deserialize_opt_u32_to_duration")]
37 pub notification_ttl: Option<Duration>,
38}
39
40#[allow(clippy::derivable_impls)]
41impl Default for RedisDbSettings {
42 fn default() -> Self {
43 Self {
44 create_timeout: Default::default(),
45 router_ttl: Some(Duration::from_secs(crate::MAX_ROUTER_TTL_SECS)),
46 notification_ttl: Some(Duration::from_secs(crate::MAX_NOTIFICATION_TTL_SECS)),
47 }
48 }
49}
50
51impl TryFrom<&str> for RedisDbSettings {
52 type Error = DbError;
53 fn try_from(setting_string: &str) -> Result<Self, Self::Error> {
54 let me: Self = match serde_json::from_str(setting_string) {
55 Ok(me) => me,
56 Err(e) if e.is_eof() => Self::default(),
57 Err(e) => Err(DbError::General(format!(
58 "Could not parse RedisDbSettings: {:?}",
59 e
60 )))?,
61 };
62 if let Some(router_ttl) = me.router_ttl {
63 if router_ttl.as_secs() == 0 {
64 return Err(DbError::General(
65 "router_ttl must be greater than 0".to_string(),
66 ));
67 }
68 }
69 if let Some(notification_ttl) = me.notification_ttl {
70 if notification_ttl.as_secs() == 0 {
71 return Err(DbError::General(
72 "notification_ttl must be greater than 0".to_string(),
73 ));
74 }
75 }
76 Ok(me)
77 }
78}
79
80#[derive(Serialize, Default, Deserialize, Clone, Debug)]
81pub struct StorableNotification {
85 #[serde(rename = "channelID")]
87 pub channel_id: Uuid,
88 pub version: String,
89 pub timestamp: u64,
90 #[serde(default = "default_ttl", skip_serializing)]
92 pub ttl: u64,
93 #[serde(skip_serializing)]
95 pub topic: Option<String>,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub data: Option<String>,
98 #[serde(skip_serializing)]
99 pub sortkey_timestamp: Option<u64>,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub headers: Option<HashMap<String, String>>,
102 #[cfg(feature = "reliable_report")]
103 #[serde(skip_serializing_if = "Option::is_none")]
104 pub reliability_id: Option<String>,
105 #[cfg(feature = "reliable_report")]
106 #[serde(skip_serializing_if = "Option::is_none")]
107 pub reliable_state: Option<crate::reliability::ReliabilityState>,
108}
109
110impl From<Notification> for StorableNotification {
111 fn from(notification: Notification) -> Self {
112 Self {
113 channel_id: notification.channel_id,
114 version: notification.version,
115 timestamp: notification.timestamp,
116 ttl: notification.ttl,
117 topic: notification.topic,
118 data: notification.data,
119 sortkey_timestamp: notification.sortkey_timestamp,
120 headers: notification.headers,
121 #[cfg(feature = "reliable_report")]
122 reliability_id: notification.reliability_id,
123 #[cfg(feature = "reliable_report")]
124 reliable_state: notification.reliable_state,
125 }
126 }
127}
128
129impl From<StorableNotification> for Notification {
130 fn from(storable: StorableNotification) -> Self {
131 Self {
132 channel_id: storable.channel_id,
133 version: storable.version,
134 timestamp: storable.timestamp,
135 ttl: storable.ttl,
136 topic: storable.topic,
137 data: storable.data,
138 sortkey_timestamp: storable.sortkey_timestamp,
139 headers: storable.headers,
140 #[cfg(feature = "reliable_report")]
141 reliability_id: storable.reliability_id,
142 #[cfg(feature = "reliable_report")]
143 reliable_state: storable.reliable_state,
144 }
145 }
146}
147
148#[cfg(test)]
149mod tests {
150
151 use std::time::Duration;
152
153 #[test]
154 fn test_settings_parse() -> Result<(), crate::db::error::DbError> {
155 let settings = super::RedisDbSettings::try_from("{\"create_timeout\": 123}")?;
156 assert_eq!(
157 settings.create_timeout,
158 Some(std::time::Duration::from_secs(123))
159 );
160 let settings = super::RedisDbSettings::try_from("{}")?;
161 assert_ne!(settings.router_ttl, Some(Duration::from_secs(0)));
162 assert_ne!(settings.notification_ttl, Some(Duration::from_secs(0)));
163 let settings = super::RedisDbSettings::try_from("{\"router_ttl\":0}");
164 assert!(settings.is_err());
165 Ok(())
166 }
167}