Skip to content

Commit e6fac59

Browse files
Your Nameclaude
andcommitted
refactor(pipeline): PR#7 slice 9 -- extract identity_migration.rs (issue #67 hotspot split, final slice)
Move-only extraction of the D4 CallSite-identity migration from pipeline.rs into the new pipeline/identity_migration.rs: needs_call_site_identity_baseline, record_call_site_identity_migration_status, rebuild_call_site_identity_baseline. Visibility: same sibling-module pattern as slice 8. driver.rs (a sibling of identity_migration.rs, not an ancestor) calls needs_call_site_identity_baseline/rebuild_call_site_identity_baseline from reindex_changed_cancellable/reindex_paths, so both are pub(super) here; pipeline.rs pulls them back in via a plain `use identity_migration::{...}` that driver.rs's existing `use super::{...}` block already reaches unchanged, same ancestor-reexport-cascade confirmed working in slice 8 -- no driver.rs edit needed. record_call_site_identity_migration_status stays plain private (its only caller moved with it). Verified via callers() before the move: real callers of the two pub(super) functions are exactly driver.rs::reindex_changed_cancellable/reindex_paths (2 sites each). Reverse dependency: rebuild_call_site_identity_baseline calls run_indexing_pipeline_cancellable (driver.rs, pub since slice 7) -- identity_migration.rs pulls it in via `use super::driver:: run_indexing_pipeline_cancellable`, along with PipelineOutcome/ ReindexOutcome (also pub in driver.rs). ReindexSummary/GraphMode/now_secs stay in pipeline.rs (not moved), pulled in via `super::` as usual. This completes PR#7's pipeline.rs split (issue #67): the file now holds only shared struct/type/const definitions, the 9 mod + import/re-export blocks, now_secs/signature_returns_option_or_result, and the untouched #[cfg(test)] mod tests block (never split out across all 9 slices). pipeline.rs itself: 6032 lines (post-slice-6) -> 5462 (post-slice-7) -> now well under half its original size across cache.rs/identity_migration.rs plus the 7 prior slices' modules. Also fixes two now-genuinely-unused top-level imports this slice's removal exposed: `use rusqlite::Connection;` (only the #[cfg(test)] mod tests block still needs it via `use super::*;` now that every non-test Connection use has moved out -- narrowed to #[cfg(test)]) and `use std::path::Path;` (zero remaining real, non-string-literal uses after this move -- removed outright). Verified: cargo build -p calm-core clean (both lib and --tests profiles), cargo clippy -p calm-core --all-targets 100% clean, cargo test -p calm-core 1247 passed/0 failed/12 ignored including both golden_equivalence_{continued,incremental}_vs_fresh_across_mutation_rounds, cargo fmt clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent ba9df67 commit e6fac59

2 files changed

Lines changed: 227 additions & 170 deletions

File tree

crates/calm-core/src/indexer/pipeline.rs

Lines changed: 18 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
#[cfg(test)]
12
use rusqlite::Connection;
23
use std::collections::{HashMap, HashSet};
3-
use std::path::Path;
44

55
use crate::indexer::chunker::CodeChunk;
66
use crate::indexer::parser::ParsedSymbol;
@@ -403,175 +403,23 @@ pub struct ResolutionMaps {
403403
go: crate::indexer::go_module::GoModule,
404404
}
405405

406-
/// Whether an existing database still contains CallSites whose line-only
407-
/// identity predates D4. Incremental indexing cannot repair these rows because
408-
/// their file hashes are unchanged, so it must take the full transactional
409-
/// baseline path instead of reporting a no-op.
410-
fn needs_call_site_identity_baseline(conn: &Connection) -> rusqlite::Result<bool> {
411-
conn.query_row(
412-
"SELECT EXISTS(
413-
SELECT 1 FROM call_sites
414-
WHERE identity_version < 2
415-
OR callee_start_byte IS NULL
416-
OR callee_end_byte IS NULL
417-
)",
418-
[],
419-
|row| row.get::<_, i64>(0),
420-
)
421-
.map(|exists| exists != 0)
422-
}
423-
424-
/// Update D4's diagnostic-only migration status. It is intentionally outside
425-
/// the graph transaction: a failed/cancelled baseline must preserve the old
426-
/// graph while still leaving a useful reason for operators.
427-
fn record_call_site_identity_migration_status(
428-
conn: &Connection,
429-
status: &str,
430-
failure_reason: Option<&str>,
431-
metrics: Option<(i64, i64, i64, Option<i64>)>,
432-
) -> rusqlite::Result<()> {
433-
let now = now_secs();
434-
let (started_at, completed_at, failed_at) = match status {
435-
"running" => (Some(now), None, None),
436-
"baseline_ready" => (None, Some(now), None),
437-
"failed" => (None, None, Some(now)),
438-
_ => (None, None, None),
439-
};
440-
let (duration_ms, rows_rebuilt, busy_retries, graph_generation) = metrics
441-
.map(
442-
|(duration_ms, rows_rebuilt, busy_retries, graph_generation)| {
443-
(
444-
Some(duration_ms),
445-
Some(rows_rebuilt),
446-
Some(busy_retries),
447-
graph_generation,
448-
)
449-
},
450-
)
451-
.unwrap_or((None, None, None, None));
452-
conn.execute(
453-
"INSERT INTO identity_migration_state
454-
(id, target_version, status, started_at, completed_at, failed_at, failure_reason,
455-
duration_ms, rows_rebuilt, busy_retries, graph_generation)
456-
VALUES (1, 2, ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)
457-
ON CONFLICT(id) DO UPDATE SET
458-
target_version = excluded.target_version,
459-
status = excluded.status,
460-
started_at = CASE WHEN excluded.status = 'running'
461-
THEN excluded.started_at
462-
ELSE identity_migration_state.started_at END,
463-
completed_at = excluded.completed_at,
464-
failed_at = excluded.failed_at,
465-
failure_reason = excluded.failure_reason,
466-
duration_ms = COALESCE(excluded.duration_ms, identity_migration_state.duration_ms),
467-
rows_rebuilt = COALESCE(excluded.rows_rebuilt, identity_migration_state.rows_rebuilt),
468-
busy_retries = COALESCE(excluded.busy_retries, identity_migration_state.busy_retries),
469-
graph_generation = COALESCE(excluded.graph_generation, identity_migration_state.graph_generation)",
470-
rusqlite::params![
471-
status,
472-
started_at,
473-
completed_at,
474-
failed_at,
475-
failure_reason,
476-
duration_ms,
477-
rows_rebuilt,
478-
busy_retries,
479-
graph_generation,
480-
],
481-
)?;
482-
Ok(())
483-
}
484-
485-
/// Run the one-time D4 baseline through the normal full-pipeline transaction.
486-
/// Both incremental entry points must share this path: an unchanged source hash
487-
/// cannot prove its persisted CallSite identity is current.
488-
fn rebuild_call_site_identity_baseline(
489-
conn: &mut Connection,
490-
project_root: &Path,
491-
cancel: &dyn Fn() -> bool,
492-
) -> rusqlite::Result<ReindexOutcome> {
493-
let started = std::time::Instant::now();
494-
tracing::info!("D4 CallSite identity migration detected — forcing a full baseline reparse");
495-
let phase = std::sync::Arc::new(std::sync::RwLock::new(crate::types::IndexingPhase::Parsing));
496-
if let Err(error) = record_call_site_identity_migration_status(conn, "running", None, None) {
497-
tracing::warn!(%error, "could not record D4 CallSite identity migration start");
498-
}
499-
500-
match run_indexing_pipeline_cancellable(conn, project_root, phase, cancel) {
501-
Ok(PipelineOutcome::Completed) => {
502-
let rebuilt_files: usize =
503-
conn.query_row("SELECT COUNT(*) FROM file_index", [], |row| {
504-
row.get::<_, i64>(0)
505-
})? as usize;
506-
if let Err(error) = record_call_site_identity_migration_status(
507-
conn,
508-
"baseline_ready",
509-
None,
510-
Some((
511-
started.elapsed().as_millis().try_into().unwrap_or(i64::MAX),
512-
rebuilt_files.try_into().unwrap_or(i64::MAX),
513-
0,
514-
conn.query_row(
515-
"SELECT generation FROM graph_generation_state WHERE id = 1",
516-
[],
517-
|row| row.get(0),
518-
)
519-
.ok(),
520-
)),
521-
) {
522-
tracing::warn!(%error, "could not record D4 CallSite identity migration completion");
523-
}
524-
Ok(ReindexOutcome::Completed(ReindexSummary {
525-
changed: rebuilt_files,
526-
graph_mode: GraphMode::FullFallback("call_site_identity_v2".to_string()),
527-
..ReindexSummary::default()
528-
}))
529-
}
530-
Ok(PipelineOutcome::Cancelled) => {
531-
if let Err(error) = record_call_site_identity_migration_status(
532-
conn,
533-
"failed",
534-
Some("baseline cancelled"),
535-
Some((
536-
started.elapsed().as_millis().try_into().unwrap_or(i64::MAX),
537-
0,
538-
0,
539-
conn.query_row(
540-
"SELECT generation FROM graph_generation_state WHERE id = 1",
541-
[],
542-
|row| row.get(0),
543-
)
544-
.ok(),
545-
)),
546-
) {
547-
tracing::warn!(%error, "could not record cancelled D4 CallSite identity migration");
548-
}
549-
Ok(ReindexOutcome::Cancelled)
550-
}
551-
Err(error) => {
552-
let failure_reason = error.to_string();
553-
if let Err(status_error) = record_call_site_identity_migration_status(
554-
conn,
555-
"failed",
556-
Some(&failure_reason),
557-
Some((
558-
started.elapsed().as_millis().try_into().unwrap_or(i64::MAX),
559-
0,
560-
0,
561-
conn.query_row(
562-
"SELECT generation FROM graph_generation_state WHERE id = 1",
563-
[],
564-
|row| row.get(0),
565-
)
566-
.ok(),
567-
)),
568-
) {
569-
tracing::warn!(%status_error, "could not record failed D4 CallSite identity migration");
570-
}
571-
Err(error)
572-
}
573-
}
574-
}
406+
// PR#7 slice 9 (final slice): move-only extraction of the D4 CallSite-
407+
// identity migration (detection predicate, diagnostic-status recorder,
408+
// one-time full-baseline reparse) into pipeline/identity_migration.rs
409+
// (issue #67 hotspot split). needs_call_site_identity_baseline/
410+
// rebuild_call_site_identity_baseline are pub(super) there since driver.rs
411+
// -- a sibling of identity_migration.rs, not a descendant -- calls both;
412+
// verified via callers() before the move that real callers are exactly
413+
// driver.rs::reindex_changed_cancellable/reindex_paths (2 sites each).
414+
// record_call_site_identity_migration_status stays plain private (its only
415+
// caller, rebuild_call_site_identity_baseline, moved with it).
416+
//
417+
// This completes pipeline.rs's PR#7 split: only shared struct/type/const
418+
// definitions, the 9 mod + import/re-export blocks, now_secs/
419+
// signature_returns_option_or_result, and the untouched #[cfg(test)] mod
420+
// tests block remain below.
421+
mod identity_migration;
422+
use identity_migration::{needs_call_site_identity_baseline, rebuild_call_site_identity_baseline};
575423

576424
#[cfg(test)]
577425
mod tests {

0 commit comments

Comments
 (0)