fix(database): reduce write-lane pressure from one-shot reads#6255
fix(database): reduce write-lane pressure from one-shot reads#6255jeremiah-k wants to merge 5 commits into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughDatabaseManager now provides tracked bounded-read access that coordinates database pool switching, eviction, and shutdown. Database-backed data sources use ChangesDatabase read path
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant DataSource
participant DatabaseManager
participant DatabasePool
participant Cleanup
DataSource->>DatabaseManager: withReadDb DAO query
DatabaseManager->>DatabasePool: capture and execute read
Cleanup->>DatabaseManager: request eviction or close
DatabaseManager-->>Cleanup: defer while reader is active
DatabaseManager->>DatabaseManager: endRead
DatabaseManager-->>Cleanup: complete deferred cleanup
Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Nice find on the per-operation One sequencing concern before this merges, though: this PR is only safe on top of #6256, and #6256 is still in draft. The reads moved from
#6256's logical retirement (never physically closing during process lifetime) removes the hazard entirely. Could we either land #6256 first and rebase this on top, or merge them together? If there's a reason to take this one alone, it would at least be worth noting the dependency in the PR body. |
|
@jamesarich Thanks — agreed on the sequencing concern. The direct I’ll return this to draft, update the description to state that dependency, and rebase it onto |
b55219e to
9986b79
Compare
Remove per-operation DataStore writes from DatabaseProvider.withDb. Last-used metadata exists to rank inactive device databases for LRU cleanup; updating it for every DAO callback adds serialized preference I/O to the hottest database path without improving the meaningful recency signal. Record recency when the active database changes or association routing changes instead. This preserves cache-ordering behavior while keeping routine packet, node, and repository work off DataStore's write path.
Introduce DatabaseProvider.withReadDb for bounded one-shot reads. Reads no longer enter the serialized withDb write lane, register with the association writer drain, or update last-used metadata, preserving the separation between coordinated writes, one-shot reads, and reactive Flow/Paging factories. Snapshot the active database synchronously and retry exactly once when the captured Room pool reports a closed-pool failure and the active database has actually changed. Cancellation always propagates, genuine failures are not retried, and a failed retry retains the original closed-pool exception as a suppressed cause for diagnostics. Route device-hardware, device-link, firmware-release, and switching node-info lookups through the helper. Keep the closed-pool classifier and retry control flow small enough for static analysis without changing those semantics. Add focused tests for switch-aware recovery, genuine-failure propagation, and cancellation behavior, and update shared fakes and provider documentation to make the read/write access policy explicit.
9986b79 to
413cedd
Compare
|
Reviewed the evolved read path in depth —
No defects found. Four test gaps worth covering while the machinery is fresh —
None of these block merge for me — happy to see this land after them, or with them as an immediate follow-up. |
|
@jamesarich Agreed—this is a good time to add the coverage while the concurrency behavior is fresh. I’ve added all four cases you identified; they’re now included in the updated branch. |
Overview
This reduces unnecessary database coordination for bounded, one-shot reads without weakening database switching, writer admission, eviction, or shutdown safety.
Routine point queries previously entered the same
DatabaseManager.withDbpath used for coordinated writes. That serialized them through the temporary write-containment lane and refreshed last-used metadata for every operation, even though these reads do not mutate state.This introduces a dedicated bounded-read path while preserving the existing coordination rules for writes, Flow and Paging subscriptions, database switching, association, and lifecycle-sensitive operations.
Builds on: #6256
Related: #6259
Changes
DatabaseProvider.withReadDbfor bounded, non-replaying reads.currentDbso they continue to re-subscribe after a database switch.Validation
Added coverage for:
Hardware validation switched between firmware 2.8 over TCP and firmware 2.7 over BLE in one process. Both configuration downloads completed, and the active database followed the selected device.
Summary by CodeRabbit