use std::fs;
use std::sync::Arc;
use std::time::Instant;
use tempfile::tempdir;
use scryer_db::{ProjectRegistry, Scope, ScryerDb, SourceFile, Symbol};
use scryer_engine::EngineService;
#[tokio::test]
async fn test_concurrency_and_high_throughput_5000_files() -> anyhow::Result<()> {
let temp = tempdir()?;
let root = temp.path().join("concurrency_repo");
fs::create_dir_all(&root)?;
const FILE_COUNT: usize = 5000;
println!("Generating {FILE_COUNT} synthetic source files...");
for i in 0..FILE_COUNT {
let dir_index = i / 100;
let dir_path = root.join(format!("pkg_{dir_index:02}"));
if i % 100 == 0 {
fs::create_dir_all(&dir_path)?;
}
let file_path = dir_path.join(format!("item_{i:04}.rs"));
let code = format!(
r#"
pub struct ItemRecord_{i:04} {{
pub id: u64,
}}
impl ItemRecord_{i:04} {{
pub fn compute_{i:04}(&self) -> u64 {{
self.id * 2
}}
}}
"#
);
fs::write(&file_path, code)?;
}
let db = ScryerDb::new_in_memory().await?;
let registry = Arc::new(ProjectRegistry::new(db.inner()).await?);
let project = registry
.register_or_update(&root, Some("concurrency-stress"))
.await?;
let engine = EngineService::with_thread_count(db.clone(), 16);
println!("Starting 16-thread Rayon parallel indexing to Turso...");
let start_time = Instant::now();
let report = engine.index_project(project.id, &root).await?;
let elapsed = start_time.elapsed();
println!("Indexed 5,000 files in {:.2?}", elapsed);
let max_duration_secs = if cfg!(debug_assertions) { 75 } else { 20 };
assert!(
elapsed.as_secs() < max_duration_secs,
"5,000 file indexing must complete in under {max_duration_secs} seconds, took {:.2?}",
elapsed
);
assert_eq!(report.scanned_files, FILE_COUNT);
assert_eq!(report.added_files, FILE_COUNT);
assert_eq!(report.modified_files, 0);
assert_eq!(report.deleted_files, 0);
let mut guard = db.lock().await;
let db_files = SourceFile::filter(SourceFile::fields().project_id().eq(project.id))
.exec(&mut *guard)
.await?;
assert_eq!(
db_files.len(),
FILE_COUNT,
"Database SourceFile count must match exactly 5,000"
);
let db_symbols = Symbol::filter(Symbol::fields().project_id().eq(project.id))
.exec(&mut *guard)
.await?;
assert_eq!(
db_symbols.len(),
FILE_COUNT * 2,
"Database Symbol count must match exactly 10,000"
);
let db_scopes = Scope::filter(Scope::fields().project_id().eq(project.id))
.exec(&mut *guard)
.await?;
assert!(
db_scopes.len() >= FILE_COUNT * 2,
"Database Scope count ({}) must match expected scope bounds",
db_scopes.len()
);
println!("✅ 100% data integrity confirmed across 5,000 files and 10,000 symbols!");
Ok(())
}