pub mod config;
mod full;
mod incremental;
pub mod metrics;
mod phase1;
mod phase2;
pub mod stages;
mod stats;
pub mod types;
mod workers;
pub use config::PipelineConfig;
pub use metrics::{PipelineMetrics, StageMetrics, StageTracker};
pub use stages::cleanup::{CleanupStage, CleanupStats};
pub use stages::context::{ContextStage, ContextStats};
pub use stages::embed::{EmbedStage, EmbedStats};
pub use stages::parse::{ParseStage, init_parser_cache, parse_file};
pub use stages::resolve::{ResolveStage, ResolveStats};
pub use stages::semantic_embed::{SemanticEmbedStage, SemanticEmbedStats};
pub use stages::write::{WriteStage, WriteStats};
pub use stats::{IncrementalStats, Phase2Stats, PipelineStats, StageTimings, SyncStats};
pub use types::{
DiscoverResult, EmbedOptions, EmbeddingBatch, FileContent, FileRegistration, FileSource,
IndexBatch, ParsedFile, Phase1Options, PipelineError, PipelineResult, ProgressSink, RawImport,
RawRelationship, RawSymbol, ResolutionContext, ResolvedBatch, ResolvedRelationship,
SingleFileStats, SymbolLookupCache, UnresolvedRelationship,
};
use crate::Settings;
use crate::semantic::SimpleSemanticSearch;
use crate::storage::DocumentIndex;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
pub struct Pipeline {
settings: Arc<Settings>,
config: PipelineConfig,
}
impl Pipeline {
pub fn new(settings: Arc<Settings>, config: PipelineConfig) -> Self {
Self { settings, config }
}
pub fn with_settings(settings: Arc<Settings>) -> Self {
let config = PipelineConfig::from_settings(&settings);
Self::new(settings, config)
}
pub fn config(&self) -> &PipelineConfig {
&self.config
}
pub fn settings(&self) -> &Settings {
&self.settings
}
fn get_start_counters(&self, index: &DocumentIndex) -> PipelineResult<(u32, u32)> {
let file_id = index.get_next_file_id()?.saturating_sub(1);
let symbol_id = index.get_next_symbol_id()?.saturating_sub(1);
Ok((file_id, symbol_id))
}
fn save_final_counters(
&self,
index: &DocumentIndex,
file_count: u32,
symbol_count: u32,
) -> PipelineResult<()> {
use crate::storage::MetadataKey;
index.start_batch()?;
index.store_metadata(MetadataKey::FileCounter, u64::from(file_count))?;
index.store_metadata(MetadataKey::SymbolCounter, u64::from(symbol_count))?;
index.commit_batch()?;
Ok(())
}
fn persist_embeddings(
&self,
semantic: Option<&Arc<Mutex<SimpleSemanticSearch>>>,
semantic_path: &Path,
) -> PipelineResult<()> {
let Some(sem) = semantic else {
return Ok(());
};
let guard = sem.lock().map_err(|_| PipelineError::Parse {
path: PathBuf::new(),
reason: "Failed to lock semantic search".to_string(),
})?;
guard.save(semantic_path).map_err(|e| {
tracing::error!(target: "pipeline", "Failed to save embeddings: {e}");
PipelineError::Parse {
path: semantic_path.to_path_buf(),
reason: format!("Failed to save embeddings: {e}"),
}
})
}
}