qrush 3.0.1

Lightweight Job Queue and Task Scheduler for Rust (Actix/Axum + Redis + Cron)
Documentation
//! QRush dashboard served with **Actix Web**.
//!
//! Run it:
//! ```sh
//! cargo run --example actix_dashboard --features dashboard-actix
//! ```
//! Requires a reachable Redis (set `REDIS_URL`, defaults to
//! `redis://127.0.0.1:6379`). Then open http://127.0.0.1:8080/qrush/metrics.

use actix_web::{web, App, HttpServer};
use async_trait::async_trait;
use futures::future::BoxFuture;
use serde::{Deserialize, Serialize};

use qrush::config::{set_redis_url, QueueConfig};
use qrush::job::Job;
use qrush::queue::enqueue;
use qrush::registry::register_job;
use qrush::routes::metrics_route::qrush_metrics_routes;

#[derive(Serialize, Deserialize)]
struct NotifyUser {
    user_id: String,
    message: String,
}

#[async_trait]
impl Job for NotifyUser {
    async fn perform(&self) -> anyhow::Result<()> {
        println!("Notify {} -> {}", self.user_id, self.message);
        Ok(())
    }

    fn name(&self) -> &'static str {
        "NotifyUser"
    }

    fn queue(&self) -> &'static str {
        "default"
    }
}

impl NotifyUser {
    fn type_name() -> &'static str {
        "NotifyUser"
    }

    fn handler(payload: String) -> BoxFuture<'static, anyhow::Result<Box<dyn Job>>> {
        Box::pin(async move {
            let job: NotifyUser = serde_json::from_str(&payload)?;
            Ok(Box::new(job) as Box<dyn Job>)
        })
    }
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    tracing_subscriber::fmt::init();

    let redis_url =
        std::env::var("REDIS_URL").unwrap_or_else(|_| "redis://127.0.0.1:6379".to_string());
    set_redis_url(redis_url.clone()).expect("failed to set Redis URL");

    // Register job types, then start the worker + cron pools.
    register_job(NotifyUser::type_name(), NotifyUser::handler);
    let queues = vec![QueueConfig::new("default", 5, 0)];
    QueueConfig::initialize(redis_url, queues)
        .await
        .expect("failed to initialize queues");

    // Enqueue a sample job so the dashboard has something to display.
    let _ = enqueue(NotifyUser {
        user_id: "123".into(),
        message: "Hello from the Actix example".into(),
    })
    .await;

    let port: u16 = std::env::var("PORT")
        .ok()
        .and_then(|p| p.parse().ok())
        .unwrap_or(8080);
    println!("QRush dashboard: http://127.0.0.1:{port}/qrush/metrics");
    HttpServer::new(|| App::new().service(web::scope("/qrush").configure(qrush_metrics_routes)))
        .bind(("0.0.0.0", port))?
        .run()
        .await
}