aboutsummaryrefslogtreecommitdiff
path: root/guix-build-coordinator/datastore/sqlite.scm
diff options
context:
space:
mode:
authorChristopher Baines <mail@cbaines.net>2023-04-21 00:20:31 +0100
committerChristopher Baines <mail@cbaines.net>2023-04-21 00:20:31 +0100
commit500d9f69b57f0f53403b06aef4629c5cc75faa31 (patch)
treecbc1165abf6b3e1c69238a3f28543a70e424b8b9 /guix-build-coordinator/datastore/sqlite.scm
parentce7ae649cfac5aa1c43384e1b5caeb19d8a1cffb (diff)
downloadbuild-coordinator-500d9f69b57f0f53403b06aef4629c5cc75faa31.tar
build-coordinator-500d9f69b57f0f53403b06aef4629c5cc75faa31.tar.gz
Handle COMMIT erroring with busy in datastore-call-with-transaction
Diffstat (limited to 'guix-build-coordinator/datastore/sqlite.scm')
-rw-r--r--guix-build-coordinator/datastore/sqlite.scm90
1 files changed, 55 insertions, 35 deletions
diff --git a/guix-build-coordinator/datastore/sqlite.scm b/guix-build-coordinator/datastore/sqlite.scm
index ce9b7e5..c19468c 100644
--- a/guix-build-coordinator/datastore/sqlite.scm
+++ b/guix-build-coordinator/datastore/sqlite.scm
@@ -422,44 +422,64 @@ PRAGMA optimize;")))))
(immediate? (not readonly?))
duration-metric-name)
(define (run-proc-within-transaction db)
- (if (with-exception-handler
- (lambda (exn)
- (match (exception-args exn)
- (('sqlite-exec 5 msg)
- (simple-format (current-error-port) "warning: sqlite error: ~A\n" msg)
- #f)
- (_
- (simple-format (current-error-port)
- "exception starting transaction\n")
- (raise-exception exn))))
- (lambda ()
- (sqlite-exec db (if immediate?
- "BEGIN IMMEDIATE TRANSACTION;"
- "BEGIN TRANSACTION;"))
- #t)
- #:unwind? #t)
-
- (with-exception-handler
- (lambda (exn)
- (if (transaction-rollback-exception? exn)
- (begin
- (sqlite-exec db "ROLLBACK TRANSACTION;")
- (transaction-rollback-exception-return-value exn))
- (begin
- (simple-format (current-error-port)
- "error: sqlite rolling back transaction (~A)\n"
- exn)
- (sqlite-exec db "ROLLBACK TRANSACTION;")
- (raise-exception exn))))
- (lambda ()
- (call-with-values
+ (define (attempt-begin)
+ (with-exception-handler
+ (lambda (exn)
+ (match (exception-args exn)
+ (('sqlite-exec 5 msg)
+ (simple-format (current-error-port) "warning: sqlite error: ~A\n" msg)
+ #f)
+ (_
+ (simple-format (current-error-port)
+ "exception starting transaction\n")
+ (raise-exception exn))))
+ (lambda ()
+ (sqlite-exec db (if immediate?
+ "BEGIN IMMEDIATE TRANSACTION;"
+ "BEGIN TRANSACTION;"))
+ #t)
+ #:unwind? #t))
+
+ (define (attempt-commit)
+ (with-exception-handler
+ (lambda (exn)
+ (match (exception-args exn)
+ (('sqlite-exec 5 msg)
+ (simple-format (current-error-port) "warning: sqlite error: ~A\n" msg)
+ #f)
+ (_
+ (simple-format (current-error-port)
+ "exception committing transaction\n")
+ (raise-exception exn))))
+ (lambda ()
+ (sqlite-exec db "COMMIT TRANSACTION;")
+ #t)
+ #:unwind? #t))
+
+ (if (attempt-begin)
+ (call-with-values
+ (lambda ()
+ (with-exception-handler
+ (lambda (exn)
+ (if (transaction-rollback-exception? exn)
+ (begin
+ (sqlite-exec db "ROLLBACK TRANSACTION;")
+ (transaction-rollback-exception-return-value exn))
+ (begin
+ (simple-format (current-error-port)
+ "error: sqlite rolling back transaction (~A)\n"
+ exn)
+ (sqlite-exec db "ROLLBACK TRANSACTION;")
+ (raise-exception exn))))
(lambda ()
(parameterize ((%current-transaction-proc proc))
(proc-with-duration-timing db)))
- (lambda vals
- (sqlite-exec db "COMMIT TRANSACTION;")
- (apply values vals))))
- #:unwind? #t)
+ #:unwind? #t))
+ (lambda vals
+ (let loop ((success? (attempt-commit)))
+ (if success?
+ (apply values vals)
+ (loop (attempt-commit))))))
;; Database is busy, so retry
(run-proc-within-transaction db)))