diff --git a/guix-data-service/database.scm b/guix-data-service/database.scm index 8c43273..e68f3f1 100644 --- a/guix-data-service/database.scm +++ b/guix-data-service/database.scm @@ -22,6 +22,7 @@ #:use-module (ice-9 exceptions) #:use-module (squee) #:use-module (prometheus) + #:use-module (knots) #:use-module (guix-data-service config) #:export (get-database-config %database-metrics-registry @@ -226,17 +227,31 @@ (lambda () (exec-query conn "ROLLBACK;")) #:unwind? #t) - ;; TODO Include the stack in the exception via knots (raise-exception exn)) (lambda () - (let ((result - (parameterize - ((%postgresql-in-transaction? #t)) - (f conn)))) - (exec-query conn (if always-rollback? - "ROLLBACK;" - "COMMIT;")) - result)) + (with-exception-handler + (lambda (exn) + (let ((stack + (match (fluid-ref %stacks) + ((stack-tag . prompt-tag) + (make-stack #t + 0 prompt-tag + 0 (and prompt-tag 1))) + (_ + (make-stack #t))))) + (raise-exception + (make-exception + exn + (make-knots-exception stack))))) + (lambda () + (let ((result + (parameterize + ((%postgresql-in-transaction? #t)) + (f conn)))) + (exec-query conn (if always-rollback? + "ROLLBACK;" + "COMMIT;")) + result)))) #:unwind? #t)) (define (check-test-database! conn) diff --git a/guix-data-service/jobs/load-new-guix-revision.scm b/guix-data-service/jobs/load-new-guix-revision.scm index 6663a95..9014f09 100644 --- a/guix-data-service/jobs/load-new-guix-revision.scm +++ b/guix-data-service/jobs/load-new-guix-revision.scm @@ -177,9 +177,13 @@ inf))) stringderivation-ids postgresql-connection-pool call-with-utility-thread - read-derivations/fiberized + read-derivations/serialised derivation-ids-hash-table derivation-file-names #:key (log-tag "unspecified")) @@ -1414,7 +1422,7 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" (chunk-for-each! (lambda (missing-derivation-file-names-chunk) (let ((missing-derivations-chunk - (read-derivations/fiberized + (read-derivations/serialised missing-derivation-file-names-chunk))) (simple-format #t "debug: derivation-file-names->derivation-ids: processing chunk ~A (~A)\n" @@ -1752,6 +1760,8 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" #:unwind? #t))))) systems))) + (destroy-resource-pool inferior-and-store-pool) + (cons (channel-instance-checkout channel-instance) result))) @@ -1972,7 +1982,7 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" guix-source store-item guix-derivation call-with-utility-thread - read-derivations/fiberized + read-derivations/serialised derivation-ids-hash-table #:key skip-system-tests? extra-inferior-environment-variables @@ -2268,43 +2278,50 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" *unspecified*) + (define get-derivations/parallelism-limiter + (make-parallelism-limiter parallelism)) (define (get-derivations system target) - (let ((derivations-vector (make-vector packages-count))) - (with-time-logging - (simple-format #f "getting derivations for ~A" (cons system target)) - (let loop ((start-index 0)) - (let* ((last-chunk? - (>= (+ start-index chunk-size) packages-count)) - (count - (if last-chunk? - (- packages-count start-index) - chunk-size)) - (chunk - (call-with-inferior - (lambda (inferior inferior-store) - (ensure-gds-inferior-packages-defined! inferior) + ;; Limit concurrency here to keep focused on specific systems until + ;; they've been fully processed + (with-parallelism-limiter + get-derivations/parallelism-limiter + (let ((derivations-vector (make-vector packages-count))) + (with-time-logging + (simple-format #f "getting derivations for ~A" + (cons system target)) + (let loop ((start-index 0)) + (let* ((last-chunk? + (>= (+ start-index chunk-size) packages-count)) + (count + (if last-chunk? + (- packages-count start-index) + chunk-size)) + (chunk + (call-with-inferior + (lambda (inferior inferior-store) + (ensure-gds-inferior-packages-defined! inferior) - (let ((result - (inferior-package-derivations - inferior-store - inferior - system - target - start-index - count))) + (let ((result + (inferior-package-derivations + inferior-store + inferior + system + target + start-index + count))) - (when last-chunk? - (inferior-cleanup inferior)) + (when last-chunk? + (inferior-cleanup inferior)) - result))))) - (vector-copy! derivations-vector - start-index - chunk) - (unless last-chunk? - (loop (+ start-index chunk-size)))))) - derivations-vector)) + result))))) + (vector-copy! derivations-vector + start-index + chunk) + (unless last-chunk? + (loop (+ start-index chunk-size)))))) + derivations-vector))) - (define (process-system-and-target system target get-derivations) + (define (process-system-and-target system target) (with-time-logging (simple-format #f "processing derivations for ~A" (cons system target)) (let* ((derivations-vector (get-derivations system target)) @@ -2315,7 +2332,7 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" (derivation-file-names->derivation-ids postgresql-connection-pool call-with-utility-thread - read-derivations/fiberized + read-derivations/serialised derivation-ids-hash-table derivations-vector #:log-tag (simple-format #f "~A:~A" system target)))) @@ -2345,46 +2362,43 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" 'finished) - (let ((get-derivations/fiberized - (fiberize get-derivations - ;; Limit concurrency here to keep focused on specific - ;; systems until they've been fully processed - #:parallelism parallelism))) - (with-time-logging "extract-and-store-package-derivations" - (fibers-map-with-progress - (match-lambda - ((system . target) - (retry-on-missing-store-item - (lambda () - (process-system-and-target system target - get-derivations/fiberized))))) - (list - (let ((all-system-target-pairs - (call-with-inferior - (lambda (inferior inferior-store) - (inferior-fetch-system-target-pairs inferior))))) - (filter - (match-lambda - ((system . target) - (if (or (member system ignore-systems) - (member target ignore-targets)) - (begin - (simple-format - (current-error-port) - "ignoring ~A ~A for package derivations\n" - system - target) - #f) - #t))) - all-system-target-pairs))) - #:report - (lambda (data) - (for-each - (match-lambda - ((result (system . target)) - (simple-format #t "~A ~A: ~A\n" - system target result))) - data)))))) + (with-time-logging "extract-and-store-package-derivations" + (fibers-map-with-progress + (match-lambda + ((system . target) + (retry-on-missing-store-item + (lambda () + (process-system-and-target system target))))) + (list + (let ((all-system-target-pairs + (call-with-inferior + (lambda (inferior inferior-store) + (inferior-fetch-system-target-pairs inferior))))) + (filter + (match-lambda + ((system . target) + (if (or (member system ignore-systems) + (member target ignore-targets)) + (begin + (simple-format + (current-error-port) + "ignoring ~A ~A for package derivations\n" + system + target) + #f) + #t))) + all-system-target-pairs))) + #:report + (lambda (data) + (for-each + (match-lambda + ((result (system . target)) + (simple-format #t "~A ~A: ~A\n" + system target result))) + data))) + (destroy-parallelism-limiter + get-derivations/parallelism-limiter) + #t)) (define (extract-and-store-system-tests) (if skip-system-tests? @@ -2400,7 +2414,8 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" inferior inferior-store guix-source - commit)))))) + commit + #:ignore-systems ignore-systems)))))) (when data-with-derivation-file-names (let ((data-with-derivation-ids (map (match-lambda @@ -2414,7 +2429,7 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" (derivation-file-names->derivation-ids postgresql-connection-pool call-with-utility-thread - read-derivations/fiberized + read-derivations/serialised derivation-ids-hash-table (list->vector (map cdr derivation-file-names-by-system)) @@ -2439,12 +2454,15 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" (with-time-logging "extract-and-store-lint-checkers-and-warnings" (extract-and-store-lint-checkers-and-warnings)))) + (destroy-resource-pool inf-and-store-pool) + (destroy-resource-pool postgresql-connection-pool) + #t) (prevent-inlining-for-tests extract-information-from) (define (load-channel-instances call-with-utility-thread - read-derivations/fiberized + read-derivations/serialised derivation-ids-hash-table git-repository-id commit channel-derivations-by-system) @@ -2473,9 +2491,8 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" (insert-guix-revision channel-instances-conn git-repository-id commit))) (postgresql-connection-pool - (make-resource-pool - (const channel-instances-conn) - 1 + (make-fixed-size-resource-pool + (list channel-instances-conn) #:name "postgres"))) (unless existing-guix-revision-id @@ -2493,7 +2510,7 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" (derivation-file-names->derivation-ids postgresql-connection-pool call-with-utility-thread - read-derivations/fiberized + read-derivations/serialised derivation-ids-hash-table (list->vector (map cdr derivations-by-system))))) @@ -2537,11 +2554,13 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" (make-missing-store-item-error filename)))) filenames)))) - (define read-derivations/fiberized - (fiberize read-derivations - ;; Don't do this in parallel as there's caching involved with - ;; read-derivation-from-file - #:parallelism 1)) + + (define read-derivations/parallelism-limiter + (make-parallelism-limiter 1)) + (define (read-derivations/serialised . args) + (with-parallelism-limiter + read-derivations/parallelism-limiter + (apply read-derivations args))) (define derivation-ids-hash-table (make-hash-table)) @@ -2581,7 +2600,7 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" channel-derivations-by-system (fibers-force channel-derivations-by-system-promise))) (load-channel-instances call-with-utility-thread - read-derivations/fiberized + read-derivations/serialised derivation-ids-hash-table git-repository-id commit channel-derivations-by-system))) @@ -2608,7 +2627,7 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" commit guix-source store-item guix-derivation call-with-utility-thread - read-derivations/fiberized + read-derivations/serialised derivation-ids-hash-table #:skip-system-tests? skip-system-tests? @@ -2619,6 +2638,9 @@ SELECT store_path FROM derivation_source_files WHERE id = $1" #:parallelism parallelism) (let ((guix-revision-id (fibers-force guix-revision-id-promise))) + (destroy-parallelism-limiter + read-derivations/parallelism-limiter) + (and (if (defined? 'channel-news-for-commit (resolve-module '(guix channels))) @@ -3133,7 +3155,9 @@ SKIP LOCKED") #:parallelism parallelism)) (record-job-succeeded conn id) - (record-job-event conn id "success")) + (record-job-event conn id "success") + + #t) (() (raise-exception job-not-found-exception)))))))) diff --git a/guix-dev.scm b/guix-dev.scm index b468015..13d1e23 100644 --- a/guix-dev.scm +++ b/guix-dev.scm @@ -42,7 +42,7 @@ (srfi srfi-1)) (define guile-knots - (let ((commit "016f37f108ca19da3664516baa97e907aa972b90") + (let ((commit "ab5411da423043f2b8a0e27c7507f8d9c34686a2") (revision "1")) (package (name "guile-knots") @@ -54,7 +54,7 @@ (commit commit))) (sha256 (base32 - "12j3l9p4acf47cjpfzm41ddxyxs1v6vlfa2vrymdd4gdday62xfn")) + "0v39yd9cfcwc23cmb4h89kvp9m96xdg47nbj2k80a43fbalfd9aq")) (file-name (string-append name "-" version "-checkout")))) (build-system gnu-build-system) (native-inputs diff --git a/scripts/guix-data-service-process-job.in b/scripts/guix-data-service-process-job.in index 5643246..029090d 100644 --- a/scripts/guix-data-service-process-job.in +++ b/scripts/guix-data-service-process-job.in @@ -93,18 +93,27 @@ (with-fluids ((%file-port-name-canonicalization 'none)) (run-fibers (lambda () - (process-load-new-guix-revision-job - job - #:skip-system-tests? (assq-ref opts 'skip-system-tests) - #:extra-inferior-environment-variables - (filter-map - (match-lambda - (('inferior-environment-variable key val) - (cons key val)) - (_ #f)) - opts) - #:ignore-systems (assq-ref opts 'ignore-systems) - #:ignore-targets (assq-ref opts 'ignore-targets) - #:parallelism (assq-ref opts 'parallelism))) + (with-exception-handler + (lambda (exn) + ;; Exit if exceptions get this far, as not all fibers are + ;; guaranteed to finish + (primitive-exit 1)) + (lambda () + (process-load-new-guix-revision-job + job + #:skip-system-tests? (assq-ref opts 'skip-system-tests) + #:extra-inferior-environment-variables + (filter-map + (match-lambda + (('inferior-environment-variable key val) + (cons key val)) + (_ #f)) + opts) + #:ignore-systems (assq-ref opts 'ignore-systems) + #:ignore-targets (assq-ref opts 'ignore-targets) + #:parallelism (assq-ref opts 'parallelism))) + #:unwind? #t)) #:hz 0 - #:parallelism 1))))) + #:parallelism 1 + ;; Drain to make sure there are no bugs with the use of fibers + #:drain? #t))))) diff --git a/tests/jobs-load-new-guix-revision.scm b/tests/jobs-load-new-guix-revision.scm index 64f2464..84d78e8 100644 --- a/tests/jobs-load-new-guix-revision.scm +++ b/tests/jobs-load-new-guix-revision.scm @@ -106,7 +106,8 @@ (process-load-new-guix-revision-job id #:parallelism 1)) #:hz 0 - #:parallelism 1)))))))))))))) + #:parallelism 1 + #:drain? #t)))))))))))))) (exec-query conn "TRUNCATE guix_revisions CASCADE") (exec-query conn "TRUNCATE load_new_guix_revision_jobs CASCADE")