Files
warren/backend/src/lib/outbound/sqlite/options.rs
409 6fa26b3ddb remove sqlite extensions to fix docker issue
UUIDs are now generated in the backend before insertion
2025-09-07 17:35:07 +02:00

135 lines
3.3 KiB
Rust

use anyhow::Context;
use sqlx::FromRow;
use crate::domain::warren::{
models::option::{
DeleteOptionError, DeleteOptionRequest, DeleteOptionResponse, GetOptionError,
GetOptionRequest, GetOptionResponse, OptionKey, OptionType, SetOptionError,
SetOptionRequest, SetOptionResponse,
},
ports::OptionRepository,
};
use super::{Sqlite, is_not_found_error};
#[derive(Debug, FromRow)]
struct OptionRow {
key: String,
value: String,
}
impl OptionRepository for Sqlite {
async fn get_option<T: OptionType>(
&self,
request: GetOptionRequest,
) -> Result<GetOptionResponse<T>, GetOptionError> {
let mut connection = self
.pool
.acquire()
.await
.context("Failed to get a Sqlite connection")?;
let key: OptionKey = request.into();
let row: OptionRow = sqlx::query_as(
"
SELECT
key,
value
FROM
application_options
WHERE
key = $1",
)
.bind(key.as_str())
.fetch_one(&mut *connection)
.await
.map_err(|e| {
if is_not_found_error(&e) {
GetOptionError::NotFound(key)
} else {
GetOptionError::Unknown(e.into())
}
})?;
let parsed = T::parse(&row.value).map_err(|_| GetOptionError::Parse)?;
Ok(GetOptionResponse::new(
OptionKey::new(&row.key).unwrap(),
parsed,
))
}
async fn set_option<T: OptionType>(
&self,
request: SetOptionRequest<T>,
) -> Result<SetOptionResponse<T>, SetOptionError> {
let mut connection = self
.pool
.acquire()
.await
.context("Failed to get a Sqlite connection")?;
let (key, value) = request.unpack();
sqlx::query_as::<_, OptionRow>(
"
INSERT INTO application_options (
key,
value
) VALUES (
$1,
$2
)
RETURNING
key,
value
",
)
.bind(key.as_str())
.bind(value.inner().to_string())
.fetch_one(&mut *connection)
.await
.map_err(|e| SetOptionError::Unknown(e.into()))?;
Ok(SetOptionResponse::new(key, value.get_inner()))
}
async fn delete_option(
&self,
request: DeleteOptionRequest,
) -> Result<DeleteOptionResponse, DeleteOptionError> {
let mut connection = self
.pool
.acquire()
.await
.context("Failed to get a Sqlite connection")?;
let key: OptionKey = request.into();
sqlx::query_as::<_, OptionRow>(
"
DELETE FROM
application_options
WHERE
key = $1
RETURNING
key,
value
",
)
.bind(key.as_str())
.fetch_one(&mut *connection)
.await
.map_err(|e| {
if is_not_found_error(&e) {
DeleteOptionError::NotFound(key.clone())
} else {
DeleteOptionError::Unknown(e.into())
}
})?;
Ok(DeleteOptionResponse::new(key))
}
}