From 495b54921954c32728b55a7de4537de7867ad021 Mon Sep 17 00:00:00 2001
From: Ramakrishnan Muthukrishnan <ram@leastauthority.com>
Date: Thu, 24 Oct 2019 17:04:05 +0530
Subject: [PATCH] do the read/write operations from the db should be in a
 transaction

`redeemVoucher' reads stuff from the db, makes decisions and then
writes to the db. However if there is another client doing a
simultaneous `redeemVoucher' for the same `voucher', then both of them
would redeem the voucher, which is incorrect. The operations should
have exclusive access to the db and this is achieved with
`withExclusiveTransaction`.
---
 src/PaymentServer/Persistence.hs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/PaymentServer/Persistence.hs b/src/PaymentServer/Persistence.hs
index 963550f..bdc3eb0 100644
--- a/src/PaymentServer/Persistence.hs
+++ b/src/PaymentServer/Persistence.hs
@@ -101,7 +101,7 @@ instance VoucherDatabase VoucherDatabaseState where
     let insertFn = (modifyIORef redeemed .) . Map.insert
     redeemVoucherHelper (unpaid, existingFingerprint) voucher fingerprint insertFn
 
-  redeemVoucher SQLiteDB { conn = conn } voucher fingerprint = do
+  redeemVoucher SQLiteDB { conn = conn } voucher fingerprint = Sqlite.withExclusiveTransaction conn $ do
     unpaid <- isVoucherUnpaid conn voucher
     existingFingerprint <- getVoucherFingerprint conn voucher
     let insertFn = insertVoucherAndFingerprint conn
-- 
GitLab