mineral-server 0.5.10

Mineral 后台 server:收纳 audio engine + task scheduler + channels,对外发 ClientHandle
//! 埋点遗忘防线(编译期强制)。
//!
//! 两层穷尽 `match`(项目规约禁 `_ =>` 兜底):
//!
//! - **入口层**:[`Request`] / [`ScriptCmd`] / [`ChannelFetchKind`] / [`PlaylistWriteOp`]
//!   ——加变体不补这里 → 编译错误 → 逼开发者对新入口做出「记 / 不记」的显式决策。
//! - **事件层**:[`BehaviorEvent`] / [`SystemEvent`]——加变体(= 建新事件类型)不补发射
//!   点账本 → 编译错误 → 逼开发者声明**谁发它**,防「有表有变体但无发出站点」的恒零列。
//!
//! 本模块运行期从不被调用——价值全在编译期穷尽性。即便无人调用,rustc
//! 仍完整类型检查函数体,故防线不因 `dead_code` 抑制而失效。防线只强制**决策存在**;
//! 「标了 [`TrackingDecision::Recorded`] 但挂接点忘调 recorder」与「不加任何变体的全新
//! 代码路径忘发既有事件」编译期兜不住,由触发链集成测试兜底。

// 编译期防线,非运行期调用;穷尽性即价值,不因未调用而失效。
#![allow(dead_code)]

use mineral_protocol::Request;
use mineral_script::ScriptCmd;
use mineral_stats::{BehaviorEvent, SystemEvent};
use mineral_task::{ChannelFetchKind, PlaylistWriteOp};

/// 一个行为入口变体的埋点归属决策。
enum TrackingDecision {
    /// 已埋,落到哪张事件表。
    Recorded(&'static str),

    /// 明确不是事件(轮询读 / 渲染流 / 纯控制流),附不记的理由。
    NotAnEvent(&'static str),
}

/// client 请求入口的埋点归属(穷尽;新增 [`Request`] 变体不补此处即编译失败)。
fn audit_request(req: &Request) -> TrackingDecision {
    use TrackingDecision::{NotAnEvent, Recorded};
    match req {
        Request::Pause => Recorded("pauses"),
        Request::Resume => Recorded("pauses"),
        Request::Stop => Recorded("plays"),
        Request::Seek(..) => Recorded("seeks"),
        Request::AudioOutputs => NotAnEvent("read: audio output devices"),
        Request::SetAudioOutput(..) => {
            NotAnEvent("session control: recorded in audio structured logs")
        }
        Request::SetVolume(..) => Recorded("volume_changes"),
        Request::SubmitTask(..) => {
            NotAnEvent("任务提交;取数事件在 task 终态记,见 audit_fetch_kind")
        }
        Request::PlaySong(..) => Recorded("plays"),
        Request::PlayQueue { .. } => Recorded("queue_ops"),
        Request::QueueInsertNext { .. } => Recorded("queue_ops"),
        Request::QueueAppend { .. } => Recorded("queue_ops"),
        Request::QueueEdit { .. } => Recorded("queue_ops"),
        Request::Playlist { .. } => Recorded("playlist_ops"),
        Request::ChannelCaps => NotAnEvent("读:channel 能力查询"),
        Request::ServiceInfo => NotAnEvent("读:daemon 服务能力查询"),
        Request::CyclePlayMode => Recorded("mode_changes"),
        Request::SetPlayMode(..) => Recorded("mode_changes"),
        // 切上首=skip 记 plays;回曲首(超阈值)分支另记 seeks,主归属取 plays。
        Request::PrevOrRestart => Recorded("plays"),
        Request::NextSong => Recorded("plays"),
        Request::DaemonInfo => NotAnEvent("读:daemon 信息"),
        Request::ToggleLove(..) => Recorded("love_changes"),
        Request::QuerySongStats(..) => NotAnEvent("读:单曲统计查询,事实来自 stats.db"),
        Request::Download(..) => Recorded("downloads"),
        Request::StopDownload(..) => NotAnEvent("session control:只写 structured log"),
        Request::StoreGet { .. } => NotAnEvent("读:per-song KV 读"),
        Request::StoreSet { .. } => Recorded("store_writes"),
        Request::TerminalState { .. } => Recorded("fullscreen_changes"),
        Request::Shutdown => Recorded("app_lifecycle"),
    }
}

/// 脚本命令入口的埋点归属(穷尽)。镜像用户动作的命令落各行为表(actor=script);读类
/// 与「触发取数 task」类不在此直接记(事件在 task 终态由 [`audit_fetch_kind`] 归属)。
fn audit_script_cmd(cmd: &ScriptCmd) -> TrackingDecision {
    use TrackingDecision::{NotAnEvent, Recorded};
    match cmd {
        ScriptCmd::Toggle => Recorded("pauses"),
        ScriptCmd::Next => Recorded("plays"),
        ScriptCmd::Prev => Recorded("plays"),
        ScriptCmd::Stop => Recorded("plays"),
        ScriptCmd::SeekRel(..) => Recorded("seeks"),
        ScriptCmd::SeekTo(..) => Recorded("seeks"),
        ScriptCmd::SetVolume(..) => Recorded("volume_changes"),
        ScriptCmd::SetMode(..) => Recorded("mode_changes"),
        ScriptCmd::Play(..) => Recorded("plays"),
        ScriptCmd::Download(..) => Recorded("downloads"),
        ScriptCmd::StoreGet { .. } => NotAnEvent("读:脚本 KV 读"),
        ScriptCmd::StoreSet { .. } => Recorded("store_writes"),
        ScriptCmd::QueueList { .. } => NotAnEvent("读:队列查询"),
        ScriptCmd::QueueSet { .. } => Recorded("queue_ops"),
        ScriptCmd::LibraryPlaylists { .. } => {
            NotAnEvent("触发取数 task;fetches 在终态记,见 audit_fetch_kind")
        }
        ScriptCmd::LibraryTracks { .. } => NotAnEvent("触发取数 task;fetches 在终态记"),
        ScriptCmd::LibrarySearch { .. } => {
            NotAnEvent("触发搜索 task;searches 在终态记,见 audit_fetch_kind")
        }
        ScriptCmd::LibrarySongUrl { .. } => {
            NotAnEvent("查询 direct media capability;stream_resolutions 在 provider resolve 终态记")
        }
        ScriptCmd::SetLoved { .. } => Recorded("love_changes"),
        ScriptCmd::ConfigOverride { .. } => Recorded("config_overrides"),
    }
}

/// 取数 task 入口的埋点归属
fn audit_fetch_kind(kind: &ChannelFetchKind) -> TrackingDecision {
    use TrackingDecision::Recorded;
    match kind {
        ChannelFetchKind::Search { .. } => Recorded("searches"),
        ChannelFetchKind::MyAlbums { .. } | ChannelFetchKind::MyPlaylists { .. } => {
            Recorded("fetches")
        }
        ChannelFetchKind::PlaylistDetail { .. } => Recorded("fetches"),
        ChannelFetchKind::Lyrics { .. } => Recorded("fetches"),
        ChannelFetchKind::RemotePlayCount { .. } => Recorded("fetches"),
        ChannelFetchKind::ArtistDetail { .. } => Recorded("fetches"),
        ChannelFetchKind::ArtistAlbums { .. } => Recorded("fetches"),
        ChannelFetchKind::AlbumDetail { .. } => Recorded("fetches"),
    }
}

/// 歌单写操作入口的埋点归属(穷尽)。全部落 `playlist_ops`(outcome/error_kind 在终态填)。
fn audit_playlist_op(op: &PlaylistWriteOp) -> TrackingDecision {
    use TrackingDecision::Recorded;
    match op {
        PlaylistWriteOp::Create { .. } => Recorded("playlist_ops"),
        PlaylistWriteOp::Delete { .. } => Recorded("playlist_ops"),
        PlaylistWriteOp::AddSongs { .. } => Recorded("playlist_ops"),
        PlaylistWriteOp::RemoveSongs { .. } => Recorded("playlist_ops"),
        PlaylistWriteOp::Rename { .. } => Recorded("playlist_ops"),
        PlaylistWriteOp::SetDescription { .. } => Recorded("playlist_ops"),
    }
}

/// 行为域事件的发射点账本(穷尽)。新增 [`BehaviorEvent`] 变体不补此处即编译失败。
/// 保留历史表示的已撤销能力明确标为「仅历史数据」,其余条目索引当前发射点。
fn audit_behavior_emitters(event: &BehaviorEvent) -> &'static str {
    match event {
        BehaviorEvent::Search { .. } => "channel_fetch 终态 + script_bridge library.search",
        BehaviorEvent::Seek { .. } => "PlayerCore::seek_playback(client / 脚本 / 媒体键统一出口)",
        BehaviorEvent::Pause { .. } => {
            "PlayerCore::pause_playback / resume_playback(client / 脚本 / 媒体键统一出口)"
        }
        BehaviorEvent::VolumeChange { .. } => "PlayerCore::set_playback_volume(统一出口)",
        BehaviorEvent::ModeChange { .. } => {
            "PlayerCore::record_mode_change(cycle / 直设 / 脚本共用)"
        }
        BehaviorEvent::LoveChange { .. } => {
            "PlayerCore::record_love_change(set_favorite / toggle_favorite / sync import 共用)"
        }
        BehaviorEvent::QueueOp { .. } => "ClientHandle 的 play_queue / insert_next / append",
        BehaviorEvent::PlaylistOp { .. } => {
            "playlist 写 task 终态(events.rs) 与 playlists::playlist_operation"
        }
        BehaviorEvent::Fetch { .. } => "channel_fetch 终态(events.rs)",
        BehaviorEvent::Download { .. } => "download.rs record_download(三种结局)",
        BehaviorEvent::CopyRender { .. } => "仅历史数据:复制模板在 client 本地执行",
        BehaviorEvent::ActionInvocation { .. } => "仅历史数据:具名脚本动作入口已删除",
        BehaviorEvent::ConfigOverride { .. } => "script_bridge ConfigOverride",
        BehaviorEvent::StoreWrite { .. } => {
            "ipc dispatch 的 StoreSet / script_bridge 的 StoreSet(Inc 仅历史数据)"
        }
        BehaviorEvent::Spawn { .. } => "仅历史数据:脚本子进程能力已删除",
        BehaviorEvent::BusMessage { .. } => "仅历史数据:脚本事件总线已删除",
        BehaviorEvent::FullscreenChange { .. } => "ipc dispatch 的 TerminalState",
        BehaviorEvent::ConnectionReject { .. } => "ipc::handshake record_connection_reject",
        BehaviorEvent::ClientConnection { .. } => "ipc::ConnGuard drop",
        BehaviorEvent::AppLifecycle { .. } => "recorder.daemon_lifecycle + ipc 会话生命周期",
    }
}

/// 系统域事件的发射点账本(穷尽)。新增 [`SystemEvent`] 变体不补此处即编译失败。
fn audit_system_emitters(event: &SystemEvent) -> &'static str {
    match event {
        SystemEvent::StreamResolution { .. } => "playback.rs provider resolve success / failure",
        SystemEvent::HookFire { .. } => "hook_bridge 各提交点裁决回来处",
        SystemEvent::GaplessBoundary { .. } => "gapless.rs check_advance 边界裁决",
        SystemEvent::Prefetch { .. } => {
            "gapless.rs 武装 + hook_bridge.rs 否决 + playback.rs 改写 / 失败"
        }
        SystemEvent::CacheHarvest { .. } => "download.rs harvest_capture 收割终态",
        SystemEvent::CacheEviction { .. } => "media_cache 淘汰点",
        SystemEvent::ScriptLifecycle { .. } => "script_reload + script_bridge 生命周期回调",
        SystemEvent::ConfigReload => "config_host 重载成功处",
    }
}