From 50676702940618f19aa0b2511a42375958784ac7 Mon Sep 17 00:00:00 2001 From: Mikhail Chusavitin Date: Wed, 1 Jul 2026 12:02:08 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20SQLITE=5FBUSY=20=D0=BF=D1=80=D0=B8=20?= =?UTF-8?q?=D0=BA=D0=BB=D0=BE=D0=BD=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B8=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D1=83=D1=80?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B2=D0=B0=D1=80=D0=B8=D0=B0=D0=BD?= =?UTF-8?q?=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SetMaxOpenConns(1) сериализует запись через единственное соединение, busy_timeout=5000 добавляет ожидание до 5с при внешних блокировках. Co-Authored-By: Claude Sonnet 4.6 --- internal/localdb/localdb.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/internal/localdb/localdb.go b/internal/localdb/localdb.go index 0b47503..112c6a6 100644 --- a/internal/localdb/localdb.go +++ b/internal/localdb/localdb.go @@ -114,6 +114,13 @@ func New(dbPath string) (*LocalDB, error) { return nil, fmt.Errorf("opening sqlite database: %w", err) } + // SQLite requires a single writer connection to avoid SQLITE_BUSY under concurrent requests. + sqlDB, err := db.DB() + if err != nil { + return nil, fmt.Errorf("get sql.DB from gorm: %w", err) + } + sqlDB.SetMaxOpenConns(1) + // Enable WAL mode so background sync writes never block UI reads. if err := db.Exec("PRAGMA journal_mode=WAL").Error; err != nil { slog.Warn("failed to enable WAL mode", "error", err) @@ -121,6 +128,10 @@ func New(dbPath string) (*LocalDB, error) { if err := db.Exec("PRAGMA synchronous=NORMAL").Error; err != nil { slog.Warn("failed to set synchronous=NORMAL", "error", err) } + // Wait up to 5 s before returning SQLITE_BUSY (guards against WAL checkpoints and external locks). + if err := db.Exec("PRAGMA busy_timeout = 5000").Error; err != nil { + slog.Warn("failed to set busy_timeout", "error", err) + } if err := ensureLocalProjectsTable(db); err != nil { return nil, fmt.Errorf("ensure local_projects table: %w", err)