fix(ingest): Reset discussion watermarks when --full flag is used

This is a P1 fix from the CP1-CP2 alignment audit. The --full flag was
designed to enable complete data re-synchronization, but it only reset
sync_cursors for issues—it failed to reset the per-issue
discussions_synced_for_updated_at watermark.

The result was an inconsistent state: issues would be re-fetched from
GitLab (because sync_cursors were cleared), but their discussions would
NOT be re-synced (because the watermark comparison prevented it). This
was a subtle bug because the watermark check uses:

  WHERE updated_at > COALESCE(discussions_synced_for_updated_at, 0)

When discussions_synced_for_updated_at is already set to the issue's
updated_at, the comparison fails and discussions are skipped.

Fix: Before clearing sync_cursors, set discussions_synced_for_updated_at
to NULL for all issues in the project. This makes COALESCE return 0,
ensuring all issues become eligible for discussion sync.

The ordering is important: watermarks must be reset BEFORE cursors to
ensure the full sync behaves consistently.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Taylor Eernisse
2026-01-26 17:01:04 -05:00
parent d9d749ac57
commit 4abbe2a226

View File

@@ -67,18 +67,26 @@ pub async fn run_ingest(
// Get projects to sync
let projects = get_projects_to_sync(&conn, &config.projects, project_filter)?;
// If --full flag is set, reset sync cursors for a complete re-fetch
// If --full flag is set, reset sync cursors and discussion watermarks for a complete re-fetch
if full {
println!(
"{}",
style("Full sync: resetting cursors to fetch all data...").yellow()
);
for (local_project_id, _, path) in &projects {
// Reset discussion watermarks first so discussions get re-synced
conn.execute(
"UPDATE issues SET discussions_synced_for_updated_at = NULL WHERE project_id = ?",
[*local_project_id],
)?;
// Then reset sync cursor
conn.execute(
"DELETE FROM sync_cursors WHERE project_id = ? AND resource_type = ?",
(*local_project_id, resource_type),
)?;
tracing::info!(project = %path, "Reset sync cursor for full re-fetch");
tracing::info!(project = %path, "Reset sync cursor and discussion watermarks for full re-fetch");
}
}