Add RabbitMQ validation, test scaffolding, and config refactor
- Extract ipl() from main() with env-aware error handling (fatal in prod, warn in dev) - Add amqp::validate() — TCP reachability check for RabbitMQ at IPL - Refactor config::load() into load() + load_from() for testability - Add lib.rs to expose public API to integration test harness - Add test fixture scaffolding: tests/fixtures/beds_test.toml, tests/common/mod.rs - Add unit tests for amqp::validate() error paths (closed port, bad address) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
76
src/main.rs
76
src/main.rs
@@ -1,10 +1,80 @@
|
||||
//! # main.rs — BEDS Entry Point
|
||||
//!
|
||||
//! Application entry point. Invokes the IPL (Initial Program Load) sequence
|
||||
//! which bootstraps all required services before the node enters its
|
||||
//! operational state.
|
||||
//!
|
||||
//! ## Calling Agents
|
||||
//! None — this is the process entry point.
|
||||
//!
|
||||
//! ## Inputs
|
||||
//! - `BEDS_ENV` environment variable selects the env config file (default: dev)
|
||||
//!
|
||||
//! ## Outputs
|
||||
//! - Running BEDS node, blocked on signal handler (not yet implemented)
|
||||
//! - On fatal IPL failure: error output to console, process exits non-zero
|
||||
//!
|
||||
//! **Author:** ms
|
||||
//! **Version:** 1.0
|
||||
//!
|
||||
//! ## History
|
||||
//! * `2026-04-02` - mks - original coding
|
||||
//! * `2026-04-02` - mks - refactored startup sequence into ipl()
|
||||
|
||||
mod amqp;
|
||||
mod config;
|
||||
mod logging;
|
||||
|
||||
fn main() {
|
||||
let cfg = config::load().expect("Failed to load config");
|
||||
/// Executes the BEDS Initial Program Load (IPL) sequence.
|
||||
///
|
||||
/// IPL bootstraps the node in strict order. Each step must succeed before
|
||||
/// the next is attempted. In production environments, any failure is fatal
|
||||
/// and the process exits with a console error report. In development
|
||||
/// environments, non-critical failures are logged and IPL continues.
|
||||
///
|
||||
/// ## IPL Sequence
|
||||
/// 1. Load configuration (beds.toml + env override)
|
||||
/// 2. Initialize logging
|
||||
/// 3. Connect to required services (AMQP, store adapters) — not yet implemented
|
||||
/// 4. Declare queues based on node role — not yet implemented
|
||||
/// 5. Node green
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// `Ok(())` if all required services are available and the node is ready.
|
||||
/// `Err(String)` with a descriptive error message if IPL cannot complete.
|
||||
///
|
||||
/// # History
|
||||
///
|
||||
/// * `2026-04-02` - mks - original coding
|
||||
fn ipl() -> Result<(), String> {
|
||||
// load configuration — fatal in all environments if this fails
|
||||
let cfg = config::load().map_err(|e| format!("Failed to load config: {}", e))?;
|
||||
|
||||
// initialize logging — must come before any tracing calls
|
||||
logging::init_from_config(cfg.syslog, cfg.syslog_mirror_console);
|
||||
tracing::info!("BEDS starting, env={}", cfg.id.env_name);
|
||||
|
||||
tracing::info!("BEDS IPL starting, node={} env={}", cfg.id.wbid, cfg.id.env_name);
|
||||
tracing::info!("Configuration loaded");
|
||||
tracing::info!("Logging initialized");
|
||||
|
||||
// validate broker reachability — fatal in production, non-fatal in all other envs
|
||||
match amqp::validate(&cfg.broker_services) {
|
||||
Ok(()) => tracing::info!("RabbitMQ reachable"),
|
||||
Err(e) => {
|
||||
if cfg.id.env_name == "production" {
|
||||
return Err(e);
|
||||
}
|
||||
tracing::warn!("RabbitMQ unreachable (non-fatal in {}): {}", cfg.id.env_name, e);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Err(e) = ipl() {
|
||||
eprintln!("[BEDS] [FATAL] [IPL] {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user