use runledger_core::jobs::{IdentifierValidationError, WorkflowBuildError};
use runledger_postgres::jobs::JobDefinitionCatalogSyncError;
use thiserror::Error;
#[non_exhaustive]
#[derive(Debug, Error)]
pub enum CatalogError {
#[error("job type {job_type:?} is invalid: {source}")]
InvalidJobType {
job_type: String,
#[source]
source: IdentifierValidationError,
},
#[error("handler job type {handler_job_type:?} is invalid: {source}")]
InvalidHandlerJobType {
handler_job_type: String,
#[source]
source: IdentifierValidationError,
},
#[error("job type {declared} does not match handler job type {handler}")]
HandlerJobTypeMismatch {
declared: String,
handler: String,
},
#[error("job type {job_type} is already registered in the catalog")]
DuplicateJobType {
job_type: String,
},
#[error("catalog defaults are invalid: {field} must be positive")]
InvalidDefinitionValue {
field: &'static str,
},
#[error("failure code must be non-empty")]
InvalidFailureCode,
#[error("retry delay override must be positive")]
InvalidRetryDelay,
#[error("exact sync scope must include at least one job type")]
InvalidExactSyncScope,
#[error("exact sync scope job type {job_type:?} is invalid: {source}")]
InvalidExactSyncScopeJobType {
job_type: String,
#[source]
source: IdentifierValidationError,
},
#[error("exact sync requires at least one catalog job")]
EmptyExactSyncCatalog,
#[error("catalog job type {job_type} is outside the exact sync scope")]
JobTypeOutsideExactSyncScope {
job_type: String,
},
#[error("active schedule {schedule_name} still references absent catalog job type {job_type}")]
ActiveScheduleForAbsentJobType {
schedule_name: String,
job_type: String,
},
#[error(
"active schedule {schedule_name} still references disabled catalog job type {job_type}"
)]
ActiveScheduleForDisabledJobType {
schedule_name: String,
job_type: String,
},
#[error("job type {job_type} is not registered in the catalog")]
UnknownJobType {
job_type: String,
},
#[error("job type {job_type} is disabled in the catalog")]
DisabledJobType {
job_type: String,
},
#[error(transparent)]
WorkflowBuild(#[from] WorkflowBuildError),
#[error("failed to start job definition sync transaction: {0}")]
SyncFailure(#[source] runledger_postgres::Error),
#[error("failed to sync job definitions with an unmapped persistence error: {0}")]
DefinitionCatalogSyncFailure(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("failed to sync job definition {job_type}: {source}")]
DefinitionSyncFailure {
job_type: String,
#[source]
source: runledger_postgres::Error,
},
#[error("failed to commit job definition sync transaction: {0}")]
CommitFailure(#[source] sqlx::Error),
#[error("failed to bound job definition sync critical section: {0}")]
CriticalSectionTimeoutFailure(#[source] runledger_postgres::Error),
#[error("job definition sync input is invalid: {0}")]
DefinitionSyncValidationFailure(#[source] runledger_postgres::Error),
#[error("failed to lock job schedules before disabling job definitions: {0}")]
ScheduleLockFailure(#[source] runledger_postgres::Error),
#[error("failed to lock job definitions before disabling job definitions: {0}")]
DefinitionLockFailure(#[source] runledger_postgres::Error),
#[error("failed to check active schedules before disabling job definitions: {0}")]
ScheduleCheckFailure(#[source] runledger_postgres::Error),
#[error("failed to inspect job definitions before syncing catalog: {0}")]
DefinitionInspectFailure(#[source] runledger_postgres::Error),
#[error("failed to disable absent job definitions: {0}")]
DisableAbsentFailure(#[source] runledger_postgres::Error),
}
impl CatalogError {
pub(crate) fn from_definition_catalog_sync_error(error: JobDefinitionCatalogSyncError) -> Self {
match error {
JobDefinitionCatalogSyncError::ActiveScheduleForAbsentJobType(reference) => {
Self::ActiveScheduleForAbsentJobType {
schedule_name: reference.schedule_name,
job_type: reference.job_type.to_string(),
}
}
JobDefinitionCatalogSyncError::ActiveScheduleForDisabledJobType(reference) => {
Self::ActiveScheduleForDisabledJobType {
schedule_name: reference.schedule_name,
job_type: reference.job_type.to_string(),
}
}
JobDefinitionCatalogSyncError::CriticalSectionTimeoutFailure(source) => {
Self::CriticalSectionTimeoutFailure(source)
}
JobDefinitionCatalogSyncError::ScheduleLockFailure(source) => {
Self::ScheduleLockFailure(source)
}
JobDefinitionCatalogSyncError::DefinitionLockFailure(source) => {
Self::DefinitionLockFailure(source)
}
JobDefinitionCatalogSyncError::ScheduleCheckFailure(source) => {
Self::ScheduleCheckFailure(source)
}
JobDefinitionCatalogSyncError::ValidationFailure(source) => {
Self::DefinitionSyncValidationFailure(source)
}
JobDefinitionCatalogSyncError::DefinitionInspectFailure(source) => {
Self::DefinitionInspectFailure(source)
}
JobDefinitionCatalogSyncError::DefinitionSyncFailure { job_type, source } => {
Self::DefinitionSyncFailure { job_type, source }
}
JobDefinitionCatalogSyncError::DisableAbsentFailure(source) => {
Self::DisableAbsentFailure(source)
}
_ => Self::DefinitionCatalogSyncFailure(Box::new(error)),
}
}
}