#[cfg(test)]
use sqlx::error::Error as SqlxError;
use ff_core::engine_error::EngineError;
pub use crate::retry::MAX_ATTEMPTS;
pub(crate) fn map_sqlx_error(err: sqlx::Error) -> EngineError {
EngineError::Transport {
backend: "sqlite",
source: Box::new(err),
}
}
impl crate::retry::IsRetryableBusy for EngineError {
fn is_retryable_busy(&self) -> bool {
if let EngineError::Transport { backend, source } = self
&& *backend == "sqlite"
&& let Some(sqlx_err) = source.downcast_ref::<sqlx::Error>()
{
return is_retryable_sqlite_busy(sqlx_err);
}
false
}
}
pub fn is_retryable_sqlite_busy(err: &sqlx::Error) -> bool {
if let sqlx::Error::Database(db_err) = err {
if let Some(code) = db_err.code()
&& let Ok(n) = code.parse::<i32>()
{
let primary = n & 0xff;
return primary == 5 || primary == 6;
}
}
false
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn non_db_error_is_not_retryable() {
let err = SqlxError::RowNotFound;
assert!(!is_retryable_sqlite_busy(&err));
}
}