Guard against nested transactions
Not sure how to do this in PostgreSQL, so use a parameter.
This commit is contained in:
parent
982121c308
commit
2430bc4307
2 changed files with 111 additions and 93 deletions
|
|
@ -19,6 +19,7 @@
|
||||||
#:use-module (system foreign)
|
#:use-module (system foreign)
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:use-module (ice-9 threads)
|
#:use-module (ice-9 threads)
|
||||||
|
#:use-module (ice-9 exceptions)
|
||||||
#:use-module (squee)
|
#:use-module (squee)
|
||||||
#:use-module (prometheus)
|
#:use-module (prometheus)
|
||||||
#:use-module (guix-data-service config)
|
#:use-module (guix-data-service config)
|
||||||
|
|
@ -31,6 +32,7 @@
|
||||||
open-postgresql-connection
|
open-postgresql-connection
|
||||||
close-postgresql-connection
|
close-postgresql-connection
|
||||||
|
|
||||||
|
%postgresql-in-transaction?
|
||||||
with-postgresql-transaction
|
with-postgresql-transaction
|
||||||
|
|
||||||
check-test-database!
|
check-test-database!
|
||||||
|
|
@ -205,8 +207,16 @@
|
||||||
(define %postgresql-connections-name
|
(define %postgresql-connections-name
|
||||||
(make-parameter #f))
|
(make-parameter #f))
|
||||||
|
|
||||||
|
(define %postgresql-in-transaction?
|
||||||
|
(make-parameter #f))
|
||||||
|
|
||||||
(define* (with-postgresql-transaction conn f
|
(define* (with-postgresql-transaction conn f
|
||||||
#:key always-rollback?)
|
#:key always-rollback?)
|
||||||
|
(when (%postgresql-in-transaction?)
|
||||||
|
(raise-exception
|
||||||
|
(make-exception-with-message
|
||||||
|
"nested transaction detected")))
|
||||||
|
|
||||||
(exec-query conn "BEGIN;")
|
(exec-query conn "BEGIN;")
|
||||||
|
|
||||||
(with-exception-handler
|
(with-exception-handler
|
||||||
|
|
@ -219,7 +229,10 @@
|
||||||
;; TODO Include the stack in the exception via knots
|
;; TODO Include the stack in the exception via knots
|
||||||
(raise-exception exn))
|
(raise-exception exn))
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(let ((result (f conn)))
|
(let ((result
|
||||||
|
(parameterize
|
||||||
|
((%postgresql-in-transaction? #t))
|
||||||
|
(f conn))))
|
||||||
(exec-query conn (if always-rollback?
|
(exec-query conn (if always-rollback?
|
||||||
"ROLLBACK;"
|
"ROLLBACK;"
|
||||||
"COMMIT;"))
|
"COMMIT;"))
|
||||||
|
|
|
||||||
|
|
@ -2562,19 +2562,21 @@ SELECT store_path FROM derivation_source_files WHERE id = $1"
|
||||||
(define guix-revision-id-promise
|
(define guix-revision-id-promise
|
||||||
(fibers-delay
|
(fibers-delay
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(retry-on-missing-store-item
|
(parameterize
|
||||||
(lambda ()
|
((%postgresql-in-transaction? #f))
|
||||||
(let ((guix-source
|
(retry-on-missing-store-item
|
||||||
channel-derivations-by-system
|
(lambda ()
|
||||||
(fibers-force channel-derivations-by-system-promise)))
|
(let ((guix-source
|
||||||
(load-channel-instances call-with-utility-thread
|
channel-derivations-by-system
|
||||||
read-derivations/fiberized
|
(fibers-force channel-derivations-by-system-promise)))
|
||||||
derivation-ids-hash-table
|
(load-channel-instances call-with-utility-thread
|
||||||
git-repository-id commit
|
read-derivations/fiberized
|
||||||
channel-derivations-by-system)))
|
derivation-ids-hash-table
|
||||||
#:on-exception
|
git-repository-id commit
|
||||||
(lambda ()
|
channel-derivations-by-system)))
|
||||||
(fibers-promise-reset channel-derivations-by-system-promise))))))
|
#:on-exception
|
||||||
|
(lambda ()
|
||||||
|
(fibers-promise-reset channel-derivations-by-system-promise)))))))
|
||||||
|
|
||||||
;; Prompt getting the guix-revision-id as soon as possible
|
;; Prompt getting the guix-revision-id as soon as possible
|
||||||
(spawn-fiber
|
(spawn-fiber
|
||||||
|
|
@ -3032,95 +3034,98 @@ SKIP LOCKED")
|
||||||
(make-channel))
|
(make-channel))
|
||||||
|
|
||||||
(define result
|
(define result
|
||||||
(with-postgresql-connection
|
(parameterize
|
||||||
(simple-format #f "load-new-guix-revision ~A" id)
|
;; Mimic the behaviour of with-postgresql-transaction
|
||||||
(lambda (conn)
|
((%postgresql-in-transaction? #t))
|
||||||
;; Fix the hash encoding of derivation_output_details. This'll only run
|
(with-postgresql-connection
|
||||||
;; once on any given database, but is kept here just to make sure any
|
(simple-format #f "load-new-guix-revision ~A" id)
|
||||||
;; instances have the data updated.
|
(lambda (conn)
|
||||||
(fix-derivation-output-details-hash-encoding conn)
|
;; Fix the hash encoding of derivation_output_details. This'll only run
|
||||||
|
;; once on any given database, but is kept here just to make sure any
|
||||||
|
;; instances have the data updated.
|
||||||
|
(fix-derivation-output-details-hash-encoding conn)
|
||||||
|
|
||||||
(add-hook! after-gc-hook
|
(add-hook! after-gc-hook
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(simple-format (current-error-port)
|
(simple-format (current-error-port)
|
||||||
"after gc\n")))
|
"after gc\n")))
|
||||||
|
|
||||||
(exec-query conn "BEGIN")
|
(exec-query conn "BEGIN")
|
||||||
|
|
||||||
(spawn-fiber
|
(spawn-fiber
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(while (perform-operation
|
(while (perform-operation
|
||||||
(choice-operation
|
(choice-operation
|
||||||
(wrap-operation (get-operation finished-channel)
|
(wrap-operation (get-operation finished-channel)
|
||||||
(const #f))
|
(const #f))
|
||||||
(wrap-operation (sleep-operation 20)
|
(wrap-operation (sleep-operation 20)
|
||||||
(const #t))))
|
(const #t))))
|
||||||
|
|
||||||
(let ((stats (gc-stats)))
|
(let ((stats (gc-stats)))
|
||||||
(simple-format
|
(simple-format
|
||||||
(current-error-port)
|
(current-error-port)
|
||||||
"process-job heap: ~a MiB used (~a MiB heap)~%"
|
"process-job heap: ~a MiB used (~a MiB heap)~%"
|
||||||
(round
|
(round
|
||||||
(/ (- (assoc-ref stats 'heap-size)
|
(/ (- (assoc-ref stats 'heap-size)
|
||||||
(assoc-ref stats 'heap-free-size))
|
(assoc-ref stats 'heap-free-size))
|
||||||
(expt 2. 20)))
|
(expt 2. 20)))
|
||||||
(round
|
(round
|
||||||
(/ (assoc-ref stats 'heap-size)
|
(/ (assoc-ref stats 'heap-size)
|
||||||
(expt 2. 20))))))))
|
(expt 2. 20))))))))
|
||||||
|
|
||||||
(match (select-job-for-update conn id)
|
(match (select-job-for-update conn id)
|
||||||
(((id commit source git-repository-id))
|
(((id commit source git-repository-id))
|
||||||
|
|
||||||
;; With a separate connection, outside of the transaction so the event
|
;; With a separate connection, outside of the transaction so the event
|
||||||
;; gets persisted regardless.
|
;; gets persisted regardless.
|
||||||
(with-postgresql-connection
|
(with-postgresql-connection
|
||||||
(simple-format #f "load-new-guix-revision ~A start-event" id)
|
(simple-format #f "load-new-guix-revision ~A start-event" id)
|
||||||
(lambda (start-event-conn)
|
(lambda (start-event-conn)
|
||||||
(record-job-event start-event-conn id "start")))
|
(record-job-event start-event-conn id "start")))
|
||||||
|
|
||||||
(simple-format #t "Processing job ~A (commit: ~A, source: ~A)\n\n"
|
(simple-format #t "Processing job ~A (commit: ~A, source: ~A)\n\n"
|
||||||
id commit source)
|
id commit source)
|
||||||
|
|
||||||
(if (eq?
|
(if (eq?
|
||||||
(with-time-logging (string-append "processing revision " commit)
|
(with-time-logging (string-append "processing revision " commit)
|
||||||
(with-exception-handler
|
(with-exception-handler
|
||||||
(const #f)
|
(const #f)
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(with-exception-handler
|
(with-exception-handler
|
||||||
(lambda (exn)
|
(lambda (exn)
|
||||||
(simple-format (current-error-port)
|
(simple-format (current-error-port)
|
||||||
"error: load-new-guix-revision: ~A\n"
|
"error: load-new-guix-revision: ~A\n"
|
||||||
exn)
|
exn)
|
||||||
(print-backtrace-and-exception/knots exn)
|
(print-backtrace-and-exception/knots exn)
|
||||||
(raise-exception exn))
|
(raise-exception exn))
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(load-new-guix-revision
|
(load-new-guix-revision
|
||||||
conn
|
conn
|
||||||
git-repository-id
|
git-repository-id
|
||||||
commit
|
commit
|
||||||
#:skip-system-tests? #t
|
#:skip-system-tests? #t
|
||||||
#:extra-inferior-environment-variables
|
#:extra-inferior-environment-variables
|
||||||
extra-inferior-environment-variables
|
extra-inferior-environment-variables
|
||||||
#:ignore-systems ignore-systems
|
#:ignore-systems ignore-systems
|
||||||
#:ignore-targets ignore-targets
|
#:ignore-targets ignore-targets
|
||||||
#:parallelism parallelism))))
|
#:parallelism parallelism))))
|
||||||
#:unwind? #t))
|
#:unwind? #t))
|
||||||
#t)
|
#t)
|
||||||
(begin
|
(begin
|
||||||
(record-job-succeeded conn id)
|
(record-job-succeeded conn id)
|
||||||
(record-job-event conn id "success")
|
(record-job-event conn id "success")
|
||||||
(exec-query conn "COMMIT")
|
(exec-query conn "COMMIT")
|
||||||
|
|
||||||
#t)
|
#t)
|
||||||
(begin
|
(begin
|
||||||
(exec-query conn "ROLLBACK")
|
(exec-query conn "ROLLBACK")
|
||||||
(record-job-event conn id "failure")
|
(record-job-event conn id "failure")
|
||||||
|
|
||||||
#f)))
|
#f)))
|
||||||
(()
|
(()
|
||||||
(exec-query conn "ROLLBACK")
|
(exec-query conn "ROLLBACK")
|
||||||
(simple-format #t "job ~A not found to be processed\n"
|
(simple-format #t "job ~A not found to be processed\n"
|
||||||
id))))))
|
id)))))))
|
||||||
|
|
||||||
(when result
|
(when result
|
||||||
(fibers-parallel
|
(fibers-parallel
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue