135 lines
3.3 KiB
Rust
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))
|
|
}
|
|
}
|