fix: stop swallowing DB errors across the entire DAO layer

Every map_err(|_| DbError::new(...)) and map_err(|_| anyhow!("..."))
in the database layer was discarding the actual Diesel/SQLite error,
making failures impossible to diagnose from logs.

- Add DbError::log() that logs the source error before converting
- Replace all ~130 swallowed outer map_err closures with DbError::log
- Replace all ~47 swallowed inner anyhow closures to include the
  source error in the message

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cameron Cordes
2026-05-27 13:56:48 -04:00
parent 39ad83f55b
commit dad0220587
10 changed files with 174 additions and 169 deletions
+7 -7
View File
@@ -274,7 +274,7 @@ impl CalendarEventDao for SqliteCalendarEventDao {
source_file: event.source_file, source_file: event.source_file,
}) })
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
fn store_events_batch( fn store_events_batch(
@@ -348,7 +348,7 @@ impl CalendarEventDao for SqliteCalendarEventDao {
Ok(inserted) Ok(inserted)
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
fn find_events_in_range( fn find_events_in_range(
@@ -373,7 +373,7 @@ impl CalendarEventDao for SqliteCalendarEventDao {
.map(|rows| rows.into_iter().map(|r| r.to_calendar_event()).collect()) .map(|rows| rows.into_iter().map(|r| r.to_calendar_event()).collect())
.map_err(|e| anyhow::anyhow!("Query error: {:?}", e)) .map_err(|e| anyhow::anyhow!("Query error: {:?}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn find_similar_events( fn find_similar_events(
@@ -429,7 +429,7 @@ impl CalendarEventDao for SqliteCalendarEventDao {
Ok(scored_events.into_iter().take(limit).map(|(_, event)| event).collect()) Ok(scored_events.into_iter().take(limit).map(|(_, event)| event).collect())
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn find_relevant_events_hybrid( fn find_relevant_events_hybrid(
@@ -500,7 +500,7 @@ impl CalendarEventDao for SqliteCalendarEventDao {
Ok(events_in_range.into_iter().take(limit).map(|r| r.to_calendar_event()).collect()) Ok(events_in_range.into_iter().take(limit).map(|r| r.to_calendar_event()).collect())
} }
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn event_exists( fn event_exists(
@@ -528,7 +528,7 @@ impl CalendarEventDao for SqliteCalendarEventDao {
Ok(result.count > 0) Ok(result.count > 0)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_event_count(&mut self, context: &opentelemetry::Context) -> Result<i64, DbError> { fn get_event_count(&mut self, context: &opentelemetry::Context) -> Result<i64, DbError> {
@@ -551,6 +551,6 @@ impl CalendarEventDao for SqliteCalendarEventDao {
Ok(result.count) Ok(result.count)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
} }
+6 -6
View File
@@ -190,7 +190,7 @@ impl DailySummaryDao for SqliteDailySummaryDao {
model_version: summary.model_version, model_version: summary.model_version,
}) })
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
fn find_similar_summaries( fn find_similar_summaries(
@@ -286,7 +286,7 @@ impl DailySummaryDao for SqliteDailySummaryDao {
Ok(top_results) Ok(top_results)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn find_similar_summaries_with_time_weight( fn find_similar_summaries_with_time_weight(
@@ -408,7 +408,7 @@ impl DailySummaryDao for SqliteDailySummaryDao {
Ok(top_results) Ok(top_results)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn summary_exists( fn summary_exists(
@@ -435,7 +435,7 @@ impl DailySummaryDao for SqliteDailySummaryDao {
Ok(count > 0) Ok(count > 0)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_summary_count( fn get_summary_count(
@@ -457,7 +457,7 @@ impl DailySummaryDao for SqliteDailySummaryDao {
.map(|r| r.count) .map(|r| r.count)
.map_err(|e| anyhow::anyhow!("Count query error: {:?}", e)) .map_err(|e| anyhow::anyhow!("Count query error: {:?}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn has_any_summaries(&mut self, context: &opentelemetry::Context) -> Result<bool, DbError> { fn has_any_summaries(&mut self, context: &opentelemetry::Context) -> Result<bool, DbError> {
@@ -481,7 +481,7 @@ impl DailySummaryDao for SqliteDailySummaryDao {
Ok(!rows.is_empty()) Ok(!rows.is_empty())
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
} }
+8 -8
View File
@@ -152,7 +152,7 @@ impl InsightGenerationJobDao for SqliteInsightGenerationJobDao {
.first::<i32>(connection.deref_mut()) .first::<i32>(connection.deref_mut())
.map_err(|e| anyhow::anyhow!("Failed to get job id: {}", e)) .map_err(|e| anyhow::anyhow!("Failed to get job id: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn complete_job( fn complete_job(
@@ -192,7 +192,7 @@ impl InsightGenerationJobDao for SqliteInsightGenerationJobDao {
.map(|_| ()) .map(|_| ())
.map_err(|e| anyhow::anyhow!("Failed to complete job: {}", e)) .map_err(|e| anyhow::anyhow!("Failed to complete job: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn fail_job( fn fail_job(
@@ -231,7 +231,7 @@ impl InsightGenerationJobDao for SqliteInsightGenerationJobDao {
.map(|_| ()) .map(|_| ())
.map_err(|e| anyhow::anyhow!("Failed to fail job: {}", e)) .map_err(|e| anyhow::anyhow!("Failed to fail job: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn cancel_job( fn cancel_job(
@@ -269,7 +269,7 @@ impl InsightGenerationJobDao for SqliteInsightGenerationJobDao {
Ok(rows > 0) Ok(rows > 0)
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn cancel_active_jobs( fn cancel_active_jobs(
@@ -309,7 +309,7 @@ impl InsightGenerationJobDao for SqliteInsightGenerationJobDao {
Ok(rows) Ok(rows)
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn get_active_job( fn get_active_job(
@@ -338,7 +338,7 @@ impl InsightGenerationJobDao for SqliteInsightGenerationJobDao {
.optional() .optional()
.map_err(|e| anyhow::anyhow!("Failed to get active job: {}", e)) .map_err(|e| anyhow::anyhow!("Failed to get active job: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_job_by_id( fn get_job_by_id(
@@ -360,7 +360,7 @@ impl InsightGenerationJobDao for SqliteInsightGenerationJobDao {
.optional() .optional()
.map_err(|e| anyhow::anyhow!("Failed to get job: {}", e)) .map_err(|e| anyhow::anyhow!("Failed to get job: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn recover_orphaned_jobs( fn recover_orphaned_jobs(
@@ -394,7 +394,7 @@ impl InsightGenerationJobDao for SqliteInsightGenerationJobDao {
Ok(rows) Ok(rows)
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
} }
+20 -20
View File
@@ -198,9 +198,9 @@ impl InsightDao for SqliteInsightDao {
.filter(is_current.eq(true)) .filter(is_current.eq(true))
.first::<PhotoInsight>(connection.deref_mut()) .first::<PhotoInsight>(connection.deref_mut())
.optional() .optional()
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_current_insight_for_library( fn get_current_insight_for_library(
@@ -224,10 +224,10 @@ impl InsightDao for SqliteInsightDao {
.filter(is_current.eq(true)) .filter(is_current.eq(true))
.first::<PhotoInsight>(connection.deref_mut()) .first::<PhotoInsight>(connection.deref_mut())
.optional() .optional()
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}, },
) )
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_insight_for_paths( fn get_insight_for_paths(
@@ -249,9 +249,9 @@ impl InsightDao for SqliteInsightDao {
.order(generated_at.desc()) .order(generated_at.desc())
.first::<PhotoInsight>(connection.deref_mut()) .first::<PhotoInsight>(connection.deref_mut())
.optional() .optional()
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_insight_history( fn get_insight_history(
@@ -268,9 +268,9 @@ impl InsightDao for SqliteInsightDao {
.filter(rel_path.eq(path)) .filter(rel_path.eq(path))
.order(generated_at.desc()) .order(generated_at.desc())
.load::<PhotoInsight>(connection.deref_mut()) .load::<PhotoInsight>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_insight_by_id( fn get_insight_by_id(
@@ -287,9 +287,9 @@ impl InsightDao for SqliteInsightDao {
.find(insight_id) .find(insight_id)
.first::<PhotoInsight>(connection.deref_mut()) .first::<PhotoInsight>(connection.deref_mut())
.optional() .optional()
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn delete_insight( fn delete_insight(
@@ -305,9 +305,9 @@ impl InsightDao for SqliteInsightDao {
diesel::delete(photo_insights.filter(rel_path.eq(path))) diesel::delete(photo_insights.filter(rel_path.eq(path)))
.execute(connection.deref_mut()) .execute(connection.deref_mut())
.map(|_| ()) .map(|_| ())
.map_err(|_| anyhow::anyhow!("Delete error")) .map_err(|e| anyhow::anyhow!("Delete error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_all_insights( fn get_all_insights(
@@ -323,9 +323,9 @@ impl InsightDao for SqliteInsightDao {
.filter(is_current.eq(true)) .filter(is_current.eq(true))
.order(generated_at.desc()) .order(generated_at.desc())
.load::<PhotoInsight>(connection.deref_mut()) .load::<PhotoInsight>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn rate_insight( fn rate_insight(
@@ -347,9 +347,9 @@ impl InsightDao for SqliteInsightDao {
.set(approved.eq(Some(is_approved))) .set(approved.eq(Some(is_approved)))
.execute(connection.deref_mut()) .execute(connection.deref_mut())
.map(|_| ()) .map(|_| ())
.map_err(|_| anyhow::anyhow!("Update error")) .map_err(|e| anyhow::anyhow!("Update error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn get_approved_insights( fn get_approved_insights(
@@ -366,9 +366,9 @@ impl InsightDao for SqliteInsightDao {
.filter(training_messages.is_not_null()) .filter(training_messages.is_not_null())
.order(generated_at.desc()) .order(generated_at.desc())
.load::<PhotoInsight>(connection.deref_mut()) .load::<PhotoInsight>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn update_training_messages( fn update_training_messages(
@@ -391,8 +391,8 @@ impl InsightDao for SqliteInsightDao {
) )
.set(training_messages.eq(Some(training_messages_json.to_string()))) .set(training_messages.eq(Some(training_messages_json.to_string())))
.execute(connection.deref_mut()) .execute(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Update error")) .map_err(|e| anyhow::anyhow!("Update error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
} }
+24 -24
View File
@@ -582,7 +582,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
} }
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
fn get_entity_by_id( fn get_entity_by_id(
@@ -599,7 +599,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
.optional() .optional()
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_entity_by_name( fn get_entity_by_name(
@@ -624,7 +624,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
.load::<Entity>(conn.deref_mut()) .load::<Entity>(conn.deref_mut())
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_entities_with_embeddings( fn get_entities_with_embeddings(
@@ -649,7 +649,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
.load::<Entity>(conn.deref_mut()) .load::<Entity>(conn.deref_mut())
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn list_entities( fn list_entities(
@@ -706,7 +706,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
Ok((results, total)) Ok((results, total))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn list_entities_with_fact_counts( fn list_entities_with_fact_counts(
@@ -894,7 +894,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
Ok((pairs, total)) Ok((pairs, total))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_predicate_stats( fn get_predicate_stats(
@@ -957,7 +957,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
.map_err(|e| anyhow::anyhow!("Query error: {}", e))?; .map_err(|e| anyhow::anyhow!("Query error: {}", e))?;
Ok(rows.into_iter().map(|r| (r.predicate, r.cnt)).collect()) Ok(rows.into_iter().map(|r| (r.predicate, r.cnt)).collect())
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn bulk_reject_facts_by_predicate( fn bulk_reject_facts_by_predicate(
@@ -1016,7 +1016,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
}; };
Ok(touched) Ok(touched)
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn build_entity_graph( fn build_entity_graph(
@@ -1194,7 +1194,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
Ok(EntityGraph { nodes, edges }) Ok(EntityGraph { nodes, edges })
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn find_consolidation_proposals( fn find_consolidation_proposals(
@@ -1349,7 +1349,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
result.truncate(max_groups); result.truncate(max_groups);
Ok(result) Ok(result)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_persona_breakdowns_for_entities( fn get_persona_breakdowns_for_entities(
@@ -1411,7 +1411,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
} }
Ok(out) Ok(out)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn update_entity_status( fn update_entity_status(
@@ -1429,7 +1429,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
.map(|_| ()) .map(|_| ())
.map_err(|e| anyhow::anyhow!("Update error: {}", e)) .map_err(|e| anyhow::anyhow!("Update error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn update_entity( fn update_entity(
@@ -1475,7 +1475,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
.optional() .optional()
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn delete_entity( fn delete_entity(
@@ -1565,7 +1565,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
}) })
.map_err(|e| anyhow::anyhow!("Merge transaction error: {}", e)) .map_err(|e| anyhow::anyhow!("Merge transaction error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -1636,7 +1636,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
Ok((inserted, true)) // true = newly created Ok((inserted, true)) // true = newly created
} }
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
fn get_facts_for_entity( fn get_facts_for_entity(
@@ -1662,7 +1662,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
q.load::<EntityFact>(conn.deref_mut()) q.load::<EntityFact>(conn.deref_mut())
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn list_facts( fn list_facts(
@@ -1719,7 +1719,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
Ok((results, total)) Ok((results, total))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn update_fact( fn update_fact(
@@ -1801,7 +1801,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
.optional() .optional()
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn update_facts_insight_id( fn update_facts_insight_id(
@@ -1823,7 +1823,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
.map(|_| ()) .map(|_| ())
.map_err(|e| anyhow::anyhow!("Update error: {}", e)) .map_err(|e| anyhow::anyhow!("Update error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn delete_fact(&mut self, cx: &opentelemetry::Context, fact_id: i32) -> Result<(), DbError> { fn delete_fact(&mut self, cx: &opentelemetry::Context, fact_id: i32) -> Result<(), DbError> {
@@ -2015,7 +2015,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
.map(|_| ()) .map(|_| ())
.map_err(|e| anyhow::anyhow!("Insert error: {}", e)) .map_err(|e| anyhow::anyhow!("Insert error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
fn delete_photo_links_for_file( fn delete_photo_links_for_file(
@@ -2031,7 +2031,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
.map(|_| ()) .map(|_| ())
.map_err(|e| anyhow::anyhow!("Delete error: {}", e)) .map_err(|e| anyhow::anyhow!("Delete error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_links_for_photo( fn get_links_for_photo(
@@ -2047,7 +2047,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
.load::<EntityPhotoLink>(conn.deref_mut()) .load::<EntityPhotoLink>(conn.deref_mut())
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_links_for_entity( fn get_links_for_entity(
@@ -2063,7 +2063,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
.load::<EntityPhotoLink>(conn.deref_mut()) .load::<EntityPhotoLink>(conn.deref_mut())
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -2111,7 +2111,7 @@ impl KnowledgeDao for SqliteKnowledgeDao {
facts: recent_facts, facts: recent_facts,
}) })
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
} }
+7 -7
View File
@@ -273,7 +273,7 @@ impl LocationHistoryDao for SqliteLocationHistoryDao {
source_file: location.source_file, source_file: location.source_file,
}) })
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
fn store_locations_batch( fn store_locations_batch(
@@ -350,7 +350,7 @@ impl LocationHistoryDao for SqliteLocationHistoryDao {
Ok(inserted) Ok(inserted)
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
fn find_nearest_location( fn find_nearest_location(
@@ -385,7 +385,7 @@ impl LocationHistoryDao for SqliteLocationHistoryDao {
Ok(results.into_iter().next().map(|r| r.to_location_record())) Ok(results.into_iter().next().map(|r| r.to_location_record()))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn find_locations_in_range( fn find_locations_in_range(
@@ -413,7 +413,7 @@ impl LocationHistoryDao for SqliteLocationHistoryDao {
.map(|rows| rows.into_iter().map(|r| r.to_location_record()).collect()) .map(|rows| rows.into_iter().map(|r| r.to_location_record()).collect())
.map_err(|e| anyhow::anyhow!("Query error: {:?}", e)) .map_err(|e| anyhow::anyhow!("Query error: {:?}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn find_locations_near_point( fn find_locations_near_point(
@@ -468,7 +468,7 @@ impl LocationHistoryDao for SqliteLocationHistoryDao {
Ok(filtered) Ok(filtered)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn location_exists( fn location_exists(
@@ -502,7 +502,7 @@ impl LocationHistoryDao for SqliteLocationHistoryDao {
Ok(result.count > 0) Ok(result.count > 0)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_location_count(&mut self, context: &opentelemetry::Context) -> Result<i64, DbError> { fn get_location_count(&mut self, context: &opentelemetry::Context) -> Result<i64, DbError> {
@@ -525,6 +525,6 @@ impl LocationHistoryDao for SqliteLocationHistoryDao {
Ok(result.count) Ok(result.count)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
} }
+84 -79
View File
@@ -203,6 +203,11 @@ impl DbError {
DbError { kind } DbError { kind }
} }
fn log(kind: DbErrorKind, source: impl std::fmt::Display) -> Self {
log::error!("DB {:?}: {}", kind, source);
DbError { kind }
}
fn exists() -> Self { fn exists() -> Self {
DbError::new(DbErrorKind::AlreadyExists) DbError::new(DbErrorKind::AlreadyExists)
} }
@@ -262,7 +267,7 @@ impl FavoriteDao for SqliteFavoriteDao {
path: favorite_path, path: favorite_path,
}) })
.execute(connection.deref_mut()) .execute(connection.deref_mut())
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} else { } else {
Err(DbError::exists()) Err(DbError::exists())
} }
@@ -283,7 +288,7 @@ impl FavoriteDao for SqliteFavoriteDao {
favorites favorites
.filter(userid.eq(user_id)) .filter(userid.eq(user_id))
.load::<Favorite>(self.connection.lock().unwrap().deref_mut()) .load::<Favorite>(self.connection.lock().unwrap().deref_mut())
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn update_path(&mut self, old_path: &str, new_path: &str) -> Result<(), DbError> { fn update_path(&mut self, old_path: &str, new_path: &str) -> Result<(), DbError> {
@@ -292,7 +297,7 @@ impl FavoriteDao for SqliteFavoriteDao {
diesel::update(favorites.filter(rel_path.eq(old_path))) diesel::update(favorites.filter(rel_path.eq(old_path)))
.set(rel_path.eq(new_path)) .set(rel_path.eq(new_path))
.execute(self.connection.lock().unwrap().deref_mut()) .execute(self.connection.lock().unwrap().deref_mut())
.map_err(|_| DbError::new(DbErrorKind::UpdateError))?; .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))?;
Ok(()) Ok(())
} }
@@ -303,7 +308,7 @@ impl FavoriteDao for SqliteFavoriteDao {
.select(rel_path) .select(rel_path)
.distinct() .distinct()
.load(self.connection.lock().unwrap().deref_mut()) .load(self.connection.lock().unwrap().deref_mut())
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
} }
@@ -923,7 +928,7 @@ impl ExifDao for SqliteExifDao {
.first::<ImageExif>(connection.deref_mut()) .first::<ImageExif>(connection.deref_mut())
.map_err(|e| anyhow::anyhow!("Post-insert lookup failed: {}", e)) .map_err(|e| anyhow::anyhow!("Post-insert lookup failed: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
fn get_exif( fn get_exif(
@@ -950,7 +955,7 @@ impl ExifDao for SqliteExifDao {
Err(_) => Err(anyhow::anyhow!("Query error")), Err(_) => Err(anyhow::anyhow!("Query error")),
} }
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn update_exif( fn update_exif(
@@ -987,15 +992,15 @@ impl ExifDao for SqliteExifDao {
last_modified.eq(&exif_data.last_modified), last_modified.eq(&exif_data.last_modified),
)) ))
.execute(connection.deref_mut()) .execute(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Update error"))?; .map_err(|e| anyhow::anyhow!("Update error: {}", e))?;
image_exif image_exif
.filter(library_id.eq(exif_data.library_id)) .filter(library_id.eq(exif_data.library_id))
.filter(rel_path.eq(&exif_data.file_path)) .filter(rel_path.eq(&exif_data.file_path))
.first::<ImageExif>(connection.deref_mut()) .first::<ImageExif>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn delete_exif(&mut self, context: &opentelemetry::Context, path: &str) -> Result<(), DbError> { fn delete_exif(&mut self, context: &opentelemetry::Context, path: &str) -> Result<(), DbError> {
@@ -1005,9 +1010,9 @@ impl ExifDao for SqliteExifDao {
diesel::delete(image_exif.filter(rel_path.eq(path))) diesel::delete(image_exif.filter(rel_path.eq(path)))
.execute(self.connection.lock().unwrap().deref_mut()) .execute(self.connection.lock().unwrap().deref_mut())
.map(|_| ()) .map(|_| ())
.map_err(|_| anyhow::anyhow!("Delete error")) .map_err(|e| anyhow::anyhow!("Delete error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_all_with_date_taken( fn get_all_with_date_taken(
@@ -1038,9 +1043,9 @@ impl ExifDao for SqliteExifDao {
.filter_map(|(path, dt)| dt.map(|ts| (path, ts))) .filter_map(|(path, dt)| dt.map(|ts| (path, ts)))
.collect() .collect()
}) })
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_exif_batch( fn get_exif_batch(
@@ -1064,9 +1069,9 @@ impl ExifDao for SqliteExifDao {
query query
.filter(rel_path.eq_any(file_paths)) .filter(rel_path.eq_any(file_paths))
.load::<ImageExif>(connection.deref_mut()) .load::<ImageExif>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn query_by_exif( fn query_by_exif(
@@ -1125,9 +1130,9 @@ impl ExifDao for SqliteExifDao {
query query
.load::<ImageExif>(connection.deref_mut()) .load::<ImageExif>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_camera_makes( fn get_camera_makes(
@@ -1152,9 +1157,9 @@ impl ExifDao for SqliteExifDao {
.filter_map(|(make, cnt)| make.map(|m| (m, cnt))) .filter_map(|(make, cnt)| make.map(|m| (m, cnt)))
.collect() .collect()
}) })
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn update_file_path( fn update_file_path(
@@ -1171,10 +1176,10 @@ impl ExifDao for SqliteExifDao {
diesel::update(image_exif.filter(rel_path.eq(old_path))) diesel::update(image_exif.filter(rel_path.eq(old_path)))
.set(rel_path.eq(new_path)) .set(rel_path.eq(new_path))
.execute(connection.deref_mut()) .execute(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Update error"))?; .map_err(|e| anyhow::anyhow!("Update error: {}", e))?;
Ok(()) Ok(())
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn get_all_file_paths( fn get_all_file_paths(
@@ -1189,9 +1194,9 @@ impl ExifDao for SqliteExifDao {
image_exif image_exif
.select(rel_path) .select(rel_path)
.load(connection.deref_mut()) .load(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_all_with_gps( fn get_all_with_gps(
@@ -1259,7 +1264,7 @@ impl ExifDao for SqliteExifDao {
Ok(filtered) Ok(filtered)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_rows_missing_hash( fn get_rows_missing_hash(
@@ -1278,9 +1283,9 @@ impl ExifDao for SqliteExifDao {
.order(id.asc()) .order(id.asc())
.limit(limit) .limit(limit)
.load::<(i32, String)>(connection.deref_mut()) .load::<(i32, String)>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn backfill_content_hash( fn backfill_content_hash(
@@ -1304,9 +1309,9 @@ impl ExifDao for SqliteExifDao {
.set((content_hash.eq(hash), size_bytes.eq(size_val))) .set((content_hash.eq(hash), size_bytes.eq(size_val)))
.execute(connection.deref_mut()) .execute(connection.deref_mut())
.map(|_| ()) .map(|_| ())
.map_err(|_| anyhow::anyhow!("Update error")) .map_err(|e| anyhow::anyhow!("Update error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn list_distinct_content_hashes( fn list_distinct_content_hashes(
@@ -1324,9 +1329,9 @@ impl ExifDao for SqliteExifDao {
.distinct() .distinct()
.load::<Option<String>>(connection.deref_mut()) .load::<Option<String>>(connection.deref_mut())
.map(|rows| rows.into_iter().flatten().collect()) .map(|rows| rows.into_iter().flatten().collect())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn list_paths_and_hashes_for_library( fn list_paths_and_hashes_for_library(
@@ -1347,10 +1352,10 @@ impl ExifDao for SqliteExifDao {
.filter(library_id.eq(lib_id)) .filter(library_id.eq(lib_id))
.select((rel_path, content_hash)) .select((rel_path, content_hash))
.load::<(String, Option<String>)>(connection.deref_mut()) .load::<(String, Option<String>)>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}, },
) )
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_rows_needing_date_backfill( fn get_rows_needing_date_backfill(
@@ -1377,10 +1382,10 @@ impl ExifDao for SqliteExifDao {
.order(id.asc()) .order(id.asc())
.limit(limit) .limit(limit)
.load::<(i32, String)>(connection.deref_mut()) .load::<(i32, String)>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}, },
) )
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn backfill_date_taken( fn backfill_date_taken(
@@ -1471,10 +1476,10 @@ impl ExifDao for SqliteExifDao {
.order(id.asc()) .order(id.asc())
.limit(limit) .limit(limit)
.load::<(String, String)>(connection.deref_mut()) .load::<(String, String)>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}, },
) )
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn backfill_clip_embedding( fn backfill_clip_embedding(
@@ -1567,7 +1572,7 @@ impl ExifDao for SqliteExifDao {
)) ))
.order(id.asc()) .order(id.asc())
.load::<(String, Vec<u8>)>(connection.deref_mut()) .load::<(String, Vec<u8>)>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error"))?; .map_err(|e| anyhow::anyhow!("Query error: {}", e))?;
// Dedupe by hash, keeping the first occurrence. Cheap; sized // Dedupe by hash, keeping the first occurrence. Cheap; sized
// to ~14k entries on this library. // to ~14k entries on this library.
@@ -1581,7 +1586,7 @@ impl ExifDao for SqliteExifDao {
} }
Ok(out) Ok(out)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn set_manual_date_taken( fn set_manual_date_taken(
@@ -1741,7 +1746,7 @@ impl ExifDao for SqliteExifDao {
}) })
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn find_by_content_hash( fn find_by_content_hash(
@@ -1758,9 +1763,9 @@ impl ExifDao for SqliteExifDao {
.filter(content_hash.eq(hash)) .filter(content_hash.eq(hash))
.first::<ImageExif>(connection.deref_mut()) .first::<ImageExif>(connection.deref_mut())
.optional() .optional()
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_rel_paths_sharing_content( fn get_rel_paths_sharing_content(
@@ -1783,7 +1788,7 @@ impl ExifDao for SqliteExifDao {
.select(content_hash) .select(content_hash)
.first::<Option<String>>(connection.deref_mut()) .first::<Option<String>>(connection.deref_mut())
.optional() .optional()
.map_err(|_| anyhow::anyhow!("Query error"))? .map_err(|e| anyhow::anyhow!("Query error: {}", e))?
.flatten(); .flatten();
let paths = match hash { let paths = match hash {
@@ -1792,13 +1797,13 @@ impl ExifDao for SqliteExifDao {
.select(rel_path) .select(rel_path)
.distinct() .distinct()
.load::<String>(connection.deref_mut()) .load::<String>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error"))?, .map_err(|e| anyhow::anyhow!("Query error: {}", e))?,
None => vec![rel_path_val.to_string()], None => vec![rel_path_val.to_string()],
}; };
Ok(paths) Ok(paths)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_rel_paths_for_library( fn get_rel_paths_for_library(
@@ -1815,9 +1820,9 @@ impl ExifDao for SqliteExifDao {
.filter(library_id.eq(library_id_val)) .filter(library_id.eq(library_id_val))
.select(rel_path) .select(rel_path)
.load::<String>(connection.deref_mut()) .load::<String>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn find_content_hash_anywhere( fn find_content_hash_anywhere(
@@ -1837,9 +1842,9 @@ impl ExifDao for SqliteExifDao {
.first::<Option<String>>(connection.deref_mut()) .first::<Option<String>>(connection.deref_mut())
.optional() .optional()
.map(|opt| opt.flatten()) .map(|opt| opt.flatten())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_rel_paths_by_hash( fn get_rel_paths_by_hash(
@@ -1857,9 +1862,9 @@ impl ExifDao for SqliteExifDao {
.select(rel_path) .select(rel_path)
.distinct() .distinct()
.load::<String>(connection.deref_mut()) .load::<String>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_rel_paths_for_hashes( fn get_rel_paths_for_hashes(
@@ -1886,14 +1891,14 @@ impl ExifDao for SqliteExifDao {
.select((content_hash.assume_not_null(), rel_path)) .select((content_hash.assume_not_null(), rel_path))
.distinct() .distinct()
.load::<(String, String)>(connection.deref_mut()) .load::<(String, String)>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error"))?; .map_err(|e| anyhow::anyhow!("Query error: {}", e))?;
for (hash, path) in rows { for (hash, path) in rows {
out.entry(hash).or_default().push(path); out.entry(hash).or_default().push(path);
} }
} }
Ok(out) Ok(out)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn list_rel_paths_for_libraries( fn list_rel_paths_for_libraries(
@@ -1959,9 +1964,9 @@ impl ExifDao for SqliteExifDao {
query query
.load::<(i32, String)>(connection.deref_mut()) .load::<(i32, String)>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn delete_exif_by_library( fn delete_exif_by_library(
@@ -1980,9 +1985,9 @@ impl ExifDao for SqliteExifDao {
) )
.execute(self.connection.lock().unwrap().deref_mut()) .execute(self.connection.lock().unwrap().deref_mut())
.map(|_| ()) .map(|_| ())
.map_err(|_| anyhow::anyhow!("Delete error")) .map_err(|e| anyhow::anyhow!("Delete error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn count_for_library( fn count_for_library(
@@ -1997,9 +2002,9 @@ impl ExifDao for SqliteExifDao {
.filter(library_id.eq(library_id_val)) .filter(library_id.eq(library_id_val))
.count() .count()
.get_result::<i64>(self.connection.lock().unwrap().deref_mut()) .get_result::<i64>(self.connection.lock().unwrap().deref_mut())
.map_err(|_| anyhow::anyhow!("Count error")) .map_err(|e| anyhow::anyhow!("Count error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn list_rel_paths_for_library_page( fn list_rel_paths_for_library_page(
@@ -2023,10 +2028,10 @@ impl ExifDao for SqliteExifDao {
.limit(limit) .limit(limit)
.offset(offset) .offset(offset)
.load::<(i32, String)>(self.connection.lock().unwrap().deref_mut()) .load::<(i32, String)>(self.connection.lock().unwrap().deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}, },
) )
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_rows_missing_perceptual_hash( fn get_rows_missing_perceptual_hash(
@@ -2071,10 +2076,10 @@ impl ExifDao for SqliteExifDao {
.order(id.asc()) .order(id.asc())
.limit(limit) .limit(limit)
.load::<(i32, String)>(connection.deref_mut()) .load::<(i32, String)>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}, },
) )
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn backfill_perceptual_hash( fn backfill_perceptual_hash(
@@ -2098,9 +2103,9 @@ impl ExifDao for SqliteExifDao {
.set((phash_64.eq(phash_val), dhash_64.eq(dhash_val))) .set((phash_64.eq(phash_val), dhash_64.eq(dhash_val)))
.execute(connection.deref_mut()) .execute(connection.deref_mut())
.map(|_| ()) .map(|_| ())
.map_err(|_| anyhow::anyhow!("Update error")) .map_err(|e| anyhow::anyhow!("Update error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
@@ -2130,7 +2135,7 @@ impl ExifDao for SqliteExifDao {
q = q.filter(library_id.eq(lib)); q = q.filter(library_id.eq(lib));
} }
q.load::<String>(connection.deref_mut()) q.load::<String>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error"))? .map_err(|e| anyhow::anyhow!("Query error: {}", e))?
}; };
if dup_hashes.is_empty() { if dup_hashes.is_empty() {
@@ -2177,7 +2182,7 @@ impl ExifDao for SqliteExifDao {
Option<i64>, Option<i64>,
)> = q )> = q
.load(connection.deref_mut()) .load(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error"))?; .map_err(|e| anyhow::anyhow!("Query error: {}", e))?;
Ok(rows Ok(rows
.into_iter() .into_iter()
@@ -2196,7 +2201,7 @@ impl ExifDao for SqliteExifDao {
}) })
.collect()) .collect())
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
@@ -2259,7 +2264,7 @@ impl ExifDao for SqliteExifDao {
Option<i64>, Option<i64>,
)> = q )> = q
.load(connection.deref_mut()) .load(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error"))?; .map_err(|e| anyhow::anyhow!("Query error: {}", e))?;
// Dedup keyed on content_hash, keeping the first occurrence // Dedup keyed on content_hash, keeping the first occurrence
// (deterministic by the SQL ORDER BY: lowest library_id, // (deterministic by the SQL ORDER BY: lowest library_id,
@@ -2285,7 +2290,7 @@ impl ExifDao for SqliteExifDao {
} }
Ok(out) Ok(out)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn list_image_paths( fn list_image_paths(
@@ -2310,9 +2315,9 @@ impl ExifDao for SqliteExifDao {
q = q.filter(duplicate_of_hash.is_null()); q = q.filter(duplicate_of_hash.is_null());
} }
q.load::<(i32, String)>(connection.deref_mut()) q.load::<(i32, String)>(connection.deref_mut())
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn lookup_duplicate_row( fn lookup_duplicate_row(
@@ -2372,9 +2377,9 @@ impl ExifDao for SqliteExifDao {
duplicate_decided_at: r.10, duplicate_decided_at: r.10,
}) })
}) })
.map_err(|_| anyhow::anyhow!("Query error")) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn set_duplicate_of( fn set_duplicate_of(
@@ -2401,9 +2406,9 @@ impl ExifDao for SqliteExifDao {
)) ))
.execute(connection.deref_mut()) .execute(connection.deref_mut())
.map(|_| ()) .map(|_| ())
.map_err(|_| anyhow::anyhow!("Update error")) .map_err(|e| anyhow::anyhow!("Update error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn clear_duplicate_of( fn clear_duplicate_of(
@@ -2428,9 +2433,9 @@ impl ExifDao for SqliteExifDao {
)) ))
.execute(connection.deref_mut()) .execute(connection.deref_mut())
.map(|_| ()) .map(|_| ())
.map_err(|_| anyhow::anyhow!("Update error")) .map_err(|e| anyhow::anyhow!("Update error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn union_perceptual_tags( fn union_perceptual_tags(
@@ -2468,9 +2473,9 @@ impl ExifDao for SqliteExifDao {
.bind::<diesel::sql_types::Text, _>(survivor_hash) .bind::<diesel::sql_types::Text, _>(survivor_hash)
.execute(connection.deref_mut()) .execute(connection.deref_mut())
.map(|_| ()) .map(|_| ())
.map_err(|_| anyhow::anyhow!("Tag union error")) .map_err(|e| anyhow::anyhow!("Tag union error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
} }
+6 -6
View File
@@ -119,7 +119,7 @@ impl PersonaDao for SqlitePersonaDao {
.load::<Persona>(conn.deref_mut()) .load::<Persona>(conn.deref_mut())
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_persona( fn get_persona(
@@ -138,7 +138,7 @@ impl PersonaDao for SqlitePersonaDao {
.optional() .optional()
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn create_persona( fn create_persona(
@@ -178,7 +178,7 @@ impl PersonaDao for SqlitePersonaDao {
.first::<Persona>(conn.deref_mut()) .first::<Persona>(conn.deref_mut())
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
fn update_persona( fn update_persona(
@@ -241,7 +241,7 @@ impl PersonaDao for SqlitePersonaDao {
.optional() .optional()
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn delete_persona( fn delete_persona(
@@ -258,7 +258,7 @@ impl PersonaDao for SqlitePersonaDao {
.map_err(|e| anyhow::anyhow!("Delete error: {}", e))?; .map_err(|e| anyhow::anyhow!("Delete error: {}", e))?;
Ok(n > 0) Ok(n > 0)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn bulk_import( fn bulk_import(
@@ -294,7 +294,7 @@ impl PersonaDao for SqlitePersonaDao {
} }
Ok(inserted) Ok(inserted)
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
} }
+5 -5
View File
@@ -96,7 +96,7 @@ impl PreviewDao for SqlitePreviewDao {
.map(|_| ()) .map(|_| ())
.map_err(|e| anyhow::anyhow!("Insert error: {}", e)) .map_err(|e| anyhow::anyhow!("Insert error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
fn update_status( fn update_status(
@@ -126,7 +126,7 @@ impl PreviewDao for SqlitePreviewDao {
.map(|_| ()) .map(|_| ())
.map_err(|e| anyhow::anyhow!("Update error: {}", e)) .map_err(|e| anyhow::anyhow!("Update error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::UpdateError)) .map_err(|e| DbError::log(DbErrorKind::UpdateError, e))
} }
fn get_preview( fn get_preview(
@@ -148,7 +148,7 @@ impl PreviewDao for SqlitePreviewDao {
Err(e) => Err(anyhow::anyhow!("Query error: {}", e)), Err(e) => Err(anyhow::anyhow!("Query error: {}", e)),
} }
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_previews_batch( fn get_previews_batch(
@@ -170,7 +170,7 @@ impl PreviewDao for SqlitePreviewDao {
.load::<VideoPreviewClip>(connection.deref_mut()) .load::<VideoPreviewClip>(connection.deref_mut())
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_by_status( fn get_by_status(
@@ -188,7 +188,7 @@ impl PreviewDao for SqlitePreviewDao {
.load::<VideoPreviewClip>(connection.deref_mut()) .load::<VideoPreviewClip>(connection.deref_mut())
.map_err(|e| anyhow::anyhow!("Query error: {}", e)) .map_err(|e| anyhow::anyhow!("Query error: {}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
} }
+7 -7
View File
@@ -227,7 +227,7 @@ impl SearchHistoryDao for SqliteSearchHistoryDao {
source_file: search.source_file, source_file: search.source_file,
}) })
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
fn store_searches_batch( fn store_searches_batch(
@@ -283,7 +283,7 @@ impl SearchHistoryDao for SqliteSearchHistoryDao {
Ok(inserted) Ok(inserted)
}) })
.map_err(|_| DbError::new(DbErrorKind::InsertError)) .map_err(|e| DbError::log(DbErrorKind::InsertError, e))
} }
fn find_searches_in_range( fn find_searches_in_range(
@@ -310,7 +310,7 @@ impl SearchHistoryDao for SqliteSearchHistoryDao {
.map(|rows| rows.into_iter().map(|r| r.to_search_record()).collect()) .map(|rows| rows.into_iter().map(|r| r.to_search_record()).collect())
.map_err(|e| anyhow::anyhow!("Query error: {:?}", e)) .map_err(|e| anyhow::anyhow!("Query error: {:?}", e))
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn find_similar_searches( fn find_similar_searches(
@@ -372,7 +372,7 @@ impl SearchHistoryDao for SqliteSearchHistoryDao {
.map(|(_, search)| search) .map(|(_, search)| search)
.collect()) .collect())
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn find_relevant_searches_hybrid( fn find_relevant_searches_hybrid(
@@ -459,7 +459,7 @@ impl SearchHistoryDao for SqliteSearchHistoryDao {
.collect()) .collect())
} }
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn search_exists( fn search_exists(
@@ -490,7 +490,7 @@ impl SearchHistoryDao for SqliteSearchHistoryDao {
Ok(result.count > 0) Ok(result.count > 0)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
fn get_search_count(&mut self, context: &opentelemetry::Context) -> Result<i64, DbError> { fn get_search_count(&mut self, context: &opentelemetry::Context) -> Result<i64, DbError> {
@@ -513,6 +513,6 @@ impl SearchHistoryDao for SqliteSearchHistoryDao {
Ok(result.count) Ok(result.count)
}) })
.map_err(|_| DbError::new(DbErrorKind::QueryError)) .map_err(|e| DbError::log(DbErrorKind::QueryError, e))
} }
} }