use super::*;
pub(super) fn ensure_nav_indexes(
workspace: &str,
cfg: &newt_core::Config,
where_is_index: &mut Option<newt_core::WhereIsIndex>,
nav_session: &mut newt_core::NavigatorSession,
index_status: &newt_core::IndexStatus,
) {
use newt_core::{gather_with_manifest, GatherCaps};
let api_cfg = cfg
.context
.as_ref()
.map(|context| context.api_surface.clone())
.unwrap_or_default();
let packs = resolved_language_packs(workspace, &api_cfg);
let exts = newt_core::api_surface::source_extensions_for(&packs, None).unwrap_or_default();
let (files, manifest) = gather_with_manifest(workspace, &exts, GatherCaps::default());
let cuts_open = !manifest.cuts.is_empty();
let id = index_status.index_id();
if where_is_index.is_none() {
*where_is_index = Some(newt_core::build_where_is_index(&files, &packs, &manifest));
}
if nav_session.usage.is_none() {
nav_session.usage = Some(newt_core::UsageIndex::build(&files, cuts_open, &id));
}
if nav_session.graph.is_none() {
nav_session.graph = Some(newt_core::GraphIndex::build(&files, cuts_open, &id));
}
if nav_session.project.is_none() {
let root = std::path::Path::new(workspace);
nav_session.project = newt_core::project_model::scan_project(
root,
&newt_core::project_model::builtin_project_packs(),
);
}
nav_session.files = files;
nav_session.ledger.set_index(id);
}
pub(super) struct SemanticIndexWarmup {
pub(super) handle: tokio::task::JoinHandle<usize>,
pub(super) job: BackgroundJob,
}
pub(super) fn spawn_semantic_indexing(
rt: &tokio::runtime::Handle,
files: Vec<(String, String)>,
embedder: std::sync::Arc<dyn newt_core::Embedder>,
index: std::sync::Arc<newt_core::SessionSemanticIndex>,
on_failure: newt_core::OnEmbedFailure,
) -> SemanticIndexWarmup {
let job = BackgroundJob::start("embedding repository for semantic retrieval");
let completion = job.completion_guard();
let inner = rt.clone();
let handle = rt.spawn_blocking(move || {
let _completion = completion;
inner.block_on(newt_core::index_files(
&files,
embedder.as_ref(),
index.as_ref(),
on_failure,
))
});
SemanticIndexWarmup { handle, job }
}
pub(super) fn poll_semantic_indexing(
rt: &tokio::runtime::Handle,
warmup: &mut Option<SemanticIndexWarmup>,
) -> Option<usize> {
let pending = warmup.take()?;
if !pending.handle.is_finished() {
*warmup = Some(pending);
return None;
}
tokio::task::block_in_place(|| rt.block_on(pending.handle)).ok()
}
pub(super) type NavWarmupOutput = (Option<newt_core::WhereIsIndex>, newt_core::NavigatorSession);
pub(super) struct NavWarmup {
pub(super) handle: tokio::task::JoinHandle<NavWarmupOutput>,
pub(super) job: BackgroundJob,
}
impl NavWarmup {
pub(super) fn abort(self) {
self.handle.abort();
}
}
pub(super) fn spawn_nav_warmup(
rt: &tokio::runtime::Handle,
workspace: &str,
cfg: &newt_core::Config,
index_status: &newt_core::IndexStatus,
) -> NavWarmup {
let workspace = workspace.to_string();
let cfg = cfg.clone();
let index_status = index_status.clone();
let job = BackgroundJob::start("indexing repository");
let completion = job.completion_guard();
let handle = rt.spawn_blocking(move || {
let _completion = completion;
let mut where_is = None;
let mut nav = newt_core::NavigatorSession::default();
ensure_nav_indexes(&workspace, &cfg, &mut where_is, &mut nav, &index_status);
(where_is, nav)
});
NavWarmup { handle, job }
}
pub(super) fn finish_nav_warmup(
rt: &tokio::runtime::Handle,
warmup: &mut Option<NavWarmup>,
where_is: &mut Option<newt_core::WhereIsIndex>,
nav: &mut newt_core::NavigatorSession,
) {
let Some(pending) = warmup.take() else {
return;
};
if !pending.handle.is_finished() {
*warmup = Some(pending);
return;
}
if let Ok((warmed_where_is, warmed_nav)) =
tokio::task::block_in_place(|| rt.block_on(pending.handle))
{
*where_is = warmed_where_is;
*nav = warmed_nav;
}
}
pub(super) fn resolved_language_packs(
workspace: &str,
api_cfg: &newt_core::config::ApiSurfaceConfig,
) -> Vec<newt_core::config::LanguagePack> {
newt_core::api_surface::resolve_language_packs(std::path::Path::new(workspace), api_cfg)
}
pub(super) fn resolved_source_extensions(workspace: &str, cfg: &newt_core::Config) -> Vec<String> {
let api_cfg = cfg
.context
.as_ref()
.map(|context| context.api_surface.clone())
.unwrap_or_default();
let packs = resolved_language_packs(workspace, &api_cfg);
newt_core::api_surface::source_extensions_for(&packs, None).unwrap_or_default()
}
#[cfg(test)]
#[path = "../chat_tests/background_warmup.rs"]
mod background_warmup_tests;