wsb-daemon 0.258.6441

wsb's daemon: the workbench, the GitHub mirror's schedule and peer continuity, for every workspace on the machine
use wsb::prelude::*;
use tokio::sync::{broadcast, RwLock};

use super::handlers::fleet::RepoDetailedStatus;
use super::handlers::workspace::WorkspaceChangedEvent;
use super::ops::OpsRegistry;
use wsb::persist::global::models::PlaceFilter;
use wsb::persist::global::{DatabaseService, SessionRepo, WsbRepos};

/// Fired when a file in the workspace is created, modified, or deleted on disk.
/// The `path` is workspace-relative (e.g. `"capdag/src/main.rs"`).
/// `mtime_secs` is the Unix timestamp of the file's new mtime, or `None` if deleted.
#[derive(Clone, Debug, serde::Serialize)]
pub struct FileChangedEvent {
    pub path: String,
    pub mtime_secs: Option<u64>,
}

#[derive(Clone)]
pub struct WebState {
    pub db: Arc<WsbRepos>,
    pub db_service: Arc<DatabaseService>,
    /// The machine's sessions — one store, shared by every worktree — and
    /// which of them ran in this worktree: none outside `$PRJ`, where no
    /// session is placed.
    pub sessions: Arc<SessionRepo>,
    pub place: Option<PlaceFilter>,
    pub workspace_root: PathBuf,
    /// The address the workbench is bound to. Reported by the settings page,
    /// which must state where this daemon actually listens rather than a
    /// remembered preference that may never have been applied.
    pub listen: std::net::IpAddr,
    pub port: u16,
    pub git_status_tx: broadcast::Sender<RepoDetailedStatus>,
    pub git_status_snapshot: Arc<RwLock<HashMap<String, RepoDetailedStatus>>>,
    pub git_focus_tx: broadcast::Sender<String>,
    pub git_nudge_tx: broadcast::Sender<Option<String>>,
    pub ops: OpsRegistry,
    /// Broadcast channel for workspace file change events.
    pub file_changed_tx: broadcast::Sender<FileChangedEvent>,
    /// Broadcast channel for workspace tree change events: which listings the
    /// explorer must re-read, and which repository's subtree moved with them.
    pub workspace_changed_tx: broadcast::Sender<WorkspaceChangedEvent>,
    /// The machine's GitHub mirror, shared by every workspace this daemon
    /// serves, or why there is none. Its change broadcast is how a page learns
    /// that what it shows is no longer what is held.
    pub github: Result<Arc<super::github::GitHub>, String>,
}

impl WebState {
    pub async fn new(
        db: Arc<WsbRepos>,
        db_service: Arc<DatabaseService>,
        sessions: Arc<SessionRepo>,
        place: Option<PlaceFilter>,
        workspace_root: PathBuf,
        listen: std::net::IpAddr,
        port: u16,
        github: Result<Arc<super::github::GitHub>, String>,
    ) -> Result<Self> {
        let (git_status_tx, _) = broadcast::channel(64);
        let (git_focus_tx, _) = broadcast::channel(16);
        let (git_nudge_tx, _) = broadcast::channel::<Option<String>>(64);
        let (file_changed_tx, _) = broadcast::channel(256);
        let (workspace_changed_tx, _) = broadcast::channel::<WorkspaceChangedEvent>(64);

        let logs_root = wsb::logs::root(&workspace_root);

        Ok(Self {
            db,
            db_service,
            sessions,
            place,
            workspace_root,
            listen,
            port,
            git_status_tx,
            git_status_snapshot: Arc::new(RwLock::new(HashMap::new())),
            git_focus_tx,
            git_nudge_tx,
            // Command lines write their operation logs under the workspace's
            // logs root, and the registry reads them from there, so a run's
            // output outlives the ring buffer's capacity and this process.
            ops: OpsRegistry::with_logs(logs_root),
            file_changed_tx,
            workspace_changed_tx,
            github,
        })
    }
}