use std::fmt;
use fraiseql_storage::backend::StorageBackend;
use super::{ServerSubsystems, StorageSubsystem};
use crate::schema::loader::SchemaStorageConfig;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum SubsystemConfigWarning {
LocalStorageInProduction,
UnknownBucket {
name: String,
},
EmptyFunctionsRegistry,
}
impl fmt::Display for SubsystemConfigWarning {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::LocalStorageInProduction => f.write_str(
"local filesystem storage is active — not suitable for multi-instance \
deployments; use S3, GCS, or Azure Blob in production",
),
Self::UnknownBucket { name } => write!(
f,
"bucket '{name}' is declared in the schema config but not found in the \
runtime storage state — requests for this bucket will return 404; \
ensure the bucket name matches exactly"
),
Self::EmptyFunctionsRegistry => f.write_str(
"the functions module directory is configured but no function \
definitions exist in the schema; the directory will be ignored",
),
}
}
}
#[must_use]
pub fn validate_subsystems_config(subsystems: &ServerSubsystems) -> Vec<SubsystemConfigWarning> {
let mut warnings = Vec::new();
if let Some(storage) = &subsystems.storage {
check_storage(&mut warnings, storage);
}
if let Some(functions) = &subsystems.functions {
if functions.config.definitions.is_empty() {
warnings.push(SubsystemConfigWarning::EmptyFunctionsRegistry);
}
}
warnings
}
fn check_storage(warnings: &mut Vec<SubsystemConfigWarning>, storage: &StorageSubsystem) {
if matches!(*storage.state.backend, StorageBackend::Local(_)) {
warnings.push(SubsystemConfigWarning::LocalStorageInProduction);
}
check_unknown_buckets(warnings, &storage.schema_config, storage);
}
fn check_unknown_buckets(
warnings: &mut Vec<SubsystemConfigWarning>,
schema_config: &SchemaStorageConfig,
storage: &StorageSubsystem,
) {
for bucket_def in &schema_config.buckets {
if !storage.state.buckets.contains_key(&bucket_def.name) {
warnings.push(SubsystemConfigWarning::UnknownBucket {
name: bucket_def.name.clone(),
});
}
}
}