From 231f2f94a5f1a87b173bd89458c8226670d70969 Mon Sep 17 00:00:00 2001
From: Jean-Paul Calderone <exarkun@twistedmatrix.com>
Date: Fri, 29 May 2020 18:23:32 -0400
Subject: [PATCH] Raise the busy timeout

The default busy timeout is 0 and in the default configuration
read-blocks-write.  Thus by default it is extremely easy for concurrent
requests to the server to block each other.  So easy I can reproduce it with
about 100% fidelity in trivial local testing.

The transactions are all short lived, though, so re-attempting the lock
acquisition for for up to a second dramatically reduces the failure rate.

On a busy enough server it's conceivable a request might have to wait a full
second behind other requests to get access to the database.  In this case the
request will fail with the same "database is locked" error.  When that time
comes, it is probably worth just provisioning a faster server.  Or we could
explore WAL mode where read *doesn't* block write (though you can still only
have one writer and our API is pretty write heavy).
---
 src/PaymentServer/Persistence.hs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/PaymentServer/Persistence.hs b/src/PaymentServer/Persistence.hs
index 6f9548f..b11ad9d 100644
--- a/src/PaymentServer/Persistence.hs
+++ b/src/PaymentServer/Persistence.hs
@@ -336,6 +336,7 @@ sqlite path =
     connect = do
       dbConn <- Sqlite.open (unpack path)
       let exec = Sqlite.execute_ dbConn
+      exec "PRAGMA busy_timeout = 1000"
       exec "PRAGMA foreign_keys = ON"
       Sqlite.withExclusiveTransaction dbConn $ do
         exec "CREATE TABLE IF NOT EXISTS vouchers (id INTEGER PRIMARY KEY, name TEXT UNIQUE)"
-- 
GitLab