]> git.ipfire.org Git - pbs.git/commitdiff
jobs: Add a CTE to fetch all currently running jobs
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 24 Jan 2025 15:55:15 +0000 (15:55 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 24 Jan 2025 15:55:15 +0000 (15:55 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/buildservice/builders.py
src/buildservice/jobs.py

index 0feff43c8338036c4f1fcbfd799251b94957fce5..c4fdef1479c20041536d0bdec9dffbc020b022a1 100644 (file)
@@ -490,15 +490,6 @@ class Builder(database.Base, database.BackendMixin, database.SoftDeleteMixin):
 
                return False
 
-       def is_idle(self):
-               """
-                       Return True if the builder has no active jobs
-               """
-               if self.jobs:
-                       return False
-
-               return True
-
        # Maintenance
 
        maintenance = Column(Boolean, nullable=False, default=False)
@@ -543,34 +534,73 @@ class Builder(database.Base, database.BackendMixin, database.SoftDeleteMixin):
 
        # Running Jobs
 
-       async def get_running_jobs(self):
-               stmt = (
+       @functools.cached_property
+       def running_jobs(self):
+               """
+                       A CTE with all jobs currently running on this builder
+               """
+               return (
                        sqlalchemy
                        .select(
                                jobs.Job,
                        )
+                       .select_from(
+                               self.backend.jobs.running_jobs,
+                       )
                        .where(
-                               jobs.Job.deleted_at == None,
-                               jobs.Job.started_at != None,
-                               jobs.Job.finished_at == None,
                                jobs.Job.builder == self,
                        )
-                       .order_by(
-                               jobs.Job.started_at.desc(),
+                       .cte("builder_running_jobs")
+               )
+
+       async def get_running_jobs(self):
+               """
+                       Returns the currently running jobs
+               """
+               stmt = (
+                       sqlalchemy
+                       .select(
+                               jobs.Job,
+                       )
+                       .select_from(
+                               self.running_jobs,
                        )
                )
 
                return await self.db.fetch_as_list(stmt)
 
+       async def num_running_jobs(self):
+               """
+                       Returns the number of currently running jobs
+               """
+               stmt = (
+                       sqlalchemy
+                       .select(
+                               sqlalchemy.func.count().label("running_jobs"),
+                       )
+                       .select_from(
+                               self.running_jobs,
+                       )
+               )
+
+               # Run the query
+               return await self.db.select_one(stmt, "running_jobs") or 0
+
        # Max Jobs
 
        max_jobs = Column(Integer, nullable=False, default=1)
 
-       def is_full(self):
+       async def is_full(self):
                """
                        Returns True if the builder has enough jobs running
                """
-               return len(self.jobs) >= self.max_jobs
+               return await self.num_running_jobs() >= self.max_jobs
+
+       async def is_idle(self):
+               """
+                       Return True if the builder has no active jobs
+               """
+               return await self.num_running_jobs() == 0
 
        # Name
 
index 869e1715435dc94df36a7d859e9fef846a352d20..4b01cece0b9453105223917f040be7af04bbb8df 100644 (file)
@@ -77,13 +77,16 @@ class Jobs(base.Object):
 
                return await self.db.fetch_one(stmt)
 
-       def get_running(self):
+       @functools.cached_property
+       def running_jobs(self):
                """
-                       Returns all currently running jobs
+                       Returns a CTE with all currently running jobs
                """
-               stmt = (
+               return (
                        sqlalchemy
-                       .select(Job)
+                       .select(
+                               Job,
+                       )
                        .where(
                                Job.deleted_at == None,
                                Job.started_at != None,
@@ -92,6 +95,21 @@ class Jobs(base.Object):
                        .order_by(
                                Job.started_at.desc(),
                        )
+                       .cte("running_jobs")
+               )
+
+       def get_running(self):
+               """
+                       Returns all currently running jobs
+               """
+               stmt = (
+                       sqlalchemy
+                       .select(
+                               Job,
+                       )
+                       .select_from(
+                               self.running_jobs,
+                       )
                )
 
                return self.backend.db.fetch(stmt)