qrush_engine/services/
cron_service.rs

1// /Users/snm/ws/xsnm/ws/crates/qrush-engine/src/services/cron_service.rs
2
3use actix_web::{web, HttpResponse, Responder};
4use serde::Deserialize;
5use tera::Context;
6use crate::cron::cron_scheduler::CronScheduler;
7use crate::services::template_service::render_template;
8use crate::cron::cron_job::CronJobMeta;
9
10
11#[derive(Deserialize)]
12pub struct CronActionRequest {
13    pub action: String,
14    pub job_id: String,
15    pub enabled: Option<bool>,
16}
17
18#[derive(Deserialize)]
19pub struct CreateCronJobRequest {
20    pub name: String,
21    pub queue: String,
22    pub cron_expression: String,
23    pub job_type: String,
24    pub payload: serde_json::Value,
25}
26
27
28
29
30pub async fn render_cron_jobs() -> impl Responder {
31    // 1) fetch from redis (this returns HashMap<String, CronJobMeta>)
32    let map = match CronScheduler::list_cron_jobs().await {
33        Ok(m) => m,
34        Err(e) => {
35            tracing::error!("Failed to list cron jobs: {:?}", e);
36            return HttpResponse::InternalServerError().body("Failed to list cron jobs");
37        }
38    };
39
40    // 2) convert map -> vec (template expects `{% for job in cron_jobs %}`)
41    let mut cron_jobs: Vec<CronJobMeta> = map
42        .into_iter()
43        .map(|(id, mut meta)| {
44            // Ensure `job.id` exists in template
45            // If CronJobMeta already has id set, this is harmless.
46            meta.id = id;
47            meta
48        })
49        .collect();
50
51    // 3) optional sort: next_run asc
52    cron_jobs.sort_by(|a, b| a.next_run.cmp(&b.next_run));
53
54    // 4) render
55    let mut ctx = Context::new();
56    ctx.insert("title", "Cron Jobs");
57    ctx.insert("cron_jobs", &cron_jobs);
58
59    render_template("cron_jobs.html.tera", ctx).await
60}
61
62
63// pub async fn render_cron_jobs() -> impl Responder {
64//     match CronScheduler::list_cron_jobs().await {
65//         Ok(cron_jobs) => {
66//             let mut ctx = Context::new();
67//             ctx.insert("title", "Cron Jobs");
68//             ctx.insert("cron_jobs", &cron_jobs);
69//             render_template("cron_jobs.html.tera", ctx).await
70//         }
71//         Err(e) => {
72//             eprintln!("Failed to fetch cron jobs: {:?}", e);
73//             HttpResponse::InternalServerError().body("Failed to fetch cron jobs")
74//         }
75//     }
76// }
77
78pub async fn cron_action(payload: web::Json<CronActionRequest>) -> impl Responder {
79    let action = &payload.action;
80    let job_id = &payload.job_id;
81
82    let result = match action.as_str() {
83        "toggle" => {
84            let enabled = payload.enabled.unwrap_or(true);
85            CronScheduler::toggle_cron_job(job_id.clone(), enabled).await
86        }
87        "delete" => {
88            CronScheduler::delete_cron_job(job_id.clone()).await
89        }
90        "run_now" => {
91            match CronScheduler::run_now(job_id.clone()).await {
92                Ok(enqueued_id) => {
93                    return HttpResponse::Ok().json(serde_json::json!({
94                        "status": "success",
95                        "action": "run_now",
96                        "enqueued_job_id": enqueued_id
97                    }));
98                }
99                Err(e) => Err(e)
100            }
101        }
102        _ => {
103            return HttpResponse::BadRequest().json(serde_json::json!({
104                "error": "Invalid action"
105            }));
106        }
107    };
108
109    match result {
110        Ok(_) => HttpResponse::Ok().json(serde_json::json!({
111            "status": "success",
112            "action": action
113        })),
114        Err(e) => HttpResponse::InternalServerError().json(serde_json::json!({
115            "error": e.to_string()
116        }))
117    }
118}
119
120pub async fn create_cron_job(_payload: web::Json<CreateCronJobRequest>) -> impl Responder {
121    // This would need to be implemented based on your job registry
122    // For now, return a placeholder response
123    HttpResponse::Ok().json(serde_json::json!({
124        "status": "Cron job creation endpoint - implement based on your job types"
125    }))
126}