waddling-errors 0.7.3

Structured, secure-by-default diagnostic codes for distributed systems with no_std and role-based documentation
Documentation
//! Database Component
//!
//! PostgreSQL database operations - connection pooling, queries, transactions, data integrity.

use crate::primaries::Primary;
use waddling_errors::ComponentIdDocumented;
use waddling_errors::prelude::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Database;

impl ComponentId for Database {
    fn as_str(&self) -> &'static str {
        "Db"
    }
}

impl ComponentIdDocumented for Database {
    fn description(&self) -> Option<&'static str> {
        Some(
            "PostgreSQL database operations. Covers connection pooling, query execution, \
              transactions, and data integrity checks.",
        )
    }

    fn examples(&self) -> &'static [&'static str] {
        &[
            "E.Db.Connection.021: Database connection pool exhausted",
            "C.Db.Data.025: Foreign key constraint violation detected",
            "E.Db.Timeout.017: Query execution timeout after 30 seconds",
        ]
    }

    fn tags(&self) -> &'static [&'static str] {
        &["persistence", "sql", "transactions"]
    }
}

// ============================================================================
// Error Code Definitions
// ============================================================================

/// Database connection not found in pool (.021 = NOTFOUND)
pub const ERR_CONNECTION_NOTFOUND: Code<Database, Primary> =
    Code::error(Database, Primary::Connection, 21);

/// CRITICAL: Connection pool exhausted (.026 = EXHAUSTED)
pub const ERR_CONNECTION_EXHAUSTED: Code<Database, Primary> =
    Code::critical(Database, Primary::Connection, 26);

/// Database query timeout exceeded (.017 = TIMEOUT)
pub const ERR_TIMEOUT: Code<Database, Primary> = Code::error(Database, Primary::Timeout, 17);

/// CRITICAL: Data corruption detected (.025 = CORRUPTED)
pub const CRIT_DATA_CORRUPTED: Code<Database, Primary> =
    Code::critical(Database, Primary::Data, 25);

/// Data conflict - concurrent modification detected (.023 = CONFLICT)
pub const ERR_DATA_CONFLICT: Code<Database, Primary> = Code::error(Database, Primary::Data, 23);

/// Database constraint validation failed (.003 = INVALID)
pub const ERR_VALIDATION_INVALID: Code<Database, Primary> =
    Code::error(Database, Primary::Validation, 3);

// ============================================================================
// Component Registration
// ============================================================================

#[cfg(feature = "doc-gen")]
pub fn register_component(generator: &mut waddling_errors::doc_generator::DocRegistry) {
    use waddling_errors::Role;

    generator.register_component(
        "Db",
        Some("PostgreSQL database operations. Covers connection pooling, query execution, transactions, and data integrity checks. Includes support for read replicas, connection failover, and query performance monitoring."),
        &[
            "Connection pool management (pgbouncer/r2d2)",
            "Prepared statement execution",
            "Transaction isolation levels",
            "Foreign key constraint validation",
            "Deadlock detection and retry",
            "Query timeout and cancellation",
        ],
        &["database", "postgresql", "sql", "transactions", "persistence", "orm"]);

    // Register component locations with role-based visibility

    // PUBLIC: Example code safe for external users
    generator.register_component_location_with_role(
        "Db",
        "examples/complete_system/components/database.rs",
        Some(Role::Public),
    );
    generator.register_component_location_with_role(
        "Db",
        "examples/db_usage.rs",
        Some(Role::Public),
    );

    // DEVELOPER: Debug utilities and development tools
    generator.register_component_location_with_role(
        "Db",
        "src/db/debug_queries.rs",
        Some(Role::Developer),
    );
    generator.register_component_location_with_role(
        "Db",
        "src/db/query_profiler.rs",
        Some(Role::Developer),
    );
    generator.register_component_location_with_role(
        "Db",
        "src/db/test_fixtures.rs",
        Some(Role::Developer),
    );

    // INTERNAL: Production implementation details
    generator.register_component_location_with_role("Db", "src/db/pool.rs", Some(Role::Internal));
    generator.register_component_location_with_role(
        "Db",
        "src/db/migrations.rs",
        Some(Role::Internal),
    );
    generator.register_component_location_with_role(
        "Db",
        "src/repositories/user_repository.rs",
        Some(Role::Internal),
    );
    generator.register_component_location_with_role(
        "Db",
        "src/repositories/session_repository.rs",
        Some(Role::Internal),
    );
    generator.register_component_location_with_role(
        "Db",
        "src/db/connection_secrets.rs",
        Some(Role::Internal),
    );
}

#[cfg(feature = "doc-gen")]
pub fn register_errors(generator: &mut waddling_errors::doc_generator::DocRegistry) {
    use waddling_errors::Role;

    generator
        .register_code_extended(
            &ERR_CONNECTION_NOTFOUND,
            "Database connection not found in pool",
            &["Check DATABASE_URL", "Verify DB server is running"],
            &["database", "connectivity"],
            Some(Role::Internal),
            &["C.Db.Connection.026"], // related_codes
            None,                     // deprecated
            &[],                      // see_also
        )
        .expect("Valid error code")
        .add_snippet_for_role(
            "Internal",
            "rust",
            format!(
                "log::error!(\"[{}] Connection not found\");",
                ERR_CONNECTION_NOTFOUND.code()
            ),
            Role::Internal,
        );

    generator
        .register_code_extended(
            &ERR_CONNECTION_EXHAUSTED,
            "CRITICAL: Connection pool exhausted",
            &[
                "Scale up immediately",
                "Investigate long queries",
                "Enable read replicas",
            ],
            &["database", "performance", "critical"],
            Some(Role::Internal),
            &["E.Db.Connection.021", "E.Db.Timeout.017"], // related_codes
            None,                                         // deprecated
            &[],                                          // see_also
        )
        .expect("Valid error code")
        .add_snippet_for_role(
            "Internal",
            "rust",
            format!(
                "log::critical!(\"[{}] Pool exhausted!\");",
                ERR_CONNECTION_EXHAUSTED.code()
            ),
            Role::Internal,
        );

    generator
        .register_code_extended(
            &ERR_TIMEOUT,
            "Database query timeout exceeded",
            &[
                "Optimize query with indexes",
                "Increase timeout limit",
                "Add query cache",
            ],
            &["database", "performance"],
            Some(Role::Internal),
            &["C.Db.Connection.026"], // related_codes
            None,                     // deprecated
            &[],                      // see_also
        )
        .expect("Valid error code")
        .add_snippet_for_role(
            "Internal",
            "rust",
            format!("log::error!(\"[{}] Query timeout\");", ERR_TIMEOUT.code()),
            Role::Internal,
        );

    generator
        .register_code_extended(
            &CRIT_DATA_CORRUPTED,
            "CRITICAL: Data corruption detected",
            &["Backup immediately", "Run VACUUM FULL", "Check hardware"],
            &["database", "integrity", "critical"],
            Some(Role::Internal),
            &["E.Db.Data.023", "C.STORAGE.Data.025"], // related_codes
            None,                                     // deprecated
            &[],                                      // see_also
        )
        .expect("Valid error code")
        .add_snippet_for_role(
            "Internal",
            "rust",
            format!(
                "log::critical!(\"[{}] DATA CORRUPTED!\");",
                CRIT_DATA_CORRUPTED.code()
            ),
            Role::Internal,
        );

    generator
        .register_code_extended(
            &ERR_DATA_CONFLICT,
            "Data conflict - concurrent modification detected",
            &["Retry with latest version", "Implement optimistic locking"],
            &["database", "concurrency"],
            Some(Role::Developer),
            &[],  // related_codes
            None, // deprecated
            &[],  // see_also
        )
        .expect("Valid error code")
        .add_snippet_for_role(
            "Developer",
            "rust",
            format!(
                "if let Err(e) = save() {{\n    eprintln!(\"Conflict: {}\");\n}}",
                ERR_DATA_CONFLICT.code()
            ),
            Role::Developer,
        );

    generator
        .register_code_extended(
            &ERR_VALIDATION_INVALID,
            "Database constraint validation failed",
            &["Check foreign key references", "Verify unique constraints"],
            &["database", "validation"],
            Some(Role::Developer),
            &[],  // related_codes
            None, // deprecated
            &[],  // see_also
        )
        .expect("Valid error code")
        .add_snippet_for_role(
            "Developer",
            "rust",
            format!(
                "if let Err(e) = validate() {{\n    eprintln!(\"Validation: {}\");\n}}",
                ERR_VALIDATION_INVALID.code()
            ),
            Role::Developer,
        );
}

// ============================================================================
// Demo Functions
// ============================================================================

pub fn demo() {
    println!("🗄️  DATABASE Component Errors:\n");
    println!(
        "  {} - Connection not found",
        ERR_CONNECTION_NOTFOUND.code()
    );
    println!(
        "  {} - Connection pool exhausted",
        ERR_CONNECTION_EXHAUSTED.code()
    );
    println!("  {} - Query timeout", ERR_TIMEOUT.code());
    println!("  {} - Data corrupted", CRIT_DATA_CORRUPTED.code());
    println!("  {} - Data conflict", ERR_DATA_CONFLICT.code());
    println!("  {} - Validation failed", ERR_VALIDATION_INVALID.code());
}