use std::sync::Arc;
use anyhow::{anyhow, Result};
use clap::{Parser, Subcommand};
use tracing::{info, error};
use lens_core::{
LensConfig,
search::SearchEngine,
lsp::manager::LspManager,
pipeline::FusedPipeline,
metrics::MetricsCollector,
attestation::AttestationManager,
benchmark::{BenchmarkRunner, BenchmarkOrchestrator, BenchmarkConfig},
grpc::{create_server as create_grpc_server, ServerConfig as GrpcServerConfig},
server::{create_server as create_http_server, ServerConfig as HttpServerConfig},
};
#[derive(Parser)]
#[command(name = "lens")]
#[command(about = "High-performance code search with LSP integration")]
#[command(version = env!("CARGO_PKG_VERSION"))]
struct Cli {
#[command(subcommand)]
command: Commands,
#[arg(long, default_value = "127.0.0.1")]
bind: String,
#[arg(long, default_value = "50051")]
port: u16,
#[arg(long, default_value = "./indexed-content")]
index_path: String,
#[arg(long, default_value = "true")]
enable_lsp: bool,
#[arg(long, default_value = "false")]
enable_semantic: bool,
#[arg(long, default_value = "24")]
cache_ttl: u64,
#[arg(long, default_value = "./pinned-datasets")]
dataset_path: String,
#[arg(long, default_value = "true")]
enable_datasets: bool,
#[arg(long)]
dataset_version: Option<String>,
#[arg(long, default_value = "true")]
enable_validation: bool,
}
#[derive(Subcommand)]
enum Commands {
Serve,
ServeGrpc,
Benchmark {
#[arg(long, default_value = "storyviz")]
dataset: String,
#[arg(long)]
limit: Option<u32>,
#[arg(long)]
smoke: bool,
#[arg(long, default_value = "true")]
reports: bool,
},
Validate {
#[arg(long, default_value = "storyviz")]
dataset: String,
},
Health,
}
#[tokio::main]
async fn main() -> Result<()> {
let cli = Cli::parse();
tracing_subscriber::fmt::init();
let config = LensConfig {
server_port: cli.port,
index_path: cli.index_path.clone(),
lsp_enabled: cli.enable_lsp,
cache_ttl_hours: cli.cache_ttl,
performance_target_ms: 150,
dataset_path: cli.dataset_path,
enable_pinned_datasets: cli.enable_datasets,
default_dataset_version: cli.dataset_version.or_else(||
Some(lens_core::benchmark::DEFAULT_PINNED_VERSION.to_string())
),
enable_corpus_validation: cli.enable_validation,
..Default::default()
};
match cli.command {
Commands::Serve => {
info!("🚀 Starting Lens HTTP API server with Rust architecture");
serve_http(config, cli.bind, cli.port, cli.enable_semantic).await
}
Commands::ServeGrpc => {
info!("🚀 Starting Lens gRPC server (legacy mode)");
serve_grpc(config, cli.bind, cli.port, cli.enable_semantic).await
}
Commands::Benchmark { dataset, limit, smoke, reports } => {
info!("🧪 Running benchmark suite for dataset: {}", dataset);
run_benchmark(config, dataset, limit, smoke, reports).await
}
Commands::Validate { dataset } => {
info!("✅ Validating corpus consistency for dataset: {}", dataset);
validate_corpus(config, dataset).await
}
Commands::Health => {
info!("💓 Checking system health");
check_health(config).await
}
}
}
async fn serve_http(
config: LensConfig,
bind_address: String,
port: u16,
enable_semantic: bool,
) -> Result<()> {
info!("Initializing HTTP REST API server components...");
let search_config = lens_core::search::SearchConfig {
index_path: config.index_path.clone(),
max_results_default: config.max_results,
sla_target_ms: config.performance_target_ms,
lsp_routing_rate: if config.lsp_enabled { 0.5 } else { 0.0 },
enable_fusion_pipeline: false, enable_semantic_search: enable_semantic,
enable_lsp: config.lsp_enabled,
context_lines: 3,
dataset_path: config.dataset_path.clone(),
enable_pinned_datasets: config.enable_pinned_datasets,
default_dataset_version: config.default_dataset_version.clone(),
enable_corpus_validation: config.enable_corpus_validation,
};
let search_engine = SearchEngine::with_config(&config.index_path, search_config).await
.map_err(|e| anyhow::anyhow!("Failed to create search engine: {}", e))?;
let search_engine = Arc::new(search_engine);
let metrics_collector = Arc::new(MetricsCollector::new());
let attestation_manager = Arc::new(AttestationManager::new(config.attestation_enabled)?);
let benchmark_config = BenchmarkConfig::default();
let benchmark_runner = Arc::new(BenchmarkRunner::new(
search_engine.clone(),
metrics_collector.clone(),
benchmark_config,
));
let http_server_config = HttpServerConfig {
bind_address,
port,
enable_cors: true,
request_timeout: std::time::Duration::from_millis(config.performance_target_ms),
max_request_size: 1024 * 1024, enable_tracing: true,
};
info!("🌐 Starting HTTP API server on {}:{}", http_server_config.bind_address, http_server_config.port);
create_http_server(
http_server_config,
search_engine,
metrics_collector,
attestation_manager,
benchmark_runner,
).await?;
Ok(())
}
async fn serve_grpc(
config: LensConfig,
bind_address: String,
port: u16,
enable_semantic: bool,
) -> Result<()> {
info!("Initializing Rust migration components...");
let search_config = lens_core::search::SearchConfig {
index_path: config.index_path.clone(),
max_results_default: config.max_results,
sla_target_ms: config.performance_target_ms,
lsp_routing_rate: if config.lsp_enabled { 0.5 } else { 0.0 },
enable_fusion_pipeline: false, enable_semantic_search: enable_semantic,
enable_lsp: config.lsp_enabled,
context_lines: 3,
dataset_path: config.dataset_path.clone(),
enable_pinned_datasets: config.enable_pinned_datasets,
default_dataset_version: config.default_dataset_version.clone(),
enable_corpus_validation: config.enable_corpus_validation,
};
let search_engine = SearchEngine::with_config(&config.index_path, search_config).await
.map_err(|e| anyhow::anyhow!("Failed to create search engine: {}", e))?;
if config.lsp_enabled {
info!("🔧 Initializing LSP manager with real language servers");
let lsp_config = lens_core::lsp::LspConfig::default();
let _lsp_manager = LspManager::new(lsp_config).await
.map_err(|e| anyhow::anyhow!("Failed to create LSP manager: {}", e))?;
}
info!("⚡ Initializing zero-copy fused pipeline");
let pipeline_config = lens_core::pipeline::PipelineConfig {
max_latency_ms: config.performance_target_ms,
..Default::default()
};
let pipeline = FusedPipeline::new(pipeline_config).await
.map_err(|e| anyhow::anyhow!("Failed to create fused pipeline: {}", e))?;
let search_engine = Arc::new(search_engine);
let metrics_collector = Arc::new(MetricsCollector::new());
let attestation_manager = Arc::new(AttestationManager::new(config.attestation_enabled)?);
let benchmark_config = BenchmarkConfig::default();
let benchmark_runner = Arc::new(BenchmarkRunner::new(
search_engine.clone(),
metrics_collector.clone(),
benchmark_config,
));
let server_config = GrpcServerConfig {
bind_address,
port,
max_concurrent_requests: 1000,
request_timeout: std::time::Duration::from_millis(config.performance_target_ms),
enable_reflection: false, enable_health_check: true,
};
info!("🌐 Starting gRPC server on {}:{}", server_config.bind_address, server_config.port);
let server = create_grpc_server(
server_config,
search_engine,
metrics_collector,
attestation_manager,
benchmark_runner,
).await?;
tokio::select! {
result = server => {
if let Err(e) = result {
error!("gRPC server error: {}", e);
}
}
_ = tokio::signal::ctrl_c() => {
info!("🛑 Received shutdown signal");
}
}
info!("Server shutdown complete");
Ok(())
}
async fn run_benchmark(
config: LensConfig,
dataset: String,
query_limit: Option<u32>,
smoke_test: bool,
generate_reports: bool,
) -> Result<()> {
let search_engine = Arc::new(SearchEngine::new(&config.index_path).await?);
let metrics_collector = Arc::new(MetricsCollector::new());
let benchmark_config = BenchmarkConfig::default();
let benchmark_runner = BenchmarkRunner::new(
search_engine,
metrics_collector,
benchmark_config,
);
info!("🏃 Starting benchmark execution...");
match benchmark_runner.run_benchmark(&dataset, query_limit, smoke_test).await {
Ok(results) => {
info!("✅ Benchmark completed successfully");
info!("📊 Total queries: {}", results.summary.total_queries);
info!("⚡ Average latency: {}ms", results.summary.average_latency_ms);
info!("🎯 P95 latency: {}ms", results.summary.p95_latency_ms);
info!("📈 Average Success@10: {:.3}", results.summary.average_success_at_10);
info!("🚦 SLA compliance: {:.1}%", results.summary.sla_compliance_rate * 100.0);
if results.summary.passes_performance_gates {
info!("🎉 All performance gates PASSED! System ready for production.");
} else {
error!("❌ Performance gates FAILED. Review gate analysis:");
for gate in &results.summary.gate_analysis {
if !gate.passed {
error!(" - {}: {:.1} (target: {:.1})", gate.gate_name, gate.actual_value, gate.target_value);
}
}
}
if let Some(report_path) = results.report_path {
info!("📋 Detailed report saved: {}", report_path);
}
}
Err(e) => {
error!("❌ Benchmark failed: {}", e);
return Err(anyhow::anyhow!("{}", e));
}
}
Ok(())
}
async fn validate_corpus(config: LensConfig, dataset: String) -> Result<()> {
info!("🔍 Validating corpus consistency for dataset: {}", dataset);
let benchmark_config = BenchmarkConfig {
dataset_path: config.dataset_path.clone(),
enable_corpus_validation: config.enable_corpus_validation,
default_version: config.default_dataset_version.clone(),
..BenchmarkConfig::default()
};
let orchestrator = BenchmarkOrchestrator::with_config(benchmark_config).await?;
let pinned_dataset = if dataset == "current" || dataset.is_empty() {
orchestrator.load_pinned_dataset().await?
} else {
orchestrator.load_dataset_version(&dataset).await?
};
info!("📊 Loaded dataset with {} queries for validation", pinned_dataset.queries.len());
let is_consistent = orchestrator.validate_corpus_consistency(&pinned_dataset).await?;
if is_consistent {
info!("✅ Corpus validation passed - all golden queries exist in the indexed corpus");
Ok(())
} else {
Err(anyhow!("❌ Corpus validation failed - some golden queries do not exist in the indexed corpus"))
}
}
async fn check_health(config: LensConfig) -> Result<()> {
info!("Performing system health check...");
let index_exists = tokio::fs::try_exists(&config.index_path).await.unwrap_or(false);
info!("📁 Index directory: {} - {}", config.index_path,
if index_exists { "✅ EXISTS" } else { "❌ MISSING" });
if config.lsp_enabled {
info!("🔧 LSP integration: ✅ ENABLED");
info!("🔍 Checking LSP server availability...");
let mut servers_found = 0;
let server_commands = vec![
("TypeScript", "typescript-language-server"),
("Python", "pylsp"),
("Rust", "rust-analyzer"),
("Go", "gopls"),
];
for (name, command) in server_commands {
match tokio::process::Command::new(command)
.arg("--version")
.output()
.await
{
Ok(output) if output.status.success() => {
info!(" ✅ {} LSP server found: {}", name, command);
servers_found += 1;
}
_ => {
info!(" ⚠️ {} LSP server not found: {}", name, command);
}
}
}
info!("🔧 LSP servers available: {}/4", servers_found);
} else {
info!("🔧 LSP integration: ⚠️ DISABLED");
}
info!("⚡ Performance target: ≤{}ms p95", config.performance_target_ms);
info!("🎯 SLA requirements: Success@10, nDCG@10, SLA-Recall@50");
info!("🦀 Rust version: {}", env!("CARGO_PKG_VERSION"));
info!("🏗️ Build info: {} ({})",
lens_core::built_info::GIT_VERSION.unwrap_or("unknown"),
env!("BUILD_TIMESTAMP", "unknown"));
Ok(())
}