use std::num::NonZeroUsize;
use thiserror::Error;
use crate::fdb::tenant_name::FoundationDbTenantName;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
pub enum FdbError {
#[error("foundationdb configuration error: {reason}")]
Config {
reason: ConfigErrorReason,
},
#[error("foundationdb setup error: {reason}")]
Setup {
reason: FdbSetupErrorReason,
},
#[error("foundationdb query error: {reason}")]
Query {
reason: FdbQueryErrorReason,
},
#[error("foundationdb health check failed: {reason}")]
Health {
reason: FdbHealthErrorReason,
},
#[error("foundationdb tenant error: {reason}")]
Tenant {
reason: TenantErrorReason,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
pub enum TenantErrorReason {
#[error("tenant `{tenant}` is not provisioned in foundationdb")]
NotProvisioned {
tenant: FoundationDbTenantName,
},
#[error("tenant lookup failed for `{tenant}`")]
LookupFailed {
tenant: FoundationDbTenantName,
},
#[error("tenant `{tenant}` could not be opened")]
OpenFailed {
tenant: FoundationDbTenantName,
},
#[error("tenant `{tenant}` already exists")]
AlreadyExists {
tenant: FoundationDbTenantName,
},
#[error("tenant administration failed for `{tenant}`")]
AdministrationFailed {
tenant: FoundationDbTenantName,
},
#[error("tenant `{tenant}` must be empty for this administration operation")]
RepairRequiresEmptyTenant {
tenant: FoundationDbTenantName,
},
#[error("tenant `{tenant}` metadata is missing required field `{field:?}")]
MetadataMissing {
tenant: FoundationDbTenantName,
field: TenantMetadataField,
},
#[error("tenant `{tenant}` metadata field `{field:?}` is malformed")]
MetadataMalformed {
tenant: FoundationDbTenantName,
field: TenantMetadataField,
},
#[error("tenant `{tenant}` metadata schema version `{schema_version}` is unsupported")]
SchemaVersionUnsupported {
tenant: FoundationDbTenantName,
schema_version: u32,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TenantMetadataField {
SchemaVersion,
CreatedAt,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConfigField {
EnvironmentPrefix,
ApiVersion,
ClusterFile,
HealthCheckTimeoutMillis,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
pub enum ConfigErrorReason {
#[error("invalid integer value in {field:?}")]
InvalidInteger {
field: ConfigField,
},
#[error("value out of bounds in {field:?}")]
ValueOutOfBounds {
field: ConfigField,
},
#[error("fdb cluster file path is not valid")]
InvalidClusterFilePath,
#[error("fdb cluster file path is missing or cannot be read")]
MissingClusterFile,
#[error("configuration value is empty")]
Empty,
#[error("configuration value in {field:?} is not valid unicode")]
InvalidEncoding {
field: ConfigField,
},
#[error("environment prefix is invalid")]
InvalidEnvironmentPrefix,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
pub enum FdbSetupErrorReason {
#[error("foundationdb client is already initialized in this process")]
ClientAlreadyInitialized,
#[error("api version not supported")]
ApiVersionUnsupported,
#[error("network bootstrap failed")]
NetworkBootFailed,
#[error("database open failed")]
DatabaseOpenFailed,
#[error("foundationdb client initialization panicked")]
ClientInitializationPanicked,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
pub enum FdbHealthErrorReason {
#[error("client network thread is unavailable")]
NetworkUnavailable,
#[error("cluster is unavailable")]
ClusterUnavailable,
#[error("health check deadline exceeded")]
DeadlineExceeded,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
pub enum FdbQueryErrorReason {
#[error("transaction failed")]
TransactionFailed,
#[error("tuple decode failed")]
TupleDecodeFailed,
#[error("tuple shape invalid")]
TupleShapeInvalid,
#[error("value decode failed")]
ValueDecodeFailed,
#[error("integer overflow")]
IntegerOverflow,
#[error("page size invalid")]
InvalidPageSize,
#[error("range prefix invalid")]
InvalidRangePrefix,
#[error("metadata key construction invalid")]
MetadataKeyInvalid,
}
pub type FdbResult<T> = Result<T, FdbError>;
pub fn non_zero_page_size(value: usize) -> FdbResult<NonZeroUsize> {
NonZeroUsize::new(value).ok_or(FdbError::Query {
reason: FdbQueryErrorReason::InvalidPageSize,
})
}