Rever safe results handling

This commit is contained in:
Manuel Cillero 2023-10-26 15:12:24 +02:00
parent 46ccbc10eb
commit ce3e0257bf
7 changed files with 66 additions and 135 deletions

View file

@ -60,7 +60,6 @@ impl MigrationTrait for Migration {
.values_panic(vec!["administrator".into(), "3".into()]), .values_panic(vec!["administrator".into(), "3".into()]),
) )
.await .await
.unwrap_or_error(|e| DbErr::Custom(e.message()))
.map(|_| ()) .map(|_| ())
} }

View file

@ -124,7 +124,7 @@ pub fn run_migrations() {
} }
Migrator::up(SchemaManagerConnection::Connection(dbconn), None) Migrator::up(SchemaManagerConnection::Connection(dbconn), None)
}) })
.expect_or_log(L10n::l("db_migration_fail").message().as_str()); .expect_or_log(L10n::l("db_migration_fail").error().as_str());
run_now({ run_now({
struct Migrator; struct Migrator;
@ -139,7 +139,7 @@ pub fn run_migrations() {
} }
Migrator::down(SchemaManagerConnection::Connection(dbconn), None) Migrator::down(SchemaManagerConnection::Connection(dbconn), None)
}) })
.expect_or_log(L10n::l("db_migration_fail").message().as_str()); .expect_or_log(L10n::l("db_migration_fail").error().as_str());
} }
} }

View file

@ -1,11 +1,11 @@
//! Acceso unificado y normalizado a base de datos. //! Acceso unificado y normalizado a base de datos.
use crate::locale::L10n; use crate::locale::L10n;
use crate::result::{SafeResult, TraceErr};
use crate::{config, trace, LazyStatic, ResultExt}; use crate::{config, trace, LazyStatic, ResultExt};
pub use url::Url as DbUri; pub use url::Url as DbUri;
pub use sea_orm::error::{DbErr, RuntimeErr};
pub use sea_orm::{DatabaseConnection as DbConn, ExecResult, QueryResult}; pub use sea_orm::{DatabaseConnection as DbConn, ExecResult, QueryResult};
use sea_orm::{ConnectOptions, ConnectionTrait, Database, DatabaseBackend, Statement}; use sea_orm::{ConnectOptions, ConnectionTrait, Database, DatabaseBackend, Statement};
@ -70,18 +70,18 @@ pub(crate) static DBCONN: LazyStatic<Option<DbConn>> = LazyStatic::new(|| {
db_opt.max_connections(config::SETTINGS.database.max_pool_size); db_opt.max_connections(config::SETTINGS.database.max_pool_size);
db_opt db_opt
})) }))
.expect_or_log(L10n::l("db_connection_fail").message().as_str()), .expect_or_log(L10n::l("db_connection_fail").to_string().as_str()),
) )
} else { } else {
None None
} }
}); });
pub async fn query<Q: QueryStatementWriter>(stmt: &mut Q) -> SafeResult<Option<Vec<QueryResult>>> { pub async fn query<Q: QueryStatementWriter>(stmt: &mut Q) -> Result<Vec<QueryResult>, DbErr> {
match &*DBCONN { match &*DBCONN {
Some(dbconn) => { Some(dbconn) => {
let dbbackend = dbconn.get_database_backend(); let dbbackend = dbconn.get_database_backend();
match dbconn dbconn
.query_all(Statement::from_string( .query_all(Statement::from_string(
dbbackend, dbbackend,
match dbbackend { match dbbackend {
@ -91,23 +91,18 @@ pub async fn query<Q: QueryStatementWriter>(stmt: &mut Q) -> SafeResult<Option<V
}, },
)) ))
.await .await
{
Ok(result) => SafeResult::Ok(Some(result)),
Err(e) => SafeResult::Err(TraceErr::error(L10n::n(e.to_string()), None)),
}
} }
None => SafeResult::Err(TraceErr::trace( None => Err(DbErr::Conn(RuntimeErr::Internal(
L10n::l("db_connection_not_initialized"), L10n::l("db_connection_not_initialized").trace(),
None, ))),
)),
} }
} }
pub async fn exec<Q: QueryStatementWriter>(stmt: &mut Q) -> SafeResult<Option<QueryResult>> { pub async fn exec<Q: QueryStatementWriter>(stmt: &mut Q) -> Result<Option<QueryResult>, DbErr> {
match &*DBCONN { match &*DBCONN {
Some(dbconn) => { Some(dbconn) => {
let dbbackend = dbconn.get_database_backend(); let dbbackend = dbconn.get_database_backend();
match dbconn dbconn
.query_one(Statement::from_string( .query_one(Statement::from_string(
dbbackend, dbbackend,
match dbbackend { match dbbackend {
@ -117,34 +112,24 @@ pub async fn exec<Q: QueryStatementWriter>(stmt: &mut Q) -> SafeResult<Option<Qu
}, },
)) ))
.await .await
{
Ok(result) => SafeResult::Ok(result),
Err(e) => SafeResult::Err(TraceErr::error(L10n::n(e.to_string()), None)),
}
} }
None => SafeResult::Err(TraceErr::trace( None => Err(DbErr::Conn(RuntimeErr::Internal(
L10n::l("db_connection_not_initialized"), L10n::l("db_connection_not_initialized").trace(),
None, ))),
)),
} }
} }
pub async fn exec_raw(stmt: String) -> SafeResult<Option<ExecResult>> { pub async fn exec_raw(stmt: String) -> Result<ExecResult, DbErr> {
match &*DBCONN { match &*DBCONN {
Some(dbconn) => { Some(dbconn) => {
let dbbackend = dbconn.get_database_backend(); let dbbackend = dbconn.get_database_backend();
match dbconn dbconn
.execute(Statement::from_string(dbbackend, stmt)) .execute(Statement::from_string(dbbackend, stmt))
.await .await
{
Ok(result) => SafeResult::Ok(Some(result)),
Err(e) => SafeResult::Err(TraceErr::error(L10n::n(e.to_string()), None)),
}
} }
None => SafeResult::Err(TraceErr::trace( None => Err(DbErr::Conn(RuntimeErr::Internal(
L10n::l("db_connection_not_initialized"), L10n::l("db_connection_not_initialized").trace(),
None, ))),
)),
} }
} }

View file

@ -129,9 +129,6 @@ static_locales!(LOCALES_PAGETOP);
// PUBLIC API. // PUBLIC API.
// ************************************************************************************************* // *************************************************************************************************
// Handling safe results.
pub mod result;
// Functions and macro helpers. // Functions and macro helpers.
pub mod util; pub mod util;

View file

@ -88,8 +88,7 @@
//! ``` //! ```
use crate::html::{Markup, PreEscaped}; use crate::html::{Markup, PreEscaped};
use crate::result::{SafeResult, TraceErr}; use crate::{config, kv, trace, LazyStatic, LOCALES_PAGETOP};
use crate::{config, kv, LazyStatic, LOCALES_PAGETOP};
pub use fluent_templates; pub use fluent_templates;
pub use unic_langid::LanguageIdentifier; pub use unic_langid::LanguageIdentifier;
@ -118,22 +117,21 @@ static FALLBACK_LANGID: LazyStatic<LanguageIdentifier> = LazyStatic::new(|| lang
/// Almacena el Identificador de Idioma Unicode /// Almacena el Identificador de Idioma Unicode
/// ([Unicode Language Identifier](https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier)) /// ([Unicode Language Identifier](https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier))
/// global para la aplicación a partir de `SETTINGS.app.language`. /// global para la aplicación a partir de `SETTINGS.app.language`.
pub(crate) static LANGID: LazyStatic<&LanguageIdentifier> = pub(crate) static LANGID: LazyStatic<&LanguageIdentifier> = LazyStatic::new(|| {
LazyStatic::new(|| langid_for(config::SETTINGS.app.language.as_str()).unwrap_or_fallback()); langid_for(config::SETTINGS.app.language.as_str()).unwrap_or(&FALLBACK_LANGID)
});
pub fn langid_for(language: impl Into<String>) -> SafeResult<&'static LanguageIdentifier> { pub fn langid_for(language: impl Into<String>) -> Result<&'static LanguageIdentifier, String> {
let language = language.into(); let language = language.into();
match LANGUAGES.get(language.as_str()) { match LANGUAGES.get(language.as_str()) {
Some((langid, _)) => SafeResult::Ok(langid), Some((langid, _)) => Ok(langid),
None => { None => {
if language.is_empty() { if language.is_empty() {
SafeResult::Ok(&FALLBACK_LANGID) Ok(&FALLBACK_LANGID)
} else { } else {
SafeResult::Err(TraceErr::warn( Err(L10n::l(LANGUAGE_SET_FAILURE)
L10n::l(LANGUAGE_SET_FAILURE) .with_arg("language", config::SETTINGS.app.language.as_str())
.with_arg("language", config::SETTINGS.app.language.as_str()), .warn())
&FALLBACK_LANGID,
))
} }
} }
} }
@ -238,7 +236,43 @@ impl L10n {
} }
} }
pub(crate) fn message(&self) -> String { pub fn escaped(&self, langid: &LanguageIdentifier) -> Markup {
PreEscaped(self.using(langid).unwrap_or_default())
}
pub fn trace(&self) -> String {
let message = self.to_string();
trace::trace!(message);
message
}
pub fn debug(&self) -> String {
let message = self.to_string();
trace::debug!(message);
message
}
pub fn info(&self) -> String {
let message = self.to_string();
trace::info!(message);
message
}
pub fn warn(&self) -> String {
let message = self.to_string();
trace::warn!(message);
message
}
pub fn error(&self) -> String {
let message = self.to_string();
trace::error!(message);
message
}
}
impl ToString for L10n {
fn to_string(&self) -> String {
match &self.op { match &self.op {
L10nOp::None => "".to_owned(), L10nOp::None => "".to_owned(),
L10nOp::Text(text) => text.to_owned(), L10nOp::Text(text) => text.to_owned(),
@ -263,8 +297,4 @@ impl L10n {
}, },
} }
} }
pub fn escaped(&self, langid: &LanguageIdentifier) -> Markup {
PreEscaped(self.using(langid).unwrap_or_default())
}
} }

View file

@ -6,9 +6,6 @@ pub use crate::{concat_string, fn_builder, main, paste, test};
// Global. // Global.
pub use crate::{Handle, HashMapResources, LazyStatic, ResultExt, Weight}; pub use crate::{Handle, HashMapResources, LazyStatic, ResultExt, Weight};
// Handling safe results.
pub use crate::result::{SafeResult, TraceErr};
// Functions and macro helpers. // Functions and macro helpers.
pub use crate::util; pub use crate::util;
pub use crate::{kv, new_handle}; pub use crate::{kv, new_handle};

View file

@ -1,77 +0,0 @@
//! Handling safe results.
use crate::locale::L10n;
use crate::trace;
pub struct TraceErr<T> {
message: String,
fallback: T,
}
impl<T> TraceErr<T> {
pub fn trace(trace: L10n, fallback: T) -> Self {
let message = trace.message();
trace::trace!(message);
TraceErr { message, fallback }
}
pub fn debug(trace: L10n, fallback: T) -> Self {
let message = trace.message();
trace::debug!(message);
TraceErr { message, fallback }
}
pub fn info(trace: L10n, fallback: T) -> Self {
let message = trace.message();
trace::info!(message);
TraceErr { message, fallback }
}
pub fn warn(trace: L10n, fallback: T) -> Self {
let message = trace.message();
trace::warn!(message);
TraceErr { message, fallback }
}
pub fn error(trace: L10n, fallback: T) -> Self {
let message = trace.message();
trace::error!(message);
TraceErr { message, fallback }
}
// TraceErr GETTERS.
pub fn message(self) -> String {
self.message
}
pub fn fallback(self) -> T {
self.fallback
}
}
pub enum SafeResult<T> {
Ok(T),
Err(TraceErr<T>),
}
impl<T> SafeResult<T> {
#[inline]
pub fn unwrap_or_error<F, E>(self, f: F) -> Result<T, E>
where
F: FnOnce(TraceErr<T>) -> E,
{
match self {
SafeResult::Ok(r) => Ok(r),
SafeResult::Err(e) => Err(f(e)),
}
}
#[inline]
pub fn unwrap_or_fallback(self) -> T {
match self {
SafeResult::Ok(r) => r,
SafeResult::Err(e) => e.fallback(),
}
}
}