From c71daefd7f524d5ae335a5f83456d888fc3d7126 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 14 Jul 2025 19:03:42 +0200 Subject: [PATCH] Makes test_execution_limit_group_throttle_wait pass Makes test_jobs_decorator.py::test_execution_limit_group_throttle_wait pass even when using group locks. --- supervisor/jobs/decorator.py | 17 ++--------------- supervisor/jobs/job_group.py | 9 +++++---- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/supervisor/jobs/decorator.py b/supervisor/jobs/decorator.py index bef6b89f5..8bd2f6ea3 100644 --- a/supervisor/jobs/decorator.py +++ b/supervisor/jobs/decorator.py @@ -111,7 +111,7 @@ class Job(CoreSysAttributes): JobExecutionLimit.GROUP_WAIT: (JobConcurrency.GROUP_QUEUE, None), JobExecutionLimit.GROUP_THROTTLE: (None, JobThrottle.GROUP_THROTTLE), JobExecutionLimit.GROUP_THROTTLE_WAIT: ( - JobConcurrency.QUEUE, # Seems a bit counter intuitive, but GROUP_QUEUE deadlocks tests/jobs/test_job_decorator.py::test_execution_limit_group_throttle_wait + JobConcurrency.GROUP_QUEUE, JobThrottle.GROUP_THROTTLE, ), JobExecutionLimit.GROUP_THROTTLE_RATE_LIMIT: ( @@ -148,19 +148,6 @@ class Job(CoreSysAttributes): ) self._rate_limited_calls = {} - if self.throttle in ( - JobThrottle.GROUP_THROTTLE, - JobThrottle.GROUP_RATE_LIMIT, - ) and self.concurrency in ( - JobConcurrency.GROUP_REJECT, - JobConcurrency.GROUP_QUEUE, - ): - # We cannot release group locks when Job is not running (e.g. throttled) - # which makes these combinations impossible to use currently. - raise RuntimeError( - f"Job {self.name} is using group throttling ({self.throttle}) with group concurrency ({self.concurrency}), which is not allowed!" - ) - @property def throttle_max_calls(self) -> int: """Return max calls for throttle.""" @@ -505,7 +492,7 @@ class Job(CoreSysAttributes): JobConcurrency.GROUP_REJECT, JobConcurrency.GROUP_QUEUE, ): - if job_group and job_group.has_lock: + if job_group: job_group.release() async def _handle_concurrency_control( diff --git a/supervisor/jobs/job_group.py b/supervisor/jobs/job_group.py index 4dece17e3..8d599057b 100644 --- a/supervisor/jobs/job_group.py +++ b/supervisor/jobs/job_group.py @@ -3,7 +3,7 @@ from asyncio import Lock from ..coresys import CoreSys, CoreSysAttributes -from ..exceptions import JobException, JobGroupExecutionLimitExceeded +from ..exceptions import JobGroupExecutionLimitExceeded from . import SupervisorJob @@ -70,10 +70,11 @@ class JobGroup(CoreSysAttributes): self._active_job = job def release(self) -> None: - """Release the lock for the group or return it to parent.""" - if not self.has_lock: - raise JobException("Cannot release as caller does not own lock") + """Release the lock for the group or return it to parent. + It is the callers responsibility to ensure that the lock is only released + when the lock is actually being held. + """ if self._parent_jobs: self._active_job = self._parent_jobs.pop() else: