rustploy 0.1.4

Rustploy PaaS daemon — lightweight self-hosted deployment platform
//! `Command::JobListAll`: jobs de todos os projetos, com nomes de
//! projeto/serviço resolvidos.

use crate::bootstrap::state::AppState;
use shared::{JobSummary, Response as RpResponse};
use std::collections::HashMap;

pub async fn handle(state: AppState) -> RpResponse {
    let jobs = match crate::store::job::list_all(&state.db).await {
        Ok(j) => j,
        Err(e) => return RpResponse::err("DatabaseError", e.to_string()),
    };

    // Resolve nomes de projeto/serviço com cache — evita N+1 pra cada job repetido.
    let mut proj_cache: HashMap<String, String> = HashMap::new();
    let mut svc_cache: HashMap<String, String> = HashMap::new();
    let mut summaries = Vec::with_capacity(jobs.len());

    for job in jobs {
        let project_name = if let Some(n) = proj_cache.get(&job.project_id) {
            n.clone()
        } else {
            let name = match crate::store::projects::get(&state.db, &job.project_id).await {
                Ok(Some(p)) => p.name,
                _ => job.project_id.clone(),
            };
            proj_cache.insert(job.project_id.clone(), name.clone());
            name
        };

        let trigger_service_name = match &job.trigger_service_id {
            None => None,
            Some(sid) => Some(if let Some(n) = svc_cache.get(sid) {
                n.clone()
            } else {
                let name = match crate::store::services::get(&state.db, sid).await {
                    Ok(Some(s)) => s.spec.name,
                    _ => sid.clone(),
                };
                svc_cache.insert(sid.clone(), name.clone());
                name
            }),
        };

        let last_run = crate::store::job_run::latest_for_job(&state.db, &job.id)
            .await
            .unwrap_or_default();

        let warm = crate::features::jobs::warm::status(&state.jobs_ctx(), &job).await;

        summaries.push(JobSummary {
            job,
            project_name,
            trigger_service_name,
            last_run,
            warm,
        });
    }

    RpResponse::JobSummaries(summaries)
}