From: Michael Tremer Date: Fri, 24 Jan 2025 15:55:15 +0000 (+0000) Subject: jobs: Add a CTE to fetch all currently running jobs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1ea234186129faf9f807bdc145cceed74d947500;p=pbs.git jobs: Add a CTE to fetch all currently running jobs Signed-off-by: Michael Tremer --- diff --git a/src/buildservice/builders.py b/src/buildservice/builders.py index 0feff43c..c4fdef14 100644 --- a/src/buildservice/builders.py +++ b/src/buildservice/builders.py @@ -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 diff --git a/src/buildservice/jobs.py b/src/buildservice/jobs.py index 869e1715..4b01cece 100644 --- a/src/buildservice/jobs.py +++ b/src/buildservice/jobs.py @@ -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)