aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bffe.scm50
-rw-r--r--bffe/config.scm.in1
-rw-r--r--bffe/manage-builds.scm260
-rw-r--r--bffe/server.scm27
-rw-r--r--bffe/view/activity.scm1
-rw-r--r--bffe/view/agent.scm4
-rw-r--r--bffe/view/build.scm22
-rw-r--r--bffe/view/home.scm4
-rw-r--r--bffe/view/util.scm8
-rw-r--r--guix-dev.scm33
10 files changed, 206 insertions, 204 deletions
diff --git a/bffe.scm b/bffe.scm
index 5b3d428..0c8f58c 100644
--- a/bffe.scm
+++ b/bffe.scm
@@ -17,6 +17,7 @@
;;; <http://www.gnu.org/licenses/>.
(define-module (bffe)
+ #:use-module (srfi srfi-1)
#:use-module (ice-9 format)
#:use-module (oop goops)
#:use-module (prometheus)
@@ -26,8 +27,7 @@
#:use-module (fibers scheduler)
#:use-module (fibers channels)
#:use-module (fibers conditions)
- #:use-module ((guix-build-coordinator utils fibers)
- #:select (call-with-sigint))
+ #:use-module (knots)
#:use-module (bffe server)
#:use-module (bffe manage-builds)
#:export (run-bffe-service))
@@ -45,11 +45,14 @@
(port-log (make <port-log>
#:port (current-output-port)
#:formatter
- (lambda (lvl time str)
+ ;; In guile-lib v0.2.8 onwards, the formatter is
+ ;; called with more arguments
+ (lambda args ; lvl, time, str
(format #f "~a (~5a): ~a~%"
- (strftime "%F %H:%M:%S" (localtime time))
- lvl
- str)))))
+ (strftime "%F %H:%M:%S" (localtime
+ (second args)))
+ (first args)
+ (third args))))))
(setvbuf (current-output-port) 'line)
@@ -57,20 +60,23 @@
(open-log! lgr)
(set-default-logger! lgr)
- (let ((finished? (make-condition)))
- (call-with-sigint
- (lambda ()
- (run-fibers
- (lambda ()
- (for-each start-submit-builds-fibers
- build)
+ (with-fluids ((%file-port-name-canonicalization 'none))
+ (let ((finished? (make-condition)))
+ (call-with-sigint
+ (lambda ()
+ (run-fibers
+ (lambda ()
+ (for-each
+ (lambda (spec)
+ (start-submit-builds-fibers metrics-registry spec))
+ build)
- (when web-server-args
- (apply start-bffe-web-server
- `(,@web-server-args
- #:pid-file ,pid-file
- #:metrics-registry ,metrics-registry)))
- (wait finished?))
- #:hz 0
- #:parallelism 1))
- finished?))))
+ (when web-server-args
+ (apply start-bffe-web-server
+ `(,@web-server-args
+ #:pid-file ,pid-file
+ #:metrics-registry ,metrics-registry)))
+ (wait finished?))
+ #:hz 0
+ #:parallelism 1))
+ finished?)))))
diff --git a/bffe/config.scm.in b/bffe/config.scm.in
index 19e5832..7af9d4d 100644
--- a/bffe/config.scm.in
+++ b/bffe/config.scm.in
@@ -17,7 +17,6 @@
;;; <http://www.gnu.org/licenses/>.
(define-module (bffe config)
- #:use-module (guix store)
#:export (%config))
(define %config
diff --git a/bffe/manage-builds.scm b/bffe/manage-builds.scm
index 16484c3..9a4bd3e 100644
--- a/bffe/manage-builds.scm
+++ b/bffe/manage-builds.scm
@@ -21,20 +21,19 @@
#:use-module (srfi srfi-71)
#:use-module (ice-9 match)
#:use-module (ice-9 exceptions)
- #:use-module (rnrs bytevectors)
#:use-module (ice-9 textual-ports)
#:use-module (logging logger)
- #:use-module (logging port-log)
+ #:use-module (prometheus)
#:use-module (zlib)
#:use-module (json)
#:use-module (fibers)
#:use-module (fibers channels)
+ #:use-module (knots queue)
+ #:use-module (knots parallelism)
#:use-module (guix records)
#:use-module (web uri)
- #:use-module (web client)
#:use-module (web response)
#:use-module (guix-build-coordinator client-communication)
- #:use-module ((guix-build-coordinator utils) #:select (create-work-queue))
#:use-module ((guix-build-coordinator utils fibers) #:select (retry-on-error))
#:use-module (bffe server)
#:export (build-from-guix-data-service
@@ -43,8 +42,9 @@
build-from-guix-data-service-systems
build-from-guix-data-service-systems-and-targets
build-from-guix-data-service-submit-builds-for-channel-instances?
- build-from-guix-data-service-build-priority
+ build-from-guix-data-service-build-keyword-arguments
build-from-guix-data-service-data-service-build-server-id
+ build-from-guix-data-service-ignore-commits
start-submit-builds-fibers))
@@ -60,14 +60,18 @@
(submit-builds-for-channel-instances?
build-from-guix-data-service-submit-builds-for-channel-instances?
(default #f))
- (build-priority build-from-guix-data-service-build-priority
- (default #f))
+ (build-keyword-arguments build-from-guix-data-service-build-keyword-arguments
+ (default #f))
(data-service-build-server-id
build-from-guix-data-service-data-service-build-server-id
(default #f))
(revision-parameters
build-from-guix-data-service-revision-parameters
- (default '())))
+ (default '()))
+ (parallelism build-from-guix-data-service-parallelism
+ (default 2))
+ (ignore-commits build-from-guix-data-service-ignore-commits
+ (default '())))
(define-exception-type &guix-data-service-error &error
make-guix-data-service-error
@@ -78,7 +82,7 @@
(define* (guix-data-service-request guix-data-service
path
#:optional (query-parameters '())
- #:key (retry-times 0) (retry-delay 15))
+ #:key (retry-times 3) (retry-delay 60))
(define uri
(string->uri (string-append
guix-data-service
@@ -140,13 +144,18 @@
make-request
#:times retry-times
#:delay retry-delay
- #:ignore (lambda (exn)
- (and (guix-data-service-error? exn)
- (< (guix-data-service-error-response-code exn)
- 500))))))
+ #:no-retry (lambda (exn)
+ (and (guix-data-service-error? exn)
+ (not
+ (= (guix-data-service-error-response-code exn)
+ 429))
+ (< (guix-data-service-error-response-code exn)
+ 500))))))
(define* (fiberize proc #:key (parallelism 1))
- (let ((channel (make-channel)))
+ (let* ((channel (make-channel))
+ (queue-channel
+ (spawn-queueing-fiber channel)))
(for-each
(lambda _
(spawn-fiber
@@ -175,74 +184,11 @@
(lambda args
(let ((reply-channel (make-channel)))
- (put-message channel (cons reply-channel args))
+ (put-message queue-channel (cons reply-channel args))
(match (get-message reply-channel)
(('result . vals) (apply values vals))
(('exception . exn) (raise-exception exn)))))))
-(define (fibers-map proc . lists)
- (let ((channels
- (apply
- map
- (lambda args
- (let ((channel (make-channel)))
- (spawn-fiber
- (lambda ()
- (put-message
- channel
- (with-exception-handler
- (lambda (exn)
- (cons 'exception exn))
- (lambda ()
- (with-throw-handler #t
- (lambda ()
- (call-with-values
- (lambda ()
- (apply proc args))
- (lambda val
- (cons 'result val))))
- (lambda _
- (backtrace))))
- #:unwind? #t))))
- channel))
- lists)))
- (map
- (match-lambda
- (('result . val) val)
- (('exception . exn) (raise-exception exn)))
- (map get-message channels))))
-
-(define (fibers-for-each proc . lists)
- ;; Like split-at, but don't care about the order of the resulting lists, and
- ;; don't error if the list is shorter than i elements
- (define (split-at* lst i)
- (let lp ((l lst) (n i) (acc '()))
- (if (or (<= n 0) (null? l))
- (values (reverse! acc) l)
- (lp (cdr l) (- n 1) (cons (car l) acc)))))
-
- ;; As this can be called with lists with tens of thousands of items in them,
- ;; batch the
- (define batch-size 20)
- (define (get-batch lists)
- (let ((split-lists
- (map (lambda (lst)
- (let ((batch rest (split-at* lst batch-size)))
- (cons batch rest)))
- lists)))
- (values (map car split-lists)
- (map cdr split-lists))))
-
- (let loop ((lists lists))
- (call-with-values
- (lambda ()
- (get-batch lists))
- (lambda (batch rest)
- (apply fibers-map proc batch)
- (unless (null? (car rest))
- (loop rest)))))
- *unspecified*)
-
(define (all-repository-ids guix-data-service)
(let ((data (guix-data-service-request guix-data-service
"/repositories.json"
@@ -300,7 +246,7 @@
guix-data-service
commit
systems
- priority-for-derivation
+ keyword-arguments-for-derivation
#:key
guix-data-service-build-server-id
branch)
@@ -337,26 +283,28 @@
(assoc-ref channel-instance-derivation "derivation"))
(system
(assoc-ref channel-instance-derivation "system")))
- (submit-build/fiberized
- coordinator
- guix-data-service
- derivation
- #:priority
- (priority-for-derivation 'channel-instance
- system
- "none")
- #:log-prefix
- (simple-format #f "channel instance (~A): ~A: "
- system
- derivation)
- #:tags `(((key . category)
- (value . channel-instance))
- ((key . revision)
- (value . ,commit))
- ,@(if branch
- `(((key . branch)
- (value . ,branch)))
- '())))))
+ (apply
+ submit-build/fiberized
+ (append!
+ (list
+ coordinator
+ guix-data-service
+ derivation
+ #:log-prefix
+ (simple-format #f "channel instance (~A): ~A: "
+ system
+ derivation)
+ #:tags `(((key . category)
+ (value . channel-instance))
+ ((key . revision)
+ (value . ,commit))
+ ,@(if branch
+ `(((key . branch)
+ (value . ,branch)))
+ '())))
+ (keyword-arguments-for-derivation 'channel-instance
+ system
+ "none")))))
channel-instance-derivations-to-submit))))
(define* (submit-package-builds-for-revision
@@ -366,7 +314,7 @@
commit
system
target
- priority-for-derivation
+ keyword-arguments-for-derivation
#:key
guix-data-service-build-server-id
branch)
@@ -391,39 +339,48 @@
" package builds for " log-suffix)
(fibers-for-each
(lambda (derivation)
- (submit-build/fiberized
- coordinator
- guix-data-service
- derivation
- #:priority
- (priority-for-derivation 'package
- system
- target)
- #:log-prefix
- (if (string=? target "none")
- (simple-format #f "package (~A): ~A: "
- system derivation)
- (simple-format #f "package (~A=>~A): ~A: "
- system target derivation))
- #:tags `(((key . category)
- (value . package))
- ((key . revision)
- (value . ,commit))
- ,@(if branch
- `(((key . branch)
- (value . ,branch)))
- '()))))
+ (apply
+ submit-build/fiberized
+ (append!
+ (list
+ coordinator
+ guix-data-service
+ derivation
+ #:log-prefix
+ (if (string=? target "none")
+ (simple-format #f "package (~A): ~A: "
+ system derivation)
+ (simple-format #f "package (~A=>~A): ~A: "
+ system target derivation))
+ #:tags `(((key . category)
+ (value . package))
+ ((key . revision)
+ (value . ,commit))
+ ,@(if branch
+ `(((key . branch)
+ (value . ,branch)))
+ '())))
+ (keyword-arguments-for-derivation 'package
+ system
+ target))))
unprocessed-package-derivations)
(log-msg 'INFO "finished submitting " (length unprocessed-package-derivations)
" package builds for " log-suffix))))
(define (submit-builds-pass
+ metrics-registry
submit-build/fiberized
guix-data-service
specification
processed-commits-hash
record-revision-as-processed
systems-and-targets)
+ (define unseen-revisions-metric
+ (or (metrics-registry-fetch-metric
+ metrics-registry "unseen_revisions_total")
+ (make-gauge-metric metrics-registry
+ "unseen_revisions_total")))
+
(fibers-for-each
(lambda (repository-id)
(fibers-for-each
@@ -440,17 +397,22 @@
(build-from-guix-data-service-revision-parameters specification)
#:retry-times 3))
(unseen-revisions
- (filter-map (lambda (entry)
- (let ((commit (assoc-ref entry "commit-hash")))
- (and (not (hash-ref processed-commits-hash
- commit))
- (assoc-ref entry "data_available")
- commit)))
- (vector->list
- (assoc-ref branch-revisions
- "revisions")))))
+ (filter-map
+ (lambda (entry)
+ (let ((commit (assoc-ref entry "commit-hash")))
+ (and (not (hash-ref processed-commits-hash
+ commit))
+ (not (member
+ commit
+ (build-from-guix-data-service-ignore-commits
+ specification)))
+ (assoc-ref entry "data_available")
+ commit)))
+ (vector->list
+ (assoc-ref branch-revisions "revisions")))))
(log-msg 'DEBUG (length unseen-revisions)
" unseen revisions")
+ (metric-set unseen-revisions-metric (length unseen-revisions))
(for-each
(lambda (commit)
(log-msg 'INFO "looking at revision " commit)
@@ -464,7 +426,7 @@
guix-data-service
commit
(map car systems-and-targets)
- (build-from-guix-data-service-build-priority
+ (build-from-guix-data-service-build-keyword-arguments
specification)
#:guix-data-service-build-server-id
(build-from-guix-data-service-data-service-build-server-id
@@ -483,7 +445,7 @@
commit
system
target
- (build-from-guix-data-service-build-priority
+ (build-from-guix-data-service-build-keyword-arguments
specification)
#:guix-data-service-build-server-id
(build-from-guix-data-service-data-service-build-server-id
@@ -492,6 +454,7 @@
systems-and-targets)
(log-msg 'INFO "finished looking at revision " commit)
+ (metric-decrement unseen-revisions-metric)
(record-revision-as-processed commit))
(reverse unseen-revisions))))
(let ((all-branches (all-repository-branches guix-data-service
@@ -505,9 +468,16 @@
(sleep 60))
-(define* (start-submit-builds-fibers specification
+(define* (start-submit-builds-fibers metrics-registry
+ specification
#:key
processed-commits-file)
+ (define build-submitted-counter-metric
+ (or (metrics-registry-fetch-metric metrics-registry
+ "build_submitted_total")
+ (make-counter-metric metrics-registry
+ "build_submitted_total")))
+
(define processed-commits-hash
(make-hash-table))
@@ -519,9 +489,10 @@
(simple-format port "~A\n" commit)
(close-port port))))
-(define* (submit-build coordinator guix-data-service derivation
+ (define* (submit-build coordinator guix-data-service derivation
#:key (priority 0) (log-prefix "")
- (tags '()))
+ (tags '())
+ skip-updating-derived-priorities?)
(retry-on-error
(lambda ()
(let ((response
@@ -534,13 +505,17 @@
#t
#t
#t
- tags)))
+ tags
+ #:skip-updating-derived-priorities?
+ skip-updating-derived-priorities?)))
(let ((no-build-submitted-response
(assoc-ref response "no-build-submitted")))
(if no-build-submitted-response
(log-msg 'DEBUG log-prefix "skipped: " no-build-submitted-response)
- (log-msg 'DEBUG log-prefix "build submitted as "
- (assoc-ref response "build-submitted"))))))
+ (begin
+ (metric-increment build-submitted-counter-metric)
+ (log-msg 'DEBUG log-prefix "build submitted as "
+ (assoc-ref response "build-submitted")))))))
;; The TTL Guix uses for transient failures fetching substitutes is 10
;; minutes, so we need to retry for longer than that
#:times 30
@@ -572,8 +547,8 @@
(let ((submit-build/fiberized
(fiberize submit-build
- #:parallelism 8)))
-
+ #:parallelism (build-from-guix-data-service-parallelism
+ specification))))
(spawn-fiber
(lambda ()
(while #t
@@ -587,7 +562,8 @@
(lambda ()
(with-throw-handler #t
(lambda ()
- (submit-builds-pass submit-build/fiberized
+ (submit-builds-pass metrics-registry
+ submit-build/fiberized
guix-data-service
specification
processed-commits-hash
diff --git a/bffe/server.scm b/bffe/server.scm
index dc9a06d..0c8c5d1 100644
--- a/bffe/server.scm
+++ b/bffe/server.scm
@@ -24,12 +24,9 @@
#:use-module (srfi srfi-19)
#:use-module (srfi srfi-71)
#:use-module (ice-9 vlist)
- #:use-module (ice-9 threads)
#:use-module (ice-9 match)
#:use-module (ice-9 atomic)
#:use-module (ice-9 textual-ports)
- #:use-module (rnrs bytevectors)
- #:use-module (web http)
#:use-module (web client)
#:use-module (web request)
#:use-module (web response)
@@ -38,18 +35,12 @@
#:use-module (prometheus)
#:use-module (system repl error-handling)
#:use-module (fibers)
- #:use-module (fibers scheduler)
#:use-module (fibers channels)
- #:use-module (fibers conditions)
- #:use-module (fibers web server)
+ #:use-module (knots web-server)
#:use-module ((guix store) #:select (%store-prefix))
- #:use-module ((guix build utils) #:select (dump-port))
#:use-module (guix-data-service web util)
- #:use-module ((guix-build-coordinator utils)
- #:select (with-time-logging call-with-delay-logging))
#:use-module ((guix-build-coordinator utils fibers)
- #:select (run-server/patched retry-on-error))
- #:use-module (guix-build-coordinator client-communication)
+ #:select (retry-on-error))
#:use-module (bffe config)
#:use-module (bffe view util)
#:use-module (bffe view home)
@@ -154,7 +145,7 @@
(lambda ()
(with-throw-handler #t
(lambda ()
- (let ((response
+ (let ((_
body
(http-get*
(string->uri
@@ -641,8 +632,10 @@
(sleep 1))
(simple-format #t "Starting the server\n")
- (run-server/patched (lambda (request body)
- (apply values
- (handler request body controller)))
- #:host host
- #:port port))))
+ (run-knots-web-server
+ (lambda (request)
+ (let ((body (read-request-body request)))
+ (apply values
+ (handler request body controller))))
+ #:host host
+ #:port port))))
diff --git a/bffe/view/activity.scm b/bffe/view/activity.scm
index 1621872..5a97bd2 100644
--- a/bffe/view/activity.scm
+++ b/bffe/view/activity.scm
@@ -2,7 +2,6 @@
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-19)
#:use-module (ice-9 match)
- #:use-module (ice-9 format)
#:use-module (bffe view util)
#:use-module ((guix store) #:select (%store-prefix))
#:export (activity))
diff --git a/bffe/view/agent.scm b/bffe/view/agent.scm
index e210402..1de2f71 100644
--- a/bffe/view/agent.scm
+++ b/bffe/view/agent.scm
@@ -1,10 +1,6 @@
(define-module (bffe view agent)
#:use-module (srfi srfi-1)
- #:use-module (srfi srfi-19)
- #:use-module (ice-9 match)
- #:use-module (ice-9 format)
#:use-module (bffe view util)
- #:use-module ((guix store) #:select (%store-prefix))
#:export (agent))
(define (agent title agent-details)
diff --git a/bffe/view/build.scm b/bffe/view/build.scm
index ded00ef..1a7dc53 100644
--- a/bffe/view/build.scm
+++ b/bffe/view/build.scm
@@ -1,10 +1,6 @@
(define-module (bffe view build)
#:use-module (srfi srfi-1)
- #:use-module (srfi srfi-19)
- #:use-module (ice-9 match)
- #:use-module (ice-9 format)
#:use-module (bffe view util)
- #:use-module ((guix store) #:select (%store-prefix))
#:export (build))
(define (build title build-details derivation-link-target tag-link-target)
@@ -50,7 +46,23 @@
"success")
"Succeeded"
"Failed")
- "Pending")))
+ "Pending"))
+ ,@(or (and=>
+ (peek (assoc-ref build-details "result"))
+ (lambda (result)
+ `((ul
+ (li "Agent "
+ (a (@ (href ,(string-append
+ "/agent/"
+ (assoc-ref result "agent_id"))))
+ ,(assoc-ref result "agent_id")))
+ ,@(or (and=>
+ (assoc-ref result "failure_reason")
+ (lambda (failure-reason)
+ `((li "Failure reason: ")
+ (dl ,failure-reason))))
+ '())))))
+ '()))
(dt "Priority")
(dd ,(assoc-ref build-details "priority")))
diff --git a/bffe/view/home.scm b/bffe/view/home.scm
index 820f75f..3f3b1de 100644
--- a/bffe/view/home.scm
+++ b/bffe/view/home.scm
@@ -1,8 +1,4 @@
(define-module (bffe view home)
- #:use-module (srfi srfi-1)
- #:use-module (srfi srfi-19)
- #:use-module (ice-9 match)
- #:use-module (ice-9 format)
#:use-module (bffe view util)
#:export (home))
diff --git a/bffe/view/util.scm b/bffe/view/util.scm
index 9b4a676..c6b89b0 100644
--- a/bffe/view/util.scm
+++ b/bffe/view/util.scm
@@ -17,23 +17,15 @@
;;; <http://www.gnu.org/licenses/>.
(define-module (bffe view util)
- #:use-module (guix-data-service config)
- #:use-module (guix-data-service web query-parameters)
#:use-module (guix-data-service web util)
- #:use-module (guix-data-service web html-utils)
#:use-module ((guix-data-service web render) #:prefix guix-data-service:)
#:use-module (ice-9 ftw)
- #:use-module (ice-9 vlist)
#:use-module (ice-9 match)
#:use-module (ice-9 binary-ports)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-19)
#:use-module (srfi srfi-26)
- #:use-module (web uri)
#:use-module (web response)
- #:use-module (texinfo)
- #:use-module (texinfo html)
- #:use-module (json)
#:export (layout
header
form-horizontal-control
diff --git a/guix-dev.scm b/guix-dev.scm
index 2fd1981..183c721 100644
--- a/guix-dev.scm
+++ b/guix-dev.scm
@@ -42,6 +42,38 @@
(gnu packages ruby)
(srfi srfi-1))
+(define guile-knots
+ (let ((commit "e8ab6f23d8611c6ebb308007306a9ec5752cfbf0")
+ (revision "1"))
+ (package
+ (name "guile-knots")
+ (version (git-version "0" revision commit))
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://git.cbaines.net/git/guile/knots")
+ (commit commit)))
+ (sha256
+ (base32
+ "1gbf6g0irjndvbycr3ygi6sh6y19v0h3h45460xgz46p62jiphsp"))
+ (file-name (string-append name "-" version "-checkout"))))
+ (build-system gnu-build-system)
+ (native-inputs
+ (list pkg-config
+ autoconf
+ automake
+ guile-3.0
+ guile-fibers))
+ (inputs
+ (list guile-3.0))
+ (propagated-inputs
+ (list guile-fibers))
+ (home-page "https://git.cbaines.net/guile/knots")
+ (synopsis "Patterns and functionality to use with Guile Fibers")
+ (description
+ "")
+ (license license:gpl3+))))
+
(package
(name "bffe")
(version "0.0.0")
@@ -52,6 +84,7 @@
guix-data-service
guile-json-4
guile-fibers-1.3
+ guile-knots
guile-readline
guile-prometheus
guix-build-coordinator