1919use std::{collections::HashMap, time::Duration};
2020
2121use chrono::{DateTime, Utc};
22- use serde::{Deserialize, Deserializer, Serialize};
22+ use serde::{Deserialize, Serialize};
2323use serde_json::Value;
2424use tokio::sync::{RwLock, mpsc};
2525use ulid::Ulid;
@@ -39,52 +39,6 @@ use crate::{
3939 storage::object_storage::{alert_json_path, alert_state_json_path},
4040};
4141
42- /// Custom deserializer for DateTime<Utc> that handles legacy empty strings
43- ///
44- /// This is a compatibility layer for migrating old alerts that stored empty strings
45- /// instead of valid timestamps. In production, this should log warnings to help
46- /// identify data quality issues.
47- ///
48- /// # Migration Path
49- /// - Empty strings → Default to current time with a warning
50- /// - Missing fields → Default to current time
51- /// - Valid timestamps → Parse normally
52- pub fn deserialize_datetime_with_empty_string_fallback<'de, D>(
53- deserializer: D,
54- ) -> Result<DateTime<Utc>, D::Error>
55- where
56- D: Deserializer<'de>,
57- {
58- #[derive(Deserialize)]
59- #[serde(untagged)]
60- enum DateTimeOrString {
61- DateTime(DateTime<Utc>),
62- String(String),
63- }
64-
65- match DateTimeOrString::deserialize(deserializer)? {
66- DateTimeOrString::DateTime(dt) => Ok(dt),
67- DateTimeOrString::String(s) => {
68- if s.is_empty() {
69- // Log warning about data quality issue
70- tracing::warn!(
71- "Alert has empty 'created' field - this indicates a data quality issue. \
72- Defaulting to current timestamp. Please investigate and fix the data source."
73- );
74- Ok(Utc::now())
75- } else {
76- s.parse::<DateTime<Utc>>().map_err(serde::de::Error::custom)
77- }
78- }
79- }
80- }
81-
82- /// Default function for created timestamp - returns current time
83- /// This handles the case where created field is missing in deserialization
84- pub fn default_created_time() -> DateTime<Utc> {
85- Utc::now()
86- }
87-
8842/// Helper struct for basic alert fields during migration
8943pub struct BasicAlertFields {
9044 pub id: Ulid,
@@ -394,10 +348,6 @@ pub struct AlertConfig {
394348 pub state: AlertState,
395349 pub notification_state: NotificationState,
396350 pub notification_config: NotificationConfig,
397- #[serde(
398- default = "default_created_time",
399- deserialize_with = "deserialize_datetime_with_empty_string_fallback"
400- )]
401351 pub created: DateTime<Utc>,
402352 pub tags: Option<Vec<String>>,
403353 pub last_triggered_at: Option<DateTime<Utc>>,
@@ -426,10 +376,6 @@ pub struct AlertConfigResponse {
426376 pub state: AlertState,
427377 pub notification_state: NotificationState,
428378 pub notification_config: NotificationConfig,
429- #[serde(
430- default = "default_created_time",
431- deserialize_with = "deserialize_datetime_with_empty_string_fallback"
432- )]
433379 pub created: DateTime<Utc>,
434380 pub tags: Option<Vec<String>>,
435381 pub last_triggered_at: Option<DateTime<Utc>>,
0 commit comments