Skip to main content

max / goingson

2.0 KB · 58 lines History Blame Raw
1 //! Thin `sync_state` key-value helpers over the sqlx pool.
2 //!
3 //! `sync_state` is a plain KV table (device_id, auto_sync_enabled,
4 //! sync_interval_minutes, last_sync_at, ...) that the engine and the app share.
5 //! Reading and writing settings is app-side and needs only the pool, so these
6 //! stay as sqlx helpers here rather than routing through the store. The engine
7 //! owns the *sync* semantics (cursor, changelog, apply); these touch only user
8 //! settings and the pending-count readout for the status UI.
9
10 use goingson_core::CoreError;
11 use sqlx::SqlitePool;
12 use std::collections::HashMap;
13
14 /// Read several `sync_state` values in one query.
15 pub(crate) async fn get_sync_states_batch(
16 pool: &SqlitePool,
17 keys: &[&str],
18 ) -> Result<HashMap<String, String>, CoreError> {
19 if keys.is_empty() {
20 return Ok(HashMap::new());
21 }
22
23 let placeholders = keys.iter().map(|_| "?").collect::<Vec<_>>().join(",");
24 let query = format!("SELECT key, value FROM sync_state WHERE key IN ({placeholders})");
25
26 let mut q = sqlx::query_as::<_, (String, String)>(sqlx::AssertSqlSafe(query.as_str()));
27 for key in keys {
28 q = q.bind(*key);
29 }
30
31 let rows = q.fetch_all(pool).await.map_err(CoreError::database)?;
32 Ok(rows.into_iter().collect())
33 }
34
35 /// Upsert one `sync_state` value.
36 pub(crate) async fn set_sync_state(
37 pool: &SqlitePool,
38 key: &str,
39 value: &str,
40 ) -> Result<(), CoreError> {
41 sqlx::query("INSERT OR REPLACE INTO sync_state (key, value) VALUES (?, ?)")
42 .bind(key)
43 .bind(value)
44 .execute(pool)
45 .await
46 .map_err(CoreError::database)?;
47 Ok(())
48 }
49
50 /// Count local changes not yet pushed (drives the status UI's pending badge).
51 pub(crate) async fn count_pending_changes(pool: &SqlitePool) -> Result<i64, CoreError> {
52 let row: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM sync_changelog WHERE pushed = 0")
53 .fetch_one(pool)
54 .await
55 .map_err(CoreError::database)?;
56 Ok(row.0)
57 }
58