From c50485f13d0b9e948bef4a47f30cf0088484023b Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Fri, 2 Aug 2024 20:36:37 +0200 Subject: [PATCH] Add sync_changes to CalendarStore --- crates/store/src/calendar.rs | 20 +++++++++++++++ crates/store/src/sqlite_store.rs | 43 +++++++++++++++++++++++++++++++- crates/store/src/store.rs | 7 ++++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/crates/store/src/calendar.rs b/crates/store/src/calendar.rs index a6fca04..a20a033 100644 --- a/crates/store/src/calendar.rs +++ b/crates/store/src/calendar.rs @@ -13,3 +13,23 @@ pub struct Calendar { pub deleted_at: Option, pub synctoken: i64, } + +impl Calendar { + pub fn format_synctoken(&self) -> String { + format_synctoken(self.synctoken) + } +} + +const SYNC_NAMESPACE: &str = "github.com/lennart-k/rustical/ns/"; + +pub fn format_synctoken(synctoken: i64) -> String { + format!("{}{}", SYNC_NAMESPACE, synctoken) +} + +pub fn parse_synctoken(synctoken: &str) -> Option { + if !synctoken.starts_with(SYNC_NAMESPACE) { + return None; + } + let (_, synctoken) = synctoken.split_at(SYNC_NAMESPACE.len()); + synctoken.parse::().ok() +} diff --git a/crates/store/src/sqlite_store.rs b/crates/store/src/sqlite_store.rs index 42c865e..6a3fe78 100644 --- a/crates/store/src/sqlite_store.rs +++ b/crates/store/src/sqlite_store.rs @@ -32,7 +32,7 @@ impl TryFrom for Event { } } -#[derive(Serialize, sqlx::Type)] +#[derive(Debug, Clone, Serialize, sqlx::Type)] #[serde(rename_all = "kebab-case")] enum CalendarChangeOperation { // There's no distinction between Add and Modify @@ -308,6 +308,47 @@ impl CalendarStore for SqliteCalendarStore { tx.commit().await?; Ok(()) } + + async fn sync_changes( + &self, + principal: &str, + cid: &str, + synctoken: i64, + ) -> Result<(Vec, Vec, i64), Error> { + struct Row { + uid: String, + synctoken: i64, + } + let changes = sqlx::query_as!( + Row, + r#" + SELECT DISTINCT uid, max(0, synctoken) as "synctoken!: i64" from eventchangelog + WHERE synctoken > ? + ORDER BY synctoken ASC + "#, + synctoken + ) + .fetch_all(&self.db) + .await?; + + let mut events = vec![]; + let mut deleted_events = vec![]; + + let new_synctoken = changes + .last() + .map(|&Row { synctoken, .. }| synctoken) + .unwrap_or(0); + + for Row { uid, .. } in changes { + match self.get_event(principal, cid, &uid).await { + Ok(event) => events.push(event), + Err(Error::NotFound) => deleted_events.push(uid), + Err(err) => return Err(err), + } + } + + Ok((events, deleted_events, new_synctoken)) + } } pub async fn create_db_pool(db_url: &str, migrate: bool) -> anyhow::Result> { diff --git a/crates/store/src/store.rs b/crates/store/src/store.rs index 23ee588..2c3bc67 100644 --- a/crates/store/src/store.rs +++ b/crates/store/src/store.rs @@ -24,6 +24,13 @@ pub trait CalendarStore: Send + Sync + 'static { ) -> Result<(), Error>; async fn restore_calendar(&mut self, principal: &str, name: &str) -> Result<(), Error>; + async fn sync_changes( + &self, + principal: &str, + cid: &str, + synctoken: i64, + ) -> Result<(Vec, Vec, i64), Error>; + async fn get_events(&self, principal: &str, cid: &str) -> Result, Error>; async fn get_event(&self, principal: &str, cid: &str, uid: &str) -> Result; async fn put_event(