track_core/
settings_repository.rs1use serde::{de::DeserializeOwned, Serialize};
2use sqlx::Row;
3
4use crate::database::DatabaseContext;
5use crate::errors::{ErrorCode, TrackError};
6
7#[derive(Debug, Clone)]
8pub struct SettingsRepository {
9 database: DatabaseContext,
10}
11
12impl SettingsRepository {
13 pub fn new(database: Option<DatabaseContext>) -> Result<Self, TrackError> {
14 let database = match database {
15 Some(database) => database,
16 None => DatabaseContext::new(None)?,
17 };
18 database.initialize()?;
19
20 Ok(Self { database })
21 }
22
23 pub fn load_json<T>(&self, key: &str) -> Result<Option<T>, TrackError>
24 where
25 T: DeserializeOwned + Send + 'static,
26 {
27 let key = key.to_owned();
28 self.database.run(move |connection| {
29 Box::pin(async move {
30 let row =
31 sqlx::query("SELECT setting_json FROM backend_settings WHERE setting_key = ?1")
32 .bind(&key)
33 .fetch_optional(&mut *connection)
34 .await
35 .map_err(|error| {
36 TrackError::new(
37 ErrorCode::TaskWriteFailed,
38 format!("Could not load backend setting `{key}`: {error}"),
39 )
40 })?;
41
42 row.map(|row| {
43 serde_json::from_str::<T>(row.get::<String, _>("setting_json").as_str())
44 .map_err(|error| {
45 TrackError::new(
46 ErrorCode::InvalidConfig,
47 format!("Backend setting `{key}` is not valid JSON: {error}"),
48 )
49 })
50 })
51 .transpose()
52 })
53 })
54 }
55
56 pub fn save_json<T>(&self, key: &str, value: &T) -> Result<(), TrackError>
57 where
58 T: Serialize,
59 {
60 let key = key.to_owned();
61 let serialized = serde_json::to_string(value).map_err(|error| {
62 TrackError::new(
63 ErrorCode::InvalidConfig,
64 format!("Could not serialize backend setting `{key}`: {error}"),
65 )
66 })?;
67
68 self.database.run(move |connection| {
69 Box::pin(async move {
70 sqlx::query(
71 r#"
72 INSERT INTO backend_settings (setting_key, setting_json)
73 VALUES (?1, ?2)
74 ON CONFLICT(setting_key) DO UPDATE SET setting_json = excluded.setting_json
75 "#,
76 )
77 .bind(&key)
78 .bind(&serialized)
79 .execute(&mut *connection)
80 .await
81 .map_err(|error| {
82 TrackError::new(
83 ErrorCode::TaskWriteFailed,
84 format!("Could not save backend setting `{key}`: {error}"),
85 )
86 })?;
87
88 Ok(())
89 })
90 })
91 }
92
93 pub fn delete(&self, key: &str) -> Result<(), TrackError> {
94 let key = key.to_owned();
95 self.database.run(move |connection| {
96 Box::pin(async move {
97 sqlx::query("DELETE FROM backend_settings WHERE setting_key = ?1")
98 .bind(&key)
99 .execute(&mut *connection)
100 .await
101 .map_err(|error| {
102 TrackError::new(
103 ErrorCode::TaskWriteFailed,
104 format!("Could not delete backend setting `{key}`: {error}"),
105 )
106 })?;
107
108 Ok(())
109 })
110 })
111 }
112}