orbok_db/repo/
settings.rs1use crate::catalog::{Catalog, db_err};
6use orbok_core::{OrbokError, OrbokResult, now_iso8601};
7use rusqlite::params;
8use serde::Serialize;
9use serde::de::DeserializeOwned;
10
11pub struct SettingsRepository<'a> {
12 catalog: &'a Catalog,
13}
14
15impl<'a> SettingsRepository<'a> {
16 pub fn new(catalog: &'a Catalog) -> Self {
17 Self { catalog }
18 }
19
20 pub fn set<T: Serialize>(&self, key: &str, value: &T) -> OrbokResult<()> {
22 let json = serde_json::to_string(value)
23 .map_err(|e| OrbokError::Database(format!("settings serialize: {e}")))?;
24 let conn = self.catalog.lock();
25 conn.execute(
26 "INSERT INTO app_settings (key, value_json, updated_at) VALUES (?1, ?2, ?3) \
27 ON CONFLICT(key) DO UPDATE SET value_json = ?2, updated_at = ?3",
28 params![key, json, now_iso8601()],
29 )
30 .map_err(db_err)?;
31 Ok(())
32 }
33
34 pub fn get<T: DeserializeOwned>(&self, key: &str) -> OrbokResult<Option<T>> {
36 let conn = self.catalog.lock();
37 let json: Option<String> = conn
38 .query_row(
39 "SELECT value_json FROM app_settings WHERE key = ?1",
40 params![key],
41 |row| row.get(0),
42 )
43 .map(Some)
44 .or_else(|e| match e {
45 rusqlite::Error::QueryReturnedNoRows => Ok(None),
46 other => Err(db_err(other)),
47 })?;
48 match json {
49 None => Ok(None),
50 Some(json) => serde_json::from_str(&json)
51 .map(Some)
52 .map_err(|e| OrbokError::Database(format!("settings deserialize {key}: {e}"))),
53 }
54 }
55}