#![cfg(all(feature = "comms", any(unix, windows)))]
use std::path::PathBuf;
use std::sync::Arc;
use std::sync::atomic::Ordering;
use rmcp::ErrorData as McpError;
use super::helpers_comms::{comms_err, connect_ephemeral_client};
use super::{MapCache, ServerState};
use crate::comms::client::RescanReport;
use crate::store::Store;
pub(super) async fn forward_rescan_and_refresh(
state: &Arc<ServerState>,
paths: Option<Vec<PathBuf>>,
full: bool,
embed: bool,
) -> Result<RescanReport, McpError> {
let mut client = connect_ephemeral_client(state).await?;
let report = client
.rescan(state.shared.root.clone(), paths, full, embed)
.await
.map_err(comms_err)?;
refresh_cache_after_scan(state).await?;
Ok(report)
}
pub(super) async fn writer_rescan_and_refresh(
state: &Arc<ServerState>,
paths: Option<Vec<PathBuf>>,
full: bool,
embed: bool,
) -> Result<RescanReport, McpError> {
if let Some(host) = &state.shared.host {
let host = Arc::clone(host);
let root = state.shared.root.clone();
let stats = tokio::task::spawn_blocking(move || host.host_rescan(&root, paths, full, embed))
.await
.map_err(|error| McpError::internal_error(format!("host rescan task panicked: {error}"), None))?
.map_err(|error| McpError::internal_error(format!("host rescan: {error}"), None))?;
refresh_cache_after_scan(state).await?;
return Ok(RescanReport {
scanned: stats.scanned,
updated: stats.updated,
removed: stats.removed,
elapsed_ms: 0,
});
}
forward_rescan_and_refresh(state, paths, full, embed).await
}
async fn refresh_cache_after_scan(state: &Arc<ServerState>) -> Result<(), McpError> {
let view = state.shared.store.read().await.view.clone();
let root = state.shared.root.clone();
let current_fingerprint = state.shared.cache.load().fingerprint;
let (store, cache) = tokio::task::spawn_blocking(move || {
let store = Store::open_read_only_no_index(&root, &view)?;
let cache =
(super::map_fingerprint::index_fingerprint(&store) != current_fingerprint).then(|| MapCache::build(&store));
Ok::<(Store, Option<MapCache>), crate::store::StoreError>((store, cache))
})
.await
.map_err(|error| McpError::internal_error(format!("refresh map task panicked: {error}"), None))?
.map_err(|error| McpError::internal_error(format!("reopen read-only store: {error}"), None))?;
*state.shared.store.write().await = store;
if let Some(cache) = cache {
state.shared.cache.store(Arc::new(cache));
}
state.shared.cache_generation.fetch_add(1, Ordering::Relaxed);
Ok(())
}