Skip to content

Handle SQLite concurrency risks with transactions and retries - #10

Merged
bonsai merged 5 commits into
mainfrom
fix/sqlite-concurrency-handling-1981043102179597813
Nov 12, 2026
Merged

bonsai merged 5 commits into
mainfrom
fix/sqlite-concurrency-handling-1981043102179597813

Conversation

@bonsai

@bonsai bonsai commented Nov 11, 2026 •

Copy link
Copy Markdown
Owner

Resolves ISSUE-002 (SQLite Concurrency Risks):

  • Wraps note save operations in rusqlite::Transaction for atomicity.
  • Implements exponential backoff retry helper (retry_on_lock) for SQLite lock and busy contention.
  • Implements DB connection caching and configuration (5000ms busy_timeout and WAL mode pragma) on App.
  • Updates refresh_notes(), open_note_at_index(), and save_note() to use the connection cache and retry helper.
  • Adds comprehensive unit tests covering transaction atomicity, connection reuse, and retry under lock contention.

Fixes #3


PR created automatically by Jules for task 1981043102179597813 started by @bonsai

Summary by Sourcery

Improve SQLite concurrency handling by combining transactional note saves, connection reuse, and retry-based lock recovery.

New Features:

  • Add cached SQLite connections configured with WAL mode and a 5-second busy timeout.
  • Retry lock- and busy-contended SQLite operations with exponential backoff.

Bug Fixes:

  • Make note saves atomic and more resilient to SQLite concurrency contention.
  • Release cached database connections when switching database files.

Enhancements:

  • Route note loading, opening, and saving through the shared configured connection and retry handling.

Tests:

  • Add coverage for transactional note persistence, connection reuse, and lock-contention retries.

Wrap SQLite write operations in explicit transactions to ensure atomicity.
Add exponential backoff retry logic for DatabaseLocked and DatabaseBusy errors.
Introduce connection caching with busy_timeout and WAL mode to mitigate contention during rapid operations.

Co-authored-by: bonsai <24775+bonsai@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@sourcery-ai

sourcery-ai Bot commented Nov 11, 2026

Copy link
Copy Markdown

Sorry @bonsai, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 15 hours and 44 minutes by commenting @sourcery-ai review. Upgrade to get a review now.

@coderabbitai

coderabbitai Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e7f0f3e1-32aa-4979-bb8a-c422e04d4eaf
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

Share

@chatgpt-codex-connector

Copy link
Copy Markdown
Codex Review Summary: ❌ Failed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ❌ Failed 2026-11-11T10:04:34.028450Z
We couldn’t complete this review. Comment @codex review to try again.
c906d34 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@sourcery-ai

sourcery-ai Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Implementation

Cache and configure database connections, retry lock and busy errors with backoff, and use the shared connection for note reads and transactional saves.

  • src/app.rs L11-41, L152-179, L258-289 (+6 small edits)

Tests

Add tests for committed transactional saves, reuse of cached connections, lock-contention retries, and releasing the cached connection before deleting the database.

  • src/app.rs L1216-1219, L1781-1782, L1788-1918

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Wrap SQLite write operations in explicit transactions to ensure atomicity.
Add exponential backoff retry logic for DatabaseLocked and DatabaseBusy errors.
Introduce connection caching with busy_timeout and WAL mode to mitigate contention during rapid operations.

Co-authored-by: bonsai <24775+bonsai@users.noreply.github.com>
…y-handling-1981043102179597813

# Conflicts:
#	src/app.rs
…y-handling-1981043102179597813

# Conflicts:
#	src/app.rs
@sourcery-ai

sourcery-ai Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Linked issues

Checked at commit 6143ac8

#3 ISSUE-002: SQLite Concurrency Risks · 2 of 3 met

# Requirement Status Notes
1 Wrap database writes in a transaction for atomicity ✅ Met save_note() performs the upsert inside a transaction and commits it.
2 Retry lock contention with exponential backoff 🟡 Partly met retry_on_lock retries DatabaseLocked and DatabaseBusy errors with exponential delays in the cached-connection paths, but cmd_db() still loads notes via load_notes() without that helper.
3 Reuse database connections for frequent operations ✅ Met The App caches a connection by database path and reuses it for note refresh, open, and save operations.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New gaps against the linked issues

Comment thread src/app.rs
return Err(format!("db not found: {}", path.display()));
}
// PR #10: DB を差し替える前にキャッシュ接続を破棄する(旧 DB のロック/WAL を解放)。
self.reset_db_connection();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Retry database switching load

The issue asks for retries on SQLite lock contention. The main note operations use retry_on_lock, but switching databases still loads notes through load_notes() without retries, so that entry point can still fail on a lock.

Prompt for AI agents
In `src/app.rs` at line 1093:

**Retry database switching load**

The issue asks for retries on SQLite lock contention. The main note operations use `retry_on_lock`, but switching databases still loads notes through `load_notes()` without retries, so that entry point can still fail on a lock.

From #3:

Retry SQLite lock and busy errors with exponential backoff.

@bonsai
bonsai merged commit 60fd04e into main Nov 12, 2026
5 checks passed
@bonsai
bonsai deleted the fix/sqlite-concurrency-handling-1981043102179597813 branch November 12, 2026 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ISSUE-002: SQLite Concurrency Risks

1 participant