fix: propagate DB errors instead of silently swallowing them

Replace .unwrap_or(), .ok(), and .filter_map(|r| r.ok()) patterns with
proper error propagation using ? and rusqlite::OptionalExtension where
the query may legitimately return no rows.

Affected areas:
- events_db::count_events: three count queries now propagate errors
  instead of defaulting to (0, 0) on failure
- note_parser::extract_refs_from_system_notes: row iteration errors
  are now propagated instead of silently dropped via filter_map
- note_parser::noteable_type_to_entity_type: unknown types now log a
  debug warning before defaulting to "issue"
- payloads::store_payload/read_payload: use .optional()? instead of
  .ok() to distinguish "no row" from "query failed"
- backoff::compute_next_attempt_at: use .clamp(0, 30) to guard against
  negative attempt_count, not just .min(30)
- search::vector::max_chunks_per_document: returns Result<i64> with
  proper error propagation through .optional()?.flatten()
- embedding::chunk_ids::decode_rowid: promote debug_assert to assert
  since negative rowids indicate data corruption worth failing fast on
- ingestion::dirty_tracker::record_dirty_error: use .optional()? to
  handle missing dirty_sources row gracefully instead of hard error

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Taylor Eernisse
2026-02-09 10:15:36 -05:00
parent 41504b4941
commit 53ef21d653
7 changed files with 51 additions and 43 deletions

View File

@@ -1,6 +1,7 @@
use std::collections::HashMap;
use rusqlite::Connection;
use rusqlite::OptionalExtension;
use crate::core::error::Result;
use crate::embedding::chunk_ids::decode_rowid;
@@ -11,7 +12,7 @@ pub struct VectorResult {
pub distance: f64,
}
fn max_chunks_per_document(conn: &Connection) -> i64 {
fn max_chunks_per_document(conn: &Connection) -> Result<i64> {
let stored: Option<i64> = conn
.query_row(
"SELECT MAX(chunk_count) FROM embedding_metadata
@@ -19,21 +20,24 @@ fn max_chunks_per_document(conn: &Connection) -> i64 {
[],
|row| row.get(0),
)
.unwrap_or(None);
.optional()?
.flatten();
if let Some(max) = stored {
return max;
return Ok(max);
}
conn.query_row(
"SELECT COALESCE(MAX(cnt), 1) FROM (
Ok(conn
.query_row(
"SELECT COALESCE(MAX(cnt), 1) FROM (
SELECT COUNT(*) as cnt FROM embedding_metadata
WHERE last_error IS NULL GROUP BY document_id
)",
[],
|row| row.get(0),
)
.unwrap_or(1)
[],
|row| row.get(0),
)
.optional()?
.unwrap_or(1))
}
pub fn search_vector(
@@ -50,7 +54,7 @@ pub fn search_vector(
.flat_map(|f| f.to_le_bytes())
.collect();
let max_chunks = max_chunks_per_document(conn).max(1);
let max_chunks = max_chunks_per_document(conn)?.max(1);
let multiplier = ((max_chunks.unsigned_abs() as usize * 3 / 2) + 1).clamp(8, 200);
let k = (limit * multiplier).min(10_000);