use axum::routing::{get, post};
use axum::{Json, Router};
use rustqueue::axum_integration::RqState;
use rustqueue::RustQueue;
use serde_json::json;
use std::sync::Arc;
use std::time::Duration;
async fn send_email(rq: RqState, Json(body): Json<serde_json::Value>) -> Json<serde_json::Value> {
let to = body["to"].as_str().unwrap_or("unknown");
let id = rq
.push("emails", "send-welcome", json!({"to": to}), None)
.await
.unwrap();
Json(json!({"queued": true, "job_id": id.to_string()}))
}
async fn stats(rq: RqState) -> Json<serde_json::Value> {
let queues = rq.list_queues().await.unwrap();
Json(json!({"queues": queues}))
}
async fn email_worker(rq: Arc<RustQueue>) {
println!("[worker] Listening for email jobs...");
loop {
let jobs = rq.pull("emails", 10).await.unwrap();
for job in &jobs {
let to = job.data["to"].as_str().unwrap_or("?");
println!("[worker] Sending email to {to} (job {})", job.id);
tokio::time::sleep(Duration::from_millis(50)).await;
rq.ack(job.id, None).await.unwrap();
}
if jobs.is_empty() {
tokio::time::sleep(Duration::from_millis(200)).await;
}
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let rq = RustQueue::redb("/tmp/rustqueue-axum-example.db")?.build()?;
let rq = Arc::new(rq);
tokio::spawn(email_worker(Arc::clone(&rq)));
let app = Router::new()
.route("/send-email", post(send_email))
.route("/stats", get(stats))
.with_state(rq);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
println!("Server running on http://localhost:3000");
println!("Try: curl -X POST http://localhost:3000/send-email -H 'Content-Type: application/json' -d '{{\"to\":\"user@example.com\"}}'");
axum::serve(listener, app).await?;
Ok(())
}