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}