wsb-daemon 0.248.6265

wsb's daemon: the workbench, the GitHub mirror's schedule and peer continuity, for every workspace on the machine
use wsb::prelude::*;
use axum::{extract::State, http::StatusCode, Json};

use super::fleet::{collect_repo_statuses, workspace_root_of};
use super::sessions::ErrorResponse;
use crate::web::state::WebState;

/// One worktree at a glance, read now.
///
/// Read rather than cached: every figure is a count over something this
/// daemon already holds, and the cache it replaced was written per worktree
/// into a table the machine now shares — one worktree's repository count
/// would have been every worktree's.
#[derive(Serialize)]
pub struct OverviewStats {
    /// The sessions that ran in this worktree, and their messages. None for a
    /// worktree outside `$PRJ`, which no session is placed in.
    pub session_count: Option<i64>,
    pub message_count: Option<i64>,
    pub fleet_repo_count: i64,
    pub open_issue_count: i64,
}

fn internal_error(msg: impl std::fmt::Display) -> (StatusCode, Json<ErrorResponse>) {
    (
        StatusCode::INTERNAL_SERVER_ERROR,
        Json(ErrorResponse {
            error: msg.to_string(),
        }),
    )
}

pub async fn get_overview_stats(
    State(state): State<WebState>,
) -> Result<Json<OverviewStats>, (StatusCode, Json<ErrorResponse>)> {
    let root = workspace_root_of(&state);
    let fleet_repo_count = tokio::task::spawn_blocking(move || collect_repo_statuses(&root))
        .await
        .map_err(internal_error)?
        .map_err(internal_error)?
        .len() as i64;

    let (session_count, message_count) = match state.place.clone() {
        Some(place) => {
            let db = state.sessions.clone();
            let stats = tokio::task::spawn_blocking(move || db.get_stats(false, &place))
                .await
                .map_err(internal_error)?
                .map_err(internal_error)?;
            (Some(stats.session_count), Some(stats.message_count))
        }
        None => (None, None),
    };

    Ok(Json(OverviewStats {
        session_count,
        message_count,
        fleet_repo_count,
        open_issue_count: open_issue_count(&state).await?,
    }))
}

/// How many issues are open across this worktree's repositories, as the
/// machine's mirror holds them.
async fn open_issue_count(state: &WebState) -> Result<i64, (StatusCode, Json<ErrorResponse>)> {
    let github = crate::web::github::of(state)?;
    let repositories = crate::web::github::repositories(state).await?;
    let service = github.service.clone();
    let facts = crate::web::github::blocking(move || service.overview(&repositories)).await?;
    Ok(facts.values().map(|facts| facts.open_issues).sum())
}