fix(observability): demote WhatsApp ingest SQLite lock noise #2917
Conversation
Introduced a new error kind for WhatsApp structured-ingest failures caused by transient SQLite file locks. This includes a dedicated matcher to classify these errors and ensures unrelated SQLite lock messages are not misclassified. Added tests to verify correct classification of both expected and unrelated error messages.
📝 WalkthroughWalkthroughThis PR extends the observability classification system to recognize and demote WhatsApp SQLite contention errors as expected transient failures. A new ChangesWhatsApp SQLite Busy Error Classification
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/core/observability.rs (1)
2531-2542: ⚡ Quick winAdd one case per lock indicator to pin classifier boundaries.
Current positives don’t independently assert
database table is lockedand a standaloneerror code 5path. Adding explicit cases will prevent accidental matcher drift.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/core/observability.rs` around lines 2531 - 2542, Add two more positive test inputs inside the test function classifies_whatsapp_data_sqlite_busy_errors so the classifier is pinned to each lock indicator: one raw string that contains the exact phrase "database table is locked" (with surrounding whatsapp_data context like the other cases) and another raw string that contains a standalone "Error code 5" message (again keeping the surrounding log context). Assert both map to Some(ExpectedErrorKind::WhatsAppDataSqliteBusy) using expected_error_kind, mirroring the existing assert_eq pattern so each indicator is independently validated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/core/observability.rs`:
- Around line 186-196: The observability.rs module is getting too large; split
it by extracting the matcher, reporting, and test sections into focused
submodules to keep files under ~500 lines. Create submodules (e.g.,
observability::matcher, observability::reporting, observability::tests) and move
related items—such as the WhatsAppDataSqliteBusy enum variant and its
matcher/reporting logic and any unit tests—into those files, re-exporting public
symbols from observability.rs (pub use crate::observability::matcher::..., pub
use ...::reporting) so existing callers of WhatsAppDataSqliteBusy and associated
functions continue to work. Ensure module declarations (mod matcher; mod
reporting; #[cfg(test)] mod tests;) are added to observability.rs and update use
paths within the moved code.
---
Nitpick comments:
In `@src/core/observability.rs`:
- Around line 2531-2542: Add two more positive test inputs inside the test
function classifies_whatsapp_data_sqlite_busy_errors so the classifier is pinned
to each lock indicator: one raw string that contains the exact phrase "database
table is locked" (with surrounding whatsapp_data context like the other cases)
and another raw string that contains a standalone "Error code 5" message (again
keeping the surrounding log context). Assert both map to
Some(ExpectedErrorKind::WhatsAppDataSqliteBusy) using expected_error_kind,
mirroring the existing assert_eq pattern so each indicator is independently
validated.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9fc2728c-de66-4f6e-a037-cf5d0b0fc0fb
📒 Files selected for processing (1)
src/core/observability.rs
graycyrus
left a comment
There was a problem hiding this comment.
clean observability fix. the double-anchor approach (ingest envelope + upsert operation context) is the right call — narrow enough to avoid demoting unrelated lock failures in other whatsapp_data operations like list_messages.
a few things i checked:
- classifier ordering in
expected_error_kind: the new check sits betweenMemoryStoreBreakerOpenandDiskFull, which is fine since every check is an independent early return with no ordering dependency error code 5as a lock indicator: risk of false positives is real in isolation, but gated behind both envelope and operation anchors so it's safe heretracing::warn!level for the reporting arm is correct — matches the pattern for other expected-error kinds, not silently swallowed- no
.unwrap(), no exposed private fns, no PII in the structured warn log - positive tests cover the canonical case and the rpc-wrapped envelope; negative cases cover other domains, other operations, and a different whatsapp_data op — solid coverage of classifier boundaries
CI 100% green including coverage gate and Rust quality checks. approving.
Summary
Added
ExpectedErrorKind::WhatsAppDataSqliteBusyfor WhatsApp ingest lock-contention errors.Added a narrow classifier that matches only the WhatsApp ingest envelope (
[whatsapp_data] ingest failed+upsert wa_message) with SQLite lock markers.Wired the new error kind into expected-error reporting so this known transient condition is demoted from Sentry error events.
Added unit tests for both positive and negative cases to protect classification boundaries.
Kept behavior unchanged for non-WhatsApp and non-ingest SQLite lock failures to avoid over-demotion.
Problem
Sentry issue TAURI-RUST-BH reports repeated errors from
openhumman.whatsapp_data_ingestwithdatabase is locked/Error code 5.The WhatsApp write path already has retries and busy timeout, but longer-lived external file locks can still exceed retry windows.
These events are expected transient local-contention conditions and currently create alert noise without actionable remediation.
Solution
Added a new expected-error kind specific to WhatsApp ingest SQLite busy/locked failures.
Implemented strict message matching to avoid demoting unrelated lock errors:
Requires WhatsApp ingest failure prefix.
Requires
upsert wa_messagecontext.Requires SQLite lock indicators (
database is locked,database table is locked,database file is locked, orerror code 5).Routed this kind through observability expected-error handling (warn breadcrumb, no Sentry error event).
Added tests covering:
Canonical and wrapped WhatsApp ingest lock messages.
Negative cases from other SQLite lock domains to prevent false positives.
Submission Checklist
If a section does not apply to this change, mark the item as N/A with a one-line reason. Do not delete items.
.github/workflows/coverage.yml. Runpnpm test:coverageandpnpm test:rustlocally; PRs below 80% on changed lines will not merge.docs/TEST-COVERAGE-MATRIX.mdreflect this change (or N/A: behaviour-only change)N/A: behaviour-only observability classification change.
N/A: no feature-row change.
docs/RELEASE-MANUAL-SMOKE.md)N/A: no release-cut UI/runtime surface changes.
N/A: tracked via Sentry issue (no linked GitHub issue in this PR).
Impact
Runtime/platform: Rust core observability path only; impacts desktop telemetry classification.
Performance: negligible string-match checks in error classification path.
Security/privacy: reduces unnecessary Sentry error noise for known local contention cases.
Compatibility: no API/schema/data-model changes; no migration required; no breaking changes expected.
Related
Closes: TAURI-RUST-BH
Summary by CodeRabbit