athena_rs 3.26.2

Hyper performant polyglot Database driver
Documentation
use anyhow::{Context, Result, anyhow};
use dotenv::from_path;
use std::path::{Path, PathBuf};
use tracing::{info, warn};

use crate::bootstrap::{Bootstrap, RuntimeConfigMetadata, build_shared_state};
use crate::config::{Config, ConfigLocation, DEFAULT_CONFIG_FILE_NAME};
use crate::config_validation::initialize_runtime_env_settings;

const DEFAULT_PIPELINES_PATH: &str = "config/pipelines.yaml";

pub struct RuntimeBootstrapContext {
    pub bootstrap: Bootstrap,
    pub config: Config,
    pub pipelines_path: String,
    pub resolved_config_path: PathBuf,
    pub runtime_config_metadata: RuntimeConfigMetadata,
}

pub async fn load_runtime_bootstrap_from_env() -> Result<RuntimeBootstrapContext> {
    let config_override = std::env::var("ATHENA_CONFIG_PATH")
        .ok()
        .filter(|value| !value.trim().is_empty())
        .map(PathBuf::from);
    let pipelines_path = DEFAULT_PIPELINES_PATH.to_string();

    let (config, resolved_config_path, source_label, seeded_default) =
        load_runtime_config(config_override.as_ref())?;
    load_dotenv_beside_config_file(&resolved_config_path);
    initialize_runtime_env_settings(&config.validation_ranges);

    let runtime_config_metadata = RuntimeConfigMetadata {
        config_path: Some(resolved_config_path.to_string_lossy().to_string()),
        source_label: Some(source_label),
        seeded_default,
    };
    let bootstrap = build_shared_state(&config, &pipelines_path, runtime_config_metadata.clone())
        .await
        .context("failed to build shared Athena runtime state")?;

    info!(
        config_path = %resolved_config_path.display(),
        pipelines_path = %pipelines_path,
        "Loaded shared Athena runtime bootstrap"
    );

    Ok(RuntimeBootstrapContext {
        bootstrap,
        config,
        pipelines_path,
        resolved_config_path,
        runtime_config_metadata,
    })
}

fn load_runtime_config(
    config_override: Option<&PathBuf>,
) -> Result<(Config, PathBuf, String, bool)> {
    if let Some(path) = config_override {
        let config = Config::load_from(path).map_err(|err| {
            let attempted = vec![ConfigLocation::new(
                "explicit ATHENA_CONFIG_PATH".to_string(),
                path.clone(),
            )];
            anyhow!(
                "failed to load config '{}': {}. Looked in:\n{}",
                path.display(),
                err,
                format_attempted_locations(&attempted)
            )
        })?;
        return Ok((
            config,
            path.clone(),
            "ATHENA_CONFIG_PATH".to_string(),
            false,
        ));
    }

    let outcome = Config::load_default().map_err(|err| {
        anyhow!(
            "failed to load config '{}': {}. Looked in:\n{}",
            DEFAULT_CONFIG_FILE_NAME,
            err,
            format_attempted_locations(&err.attempted_locations)
        )
    })?;
    let source_label = outcome
        .attempted_locations
        .iter()
        .find(|location| location.path == outcome.path)
        .map(|location| location.label.clone())
        .unwrap_or_else(|| "auto-discovered config path".to_string());
    Ok((
        outcome.config,
        outcome.path,
        source_label,
        outcome.seeded_default,
    ))
}

fn config_sidecar_dotenv_path(config_file: &Path) -> PathBuf {
    config_file
        .parent()
        .unwrap_or_else(|| Path::new("."))
        .join(".env")
}

fn load_dotenv_beside_config_file(config_file: &Path) {
    let env_path = config_sidecar_dotenv_path(config_file);
    if !env_path.exists() {
        return;
    }

    match from_path(&env_path) {
        Ok(()) => info!(path = %env_path.display(), "Loaded supplementary .env beside config file"),
        Err(err) => warn!(
            path = %env_path.display(),
            error = %err,
            "Found .env beside config file but failed to parse it; ignoring"
        ),
    }
}

fn format_attempted_locations(locations: &[ConfigLocation]) -> String {
    locations
        .iter()
        .map(|location| format!("- {}", location.describe()))
        .collect::<Vec<_>>()
        .join("\n")
}