Match the self-host open path: a per-connection PRAGMA busy_timeout=5000 gives writers a 5s retry window instead of an instant SQLITE_BUSY when a second OS process transiently holds the write lock (a CLI tool, the v1->v2 migration reader, or a launchd restart racing the old pid).
Unified · Split
| @@ -26,6 +26,13 @@ export const openLocalLibsql = async (path: string): Promise<Client> => { · 25 unmodified lines | |||
| 26 | // first enabling. Re-apply both since libSQL gives no shared handle. | 26 | // first enabling. Re-apply both since libSQL gives no shared handle. |
| 27 | await client.execute("PRAGMA foreign_keys = ON"); | 27 | await client.execute("PRAGMA foreign_keys = ON"); |
| 28 | await client.execute("PRAGMA journal_mode = WAL"); | 28 | await client.execute("PRAGMA journal_mode = WAL"); |
| 29 | // busy_timeout is per-connection (default 0 = fail immediately on a lock). | ||
| 30 | // Under the supervised-daemon model a single process owns this file, but a | ||
| 31 | // second OS process can still transiently hold the write lock (e.g. a CLI | ||
| 32 | // tool, the v1→v2 migration reader, or a launchd restart racing the old | ||
| 33 | // pid). Give writers a 5s retry window instead of an instant SQLITE_BUSY. | ||
| 34 | // Matches the self-host open path (self-host-db.ts). | ||
| 35 | await client.execute("PRAGMA busy_timeout = 5000"); | ||
| 29 | return client; | 36 | return client; |
| 30 | }; | 37 | }; |
| 31 | 38 | ||