Voucher redemptions can still fail with a SQLite3 ErrorBusy
The voucher database connection is configured with a 1 second busy timeout. This means all our transactions will try to get a write lock on the database for about 1 second and, if they haven't gotten it yet, fail with ErrorBusy.
Payment processing is fairly quick - it involves just one row inserted. Voucher redemption is slightly more expensive but not much - it reads and writes a few rows.
So it seems like there shouldn't be ErrorBusy failures most of the time. However, they're fairly easily provoked with a few dozen concurrent clients redeeming vouchers as quickly as possible. This may be because there are only a few opportunities during that 1 second busy timeout when SQLite3 actually re-tries acquiring the necessary lock. On past projects I've implemented custom busy handling logic rather than use SQLite3's builtin logic. And since we know that we can't really support any write contention we may just want to serialize our access to the database at the application layer entirely - rather than relying on SQLite3 to do a not-very-good job of it.
Of course another approach would be to dramatically raise the busy timeout and let SQLite3 keep managing it.
These errors are fairly easily produced by running misc/load-test.py
.