Skip to content

fix(database): set busy_timeout to prevent "database is locked" errors#1777

Merged
piorpua merged 1 commit intomainfrom
fix/sentry-ELECTRON-DD
Mar 29, 2026
Merged

fix(database): set busy_timeout to prevent "database is locked" errors#1777
piorpua merged 1 commit intomainfrom
fix/sentry-ELECTRON-DD

Conversation

@kaizhou-lab
Copy link
Copy Markdown
Collaborator

Summary

  • Add PRAGMA busy_timeout = 5000 in initSchema() to prevent immediate SQLITE_BUSY failures when multiple processes access the database concurrently during startup
  • Add unit tests verifying the pragma is set before any CREATE TABLE statements

Closes #1776
Fixes ELECTRON-DD (22 occurrences, escalating)

Root Cause

initSchema() did not set busy_timeout, so SQLite used the default value of 0 — any lock contention failed immediately. This manifested during app startup when CronService.init() tried to access the database while schema initialization was in progress on another connection.

Test Plan

  • Unit tests verify busy_timeout = 5000 pragma is called
  • Unit tests verify pragma is set before CREATE TABLE statements
  • Unit tests verify WAL failure doesn't prevent initialization
  • bun run test passes
  • bunx tsc --noEmit passes
  • bun run lint:fix — 0 errors
  • bun run format — clean

When multiple processes or startup tasks (e.g. CronService.init) access
the database concurrently, SQLite immediately fails with SQLITE_BUSY
("database is locked") because no busy_timeout is configured.

Add `PRAGMA busy_timeout = 5000` in initSchema so SQLite retries for
up to 5 seconds before giving up, which is the standard mitigation for
transient lock contention in WAL mode.

Fixes ELECTRON-DD
@kaizhou-lab kaizhou-lab marked this pull request as ready for review March 27, 2026 03:45
@piorpua piorpua added the bot:reviewing Review in progress (mutex) label Mar 29, 2026
@piorpua
Copy link
Copy Markdown
Contributor

piorpua commented Mar 29, 2026

Code Review:fix(database): set busy_timeout to prevent "database is locked" errors (#1777)

变更概述

本 PR 在 initSchema() 中新增 PRAGMA busy_timeout = 5000,将 SQLite 默认的立即失败行为改为最多等待 5 秒,修复多进程/多连接并发访问数据库时出现的 "database is locked" 错误(Sentry 事件 ELECTRON-DD,22 次发生)。同时新增 schema.test.ts 单元测试,覆盖该 pragma 的设置时机及 WAL 降级行为。


方案评估

结论:✅ 方案合理

busy_timeout 是 SQLite 针对并发写锁冲突的标准解法,直接对准根因(默认 timeout 为 0)。将其放置在 initSchema() 的最前部、WAL 设置之前,确保所有后续操作都受保护。方案简洁,无过度工程化。


问题清单

未发现需要报告的问题。代码变更最小化(4 行生产代码),lint 零错误,测试覆盖了 pragma 调用存在性、调用时序(busy_timeout 在任何 exec 之前)、WAL 模式启用,以及 WAL 失败时的降级路径,质量良好。


汇总

无问题。

结论

批准合并 — 无阻塞性问题,修复准确,测试充分。


本报告由本地 pr-review skill 生成,包含完整项目上下文,无截断限制。

@piorpua
Copy link
Copy Markdown
Contributor

piorpua commented Mar 29, 2026

✅ 已自动 review,无阻塞性问题,正在触发自动合并。

@piorpua piorpua merged commit d4d17ed into main Mar 29, 2026
17 checks passed
@piorpua piorpua deleted the fix/sentry-ELECTRON-DD branch March 29, 2026 05:10
@piorpua piorpua added bot:done Auto-merged by bot and removed bot:reviewing Review in progress (mutex) labels Mar 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:done Auto-merged by bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(database): "database is locked" error during concurrent startup

2 participants