qrush 2.0.2

Lightweight Job Queue and Task Scheduler for Rust (Actix + Redis + Cron)
Documentation
//! QRush dashboard served with **Axum**.
//!
//! Run it:
//! ```sh
//! cargo run --example axum_dashboard --features dashboard-axum
//! ```
//! 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 async_trait::async_trait;
use axum::Router;
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::axum_route::qrush_metrics_router;

#[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>)
        })
    }
}

#[tokio::main]
async fn main() -> anyhow::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())?;

    // 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?;

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

    // Mount the dashboard under /qrush -> /qrush/metrics/...
    let app = Router::new().nest("/qrush", qrush_metrics_router());

    let port = std::env::var("PORT").unwrap_or_else(|_| "8080".to_string());
    println!("QRush dashboard: http://127.0.0.1:{port}/qrush/metrics");
    let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{port}")).await?;
    axum::serve(listener, app).await?;
    Ok(())
}