use crate::context::SharedContext;
use crate::repository::RepositoryError;
use thiserror::Error;
use tracing::{error, warn};
#[derive(Debug, Error)]
pub enum PollingError {
#[error("Database operation failed: {0}")]
DatabaseOperation(#[from] sqlx::Error),
}
impl From<RepositoryError> for PollingError {
fn from(error: RepositoryError) -> Self {
match error {
RepositoryError::Database(e) => PollingError::DatabaseOperation(e),
RepositoryError::NotFound => PollingError::DatabaseOperation(sqlx::Error::RowNotFound),
RepositoryError::Mapping(e) => {
error!("Data mapping error: {e}");
PollingError::DatabaseOperation(sqlx::Error::RowNotFound)
}
}
}
}
pub(super) async fn handle_polling_error(error: PollingError, ctx: &SharedContext) {
match error {
PollingError::DatabaseOperation(e) => handle_sqlx_error(e, ctx).await,
}
}
async fn handle_sqlx_error(error: sqlx::Error, ctx: &SharedContext) {
let critical;
match error {
sqlx::Error::Database(e) => {
if e.is_unique_violation() {
critical = false;
warn!("Attempted duplicate insertion of unique value: {e}");
} else {
critical = true;
error!("Database error: {e}");
}
}
sqlx::Error::Io(e) => {
critical = true;
error!("Database I/O error: {e}");
}
e => {
critical = true;
error!("{e}")
}
}
if critical {
tokio::select! {
_ = tokio::time::sleep(ctx.config.database.polling_db_error_cooldown) => {}
_ = ctx.token.cancelled() => {}
}
}
}