fix(ingestion): label upsert reliability, init idempotency, and sync health

Label upsert (issues + merge_requests): Replace INSERT ... ON CONFLICT DO
UPDATE RETURNING with INSERT OR IGNORE + SELECT. The prior RETURNING-based
approach relied on last_insert_rowid() matching the returned id, which is
not guaranteed when ON CONFLICT triggers an update (SQLite may return 0).
The new two-step approach is unambiguous and correctly tracks created_count.

Init: Add ON CONFLICT(gitlab_project_id) DO UPDATE to the project insert
so re-running `lore init` updates path/branch/url instead of failing with
a unique constraint violation.

MR discussions sync: Reset discussions_sync_attempts to 0 when clearing a
sync health error, so previously-failed MRs get a fresh retry budget after
successful sync.

Count: format_number now handles negative numbers correctly by extracting
the sign before inserting thousand-separators.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Taylor Eernisse
2026-02-09 10:15:53 -05:00
parent 53ef21d653
commit dfa44e5bcd
5 changed files with 34 additions and 17 deletions

View File

@@ -299,18 +299,21 @@ fn upsert_label_tx(
name: &str,
created_count: &mut usize,
) -> Result<i64> {
tx.execute(
"INSERT OR IGNORE INTO labels (project_id, name) VALUES (?1, ?2)",
(project_id, name),
)?;
if tx.changes() > 0 {
*created_count += 1;
}
let id: i64 = tx.query_row(
"INSERT INTO labels (project_id, name) VALUES (?1, ?2)
ON CONFLICT(project_id, name) DO UPDATE SET name = excluded.name
RETURNING id",
"SELECT id FROM labels WHERE project_id = ?1 AND name = ?2",
(project_id, name),
|row| row.get(0),
)?;
if tx.last_insert_rowid() == id {
*created_count += 1;
}
Ok(id)
}

View File

@@ -295,18 +295,21 @@ fn upsert_label_tx(
name: &str,
created_count: &mut usize,
) -> Result<i64> {
tx.execute(
"INSERT OR IGNORE INTO labels (project_id, name) VALUES (?1, ?2)",
(project_id, name),
)?;
if tx.changes() > 0 {
*created_count += 1;
}
let id: i64 = tx.query_row(
"INSERT INTO labels (project_id, name) VALUES (?1, ?2)
ON CONFLICT(project_id, name) DO UPDATE SET name = excluded.name
RETURNING id",
"SELECT id FROM labels WHERE project_id = ?1 AND name = ?2",
(project_id, name),
|row| row.get(0),
)?;
if tx.last_insert_rowid() == id {
*created_count += 1;
}
Ok(id)
}

View File

@@ -593,6 +593,7 @@ fn clear_sync_health_error(conn: &Connection, local_mr_id: i64) -> Result<()> {
conn.execute(
"UPDATE merge_requests SET
discussions_sync_last_attempt_at = ?,
discussions_sync_attempts = 0,
discussions_sync_last_error = NULL
WHERE id = ?",
params![now_ms(), local_mr_id],