]> git.ipfire.org Git - pbs.git/commitdiff
jobs: Refactor the dispatch algorithm to dispatch mutliple jobs at once
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 27 Apr 2023 15:32:54 +0000 (15:32 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 27 Apr 2023 15:32:54 +0000 (15:32 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/buildservice/jobs.py

index 2c95eff60413622a99f712a0fba0bff9ed4a5c75..fbc273755e1cc8d619df0376262d17c2c2de5e38 100644 (file)
@@ -6,6 +6,7 @@ import gzip
 import hashlib
 import logging
 import os
+import queue
 import shutil
 
 import pakfire
@@ -152,29 +153,46 @@ class Queue(base.Object):
                """
                log.debug("Dispatching jobs...")
 
-               # Process all builders and assign jobs
-               # We prioritize builders with fewer jobs
+               # Create a queue for all builders
+               builders = queue.SimpleQueue()
+
+               # Add all builders to the queue in ascending order of running jobs
                for builder in sorted(self.backend.builders.connections, key=lambda b: len(b.jobs)):
+                       # Skip builders that are not ready
+                       if not builder.is_ready():
+                               continue
+
+                       builders.put(builder)
+
+               # Run for as long as we have unprocessed builders
+               while not builders.empty():
+                       # Take the first builder
+                       builder = builders.get()
+
                        log.debug("  Processing builder %s" % builder)
 
                        with self.backend.db.transaction():
-                               if not builder.is_ready():
-                                       log.debug("  Builder %s is not ready" % builder)
-                                       continue
-
                                # We are ready for a new job
                                job = self.pop(builder)
-                               if job:
-                                       try:
-                                               builder.dispatch_job(job)
 
-                                       # Ignore if the builder suddenly went away
-                                       except BuilderNotOnlineError:
-                                               pass
+                               # If no job could be found for this builder, we simply continue
+                               if not job:
+                                       log.debug("  No jobs processable for %s" % builder)
+                                       continue
+
+                               # If we have a job, we dispatch it to the builder
+                               try:
+                                       builder.dispatch_job(job)
 
+                               # Ignore if the builder suddenly went away
+                               except BuilderNotOnlineError:
                                        continue
 
-                               log.debug("  No jobs processable for %s" % builder)
+                       # If the builder has not any free slots remaining, we put it back in the
+                       # queue to fill it up, but we give priority to builders who have fewer
+                       # jobs to run.
+                       if len(builder.jobs) < builder.max_jobs:
+                               builders.put(builder)
 
                # Auto-scale builders
                await self.backend.builders.autoscale()