Skip to main content

romm_cli/commands/
library_scan.rs

1//! CLI presentation wrappers for shared library scan helpers in `romm_api::core::library_scan`.
2
3use std::time::Duration;
4
5use anyhow::Result;
6use indicatif::ProgressBar;
7use serde_json::Value;
8
9use romm_api::client::RommClient;
10use romm_api::core::interrupt::InterruptContext;
11use romm_api::core::library_scan::{
12    apply_disk_cache_invalidate, start_scan_library, wait_for_task_terminal,
13};
14
15use super::OutputFormat;
16use crate::cli_presentation::CliPresentation;
17
18pub use romm_api::core::library_scan::{
19    ScanCacheInvalidate, ScanLibraryOptions, ScanLibraryStart, SCAN_LIBRARY_TASK_NAME,
20};
21
22/// CLI: poll task status with an `indicatif` spinner when text mode allows progress.
23pub async fn wait_for_scan_task(
24    client: &RommClient,
25    task_id: &str,
26    timeout: Duration,
27    interrupt: Option<&InterruptContext>,
28    presentation: CliPresentation,
29) -> Result<Value> {
30    if presentation.is_json() || !presentation.shows_progress() {
31        return wait_for_task_terminal(client, task_id, timeout, interrupt, |_| {}).await;
32    }
33
34    let pb = ProgressBar::new_spinner();
35    pb.set_draw_target(presentation.progress_draw_target());
36    pb.enable_steady_tick(Duration::from_millis(120));
37    pb.set_message(format!("Waiting for library scan (task {task_id})…"));
38
39    let result = wait_for_task_terminal(client, task_id, timeout, interrupt, |st| {
40        pb.set_message(format!("Library scan: {st}…"));
41    })
42    .await;
43
44    pb.finish_and_clear();
45    result
46}
47
48/// Start a library scan; optionally wait. Prints human text or JSON per `presentation`.
49pub async fn run_scan_library_flow(
50    client: &RommClient,
51    options: ScanLibraryOptions,
52    presentation: CliPresentation,
53    interrupt: Option<&InterruptContext>,
54) -> Result<()> {
55    let format = presentation.format;
56    match format {
57        OutputFormat::Text => println!("Triggering library scan..."),
58        OutputFormat::Json => {}
59    }
60
61    let start = start_scan_library(client, options.task_kwargs.clone()).await?;
62
63    match format {
64        OutputFormat::Text => println!(
65            "Scan started: task_id={}, status={}",
66            start.task_id, start.initial_status
67        ),
68        OutputFormat::Json if !options.wait => {
69            println!("{}", serde_json::to_string_pretty(&start.raw)?);
70        }
71        OutputFormat::Json => {}
72    }
73
74    if options.wait {
75        let final_body = wait_for_scan_task(
76            client,
77            &start.task_id,
78            options.wait_timeout,
79            interrupt,
80            presentation,
81        )
82        .await?;
83        apply_disk_cache_invalidate(&options.cache_invalidate);
84        match format {
85            OutputFormat::Text => println!("Library scan finished successfully."),
86            OutputFormat::Json => {
87                let mut out = start.raw;
88                if let Value::Object(ref mut m) = out {
89                    m.insert("final_status".into(), final_body);
90                }
91                println!("{}", serde_json::to_string_pretty(&out)?);
92            }
93        }
94    }
95
96    Ok(())
97}