waddling-errors 0.7.3

Structured, secure-by-default diagnostic codes for distributed systems with no_std and role-based documentation
Documentation
//! Queue Component
//!
//! Background job processing - async tasks, job scheduling, retry logic, worker pools.

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

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

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

impl ComponentIdDocumented for Queue {
    fn description(&self) -> Option<&'static str> {
        Some(
            "Background job processing system. Manages async tasks, job scheduling, \
              retry logic, and worker pool management.",
        )
    }

    fn examples(&self) -> &'static [&'static str] {
        &[
            "E.Queue.Connection.021: Message broker not found",
            "B.Queue.Timeout.017: Job execution in progress (5/10 min)",
            "W.Queue.Validation.003: Job payload validation warning",
        ]
    }

    fn tags(&self) -> &'static [&'static str] {
        &["async", "background-jobs", "workers"]
    }
}

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

/// Message broker connection not found (.021 = NOTFOUND)
pub const ERR_CONNECTION_NOTFOUND: Code<Queue, Primary> =
    Code::error(Queue, Primary::Connection, 21);

/// Background job execution in progress (.015 = INPROGRESS)
pub const BLOCKED_TIMEOUT_INPROGRESS: Code<Queue, Primary> =
    Code::blocked(Queue, Primary::Timeout, 15);

/// Background job cancelled by user/timeout (.014 = CANCELLED)
pub const ERR_JOB_CANCELLED: Code<Queue, Primary> = Code::error(Queue, Primary::Timeout, 14);

/// Job payload validation warning (.003 = INVALID)
pub const WARN_VALIDATION_INVALID: Code<Queue, Primary> =
    Code::warning(Queue, Primary::Validation, 3);

/// Background job completed successfully (.999 = COMPLETE)
pub const SUCCESS_JOB_COMPLETED: Code<Queue, Primary> = Code::completed(Queue, Primary::Data, 999);

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

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

    generator.register_component(
        "Queue",
        Some("Background job processing system. Manages async tasks, job scheduling, retry logic, and worker pool management. Supports priority queues, delayed jobs, and job result tracking with dead letter queues."),
        &[
            "Async job enqueueing and processing",
            "Priority-based job scheduling",
            "Automatic retry with backoff",
            "Worker pool scaling",
            "Job progress tracking",
            "Dead letter queue for failed jobs",
        ],
        &["Queue", "async", "background-jobs", "workers", "rabbitmq", "celery"]);

    // Register component locations with role-based visibility

    // PUBLIC: Examples for external users
    generator.register_component_location_with_role(
        "Queue",
        "examples/complete_system/components/queue.rs",
        Some(Role::Public),
    );
    generator.register_component_location_with_role(
        "Queue",
        "examples/queue_usage.rs",
        Some(Role::Public),
    );

    // DEVELOPER: Job monitoring and debugging
    generator.register_component_location_with_role(
        "Queue",
        "src/queue/job_monitor.rs",
        Some(Role::Developer),
    );
    generator.register_component_location_with_role(
        "Queue",
        "src/queue/debug_utils.rs",
        Some(Role::Developer),
    );

    // INTERNAL: Production implementation
    generator.register_component_location_with_role(
        "Queue",
        "src/queue/job_processor.rs",
        Some(Role::Internal),
    );
    generator.register_component_location_with_role(
        "Queue",
        "src/queue/worker_pool.rs",
        Some(Role::Internal),
    );
    generator.register_component_location_with_role(
        "Queue",
        "src/jobs/email_job.rs",
        Some(Role::Internal),
    );
    generator.register_component_location_with_role(
        "Queue",
        "src/queue/dlq_handler.rs",
        Some(Role::Internal),
    );
}

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

    let errors = vec![
        (
            "E.Queue.Connection.021",
            "Message broker connection not found",
            &["Check BROKER_URL", "Verify RabbitMQ/SQS is running"][..],
            &["Queue", "messaging", "connectivity"][..],
            Role::Internal,
        ),
        (
            "B.Queue.Timeout.015",
            "Background job execution in progress",
            &["Job running", "Check progress logs", "Wait for completion"],
            &["Queue", "async", "jobs"],
            Role::Internal,
        ),
        (
            "E.Queue.Timeout.014",
            "Background job cancelled by user/timeout",
            &[
                "Check job logs",
                "Retry if needed",
                "Review timeout settings",
            ],
            &["Queue", "jobs"],
            Role::Developer,
        ),
        (
            "W.Queue.Validation.003",
            "Job payload validation warning",
            &[
                "Check payload schema",
                "Update job definition",
                "Validate input",
            ],
            &["Queue", "validation"],
            Role::Developer,
        ),
        (
            "K.Queue.Data.999",
            "Background job completed successfully",
            &["Job finished", "Check results in database"],
            &["Queue", "success"],
            Role::Internal,
        ),
    ];

    for (code, desc, hints, tags, role) in &errors {
        let _ = generator.register(*code, *desc, hints, tags);

        let snippet = match role {
            Role::Internal => format!(
                "// Internal debugging\nlog::error!(\"[{}] {}\");",
                code, desc
            ),
            Role::Developer => format!(
                "// Developer API usage\nif let Err(e) = operation() {{\n    eprintln!(\"Error: {}\");\n}}",
                code
            ),
            Role::Public => format!(
                "// Public error handling\nmatch result {{\n    Err(_) => println!(\"Operation failed: {}\"),\n    Ok(_) => println!(\"Success\"),\n}}",
                desc
            ),
        };

        generator.add_snippet_for_role(
            format!("{:?} - Usage Example", role),
            "rust",
            snippet,
            *role,
        );
    }
}

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

pub fn demo() {
    println!("📬 QUEUE Component Errors:\n");
    println!(
        "  {} - Connection not found",
        ERR_CONNECTION_NOTFOUND.code()
    );
    println!("  {} - Job in progress", BLOCKED_TIMEOUT_INPROGRESS.code());
    println!("  {} - Job cancelled", ERR_JOB_CANCELLED.code());
    println!("  {} - Validation warning", WARN_VALIDATION_INVALID.code());
    println!("  {} - Job completed", SUCCESS_JOB_COMPLETED.code());
}