Skip to main content

mxr_store/
sync_log.rs

1use chrono::{DateTime, Utc};
2use mxr_core::AccountId;
3
4pub struct SyncLogEntry {
5    pub id: i64,
6    pub account_id: AccountId,
7    pub started_at: DateTime<Utc>,
8    pub finished_at: Option<DateTime<Utc>>,
9    pub status: SyncStatus,
10    pub messages_synced: u32,
11    pub error_message: Option<String>,
12}
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum SyncStatus {
16    Running,
17    Success,
18    Error,
19}
20
21impl SyncStatus {
22    fn as_str(&self) -> &str {
23        match self {
24            SyncStatus::Running => "running",
25            SyncStatus::Success => "success",
26            SyncStatus::Error => "error",
27        }
28    }
29
30    fn from_str(s: &str) -> Self {
31        match s {
32            "running" => SyncStatus::Running,
33            "success" => SyncStatus::Success,
34            _ => SyncStatus::Error,
35        }
36    }
37}
38
39impl super::Store {
40    pub async fn insert_sync_log(
41        &self,
42        account_id: &AccountId,
43        status: &SyncStatus,
44    ) -> Result<i64, sqlx::Error> {
45        let now = Utc::now().timestamp();
46        let aid = account_id.as_str();
47        let status_str = status.as_str();
48        let result = sqlx::query!(
49            "INSERT INTO sync_log (account_id, started_at, status) VALUES (?, ?, ?)",
50            aid,
51            now,
52            status_str,
53        )
54        .execute(self.writer())
55        .await?;
56
57        Ok(result.last_insert_rowid())
58    }
59
60    pub async fn complete_sync_log(
61        &self,
62        log_id: i64,
63        status: &SyncStatus,
64        messages_synced: u32,
65        error_message: Option<&str>,
66    ) -> Result<(), sqlx::Error> {
67        let now = Utc::now().timestamp();
68        let status_str = status.as_str();
69        sqlx::query!(
70            "UPDATE sync_log SET finished_at = ?, status = ?, messages_synced = ?, error_message = ? WHERE id = ?",
71            now,
72            status_str,
73            messages_synced,
74            error_message,
75            log_id,
76        )
77        .execute(self.writer())
78        .await?;
79
80        Ok(())
81    }
82
83    pub async fn get_last_sync(
84        &self,
85        account_id: &AccountId,
86    ) -> Result<Option<SyncLogEntry>, sqlx::Error> {
87        let aid = account_id.as_str();
88        let row = sqlx::query!(
89            r#"SELECT id as "id!", account_id as "account_id!", started_at as "started_at!",
90                      finished_at, status as "status!", messages_synced as "messages_synced!",
91                      error_message
92               FROM sync_log WHERE account_id = ? ORDER BY started_at DESC LIMIT 1"#,
93            aid,
94        )
95        .fetch_optional(self.reader())
96        .await?;
97
98        Ok(row.map(|r| SyncLogEntry {
99            id: r.id,
100            account_id: AccountId::from_uuid(uuid::Uuid::parse_str(&r.account_id).unwrap()),
101            started_at: DateTime::from_timestamp(r.started_at, 0).unwrap_or_default(),
102            finished_at: r.finished_at.and_then(|ts| DateTime::from_timestamp(ts, 0)),
103            status: SyncStatus::from_str(&r.status),
104            messages_synced: r.messages_synced as u32,
105            error_message: r.error_message,
106        }))
107    }
108}