prest 0.5.1

Progressive RESTful framework
Documentation
use crate::*;
use std::collections::HashMap;

pub(crate) async fn full() -> Result<Markup> {
    let jobs_records = ScheduledJobRecord::select_all().await?;

    #[derive(Default)]
    struct ScheduledJobStat {
        finished_successfully: u32,
        in_progress: u32,
        avg_duration: f64,
        errors: Vec<(NaiveDateTime, String)>,
    }

    let jobs_stats: HashMap<String, ScheduledJobStat> = jobs_records.into_iter().fold(
        HashMap::new(),
        |mut map,
         ScheduledJobRecord {
             name,
             start,
             end,
             error,
             ..
         }| {
            let entry = map.entry(name).or_default();

            if end.is_none() {
                entry.in_progress += 1;
            } else if end.is_some() && error.is_none() {
                let updated_successes = entry.finished_successfully + 1;
                let duration = (end.unwrap() - start).num_milliseconds().abs() as f64;

                let updated_avg_duration =
                    (entry.finished_successfully as f64 * entry.avg_duration + duration)
                        / (updated_successes as f64);

                entry.finished_successfully = updated_successes;
                entry.avg_duration = updated_avg_duration;
            } else if end.is_some() && error.is_some() {
                entry.errors.push((end.unwrap(), error.unwrap()));
            }

            map
        },
    );

    Ok(html! {
        $"w-full" get="/admin/schedule_stats" trigger="load delay:10s" swap-this-no-transition {
            $"font-bold text-lg" {"Scheduled jobs stats"}
            $"w-full text-xs md:text-sm font-mono" {
                @for (name, stats) in jobs_stats {
                    @let duration = format!("{:.1}ms", stats.avg_duration);
                    $"w-full" {b{(name)}": in progress = "(stats.in_progress)", finished = "(stats.finished_successfully)", avg duration = "(duration)}
                    @for (end, error) in stats.errors {
                        p{(end)" - "(error)}
                    }
                }
            }
        }
    })
}