From 97a93ecd8a627b9c4445904abd9890cf084b5fba Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Tue, 17 Feb 2026 14:48:24 +0100 Subject: [PATCH] fix: update seconds_elapsed in finally block to prevent infinite loop in _wait_for_finish When _wait_for_finish polls a job that consistently returns 404, seconds_elapsed was never updated because the update was only inside the try block on success. This caused the timeout check (seconds_elapsed > DEFAULT_WAIT_WHEN_JOB_NOT_EXIST_SEC) to always evaluate as 0 > 3 = False, spinning the loop indefinitely at 250ms intervals. Co-Authored-By: Claude Opus 4.6 --- src/apify_client/clients/base/actor_job_base_client.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/apify_client/clients/base/actor_job_base_client.py b/src/apify_client/clients/base/actor_job_base_client.py index abf7e274..b8d3d0ac 100644 --- a/src/apify_client/clients/base/actor_job_base_client.py +++ b/src/apify_client/clients/base/actor_job_base_client.py @@ -39,7 +39,6 @@ def _wait_for_finish(self, wait_secs: int | None = None) -> dict | None: ) job = parse_date_fields(pluck_data(response.json())) - seconds_elapsed = math.floor((datetime.now(timezone.utc) - started_at).total_seconds()) if ActorJobStatus(job['status']).is_terminal or ( wait_secs is not None and seconds_elapsed >= wait_secs ): @@ -57,6 +56,9 @@ def _wait_for_finish(self, wait_secs: int | None = None) -> dict | None: if seconds_elapsed > DEFAULT_WAIT_WHEN_JOB_NOT_EXIST_SEC: return None + finally: + seconds_elapsed = math.floor((datetime.now(timezone.utc) - started_at).total_seconds()) + # It might take some time for database replicas to get up-to-date so sleep a bit before retrying time.sleep(0.25) @@ -93,7 +95,6 @@ async def _wait_for_finish(self, wait_secs: int | None = None) -> dict | None: ) job = parse_date_fields(pluck_data(response.json())) - seconds_elapsed = math.floor((datetime.now(timezone.utc) - started_at).total_seconds()) if ActorJobStatus(job['status']).is_terminal or ( wait_secs is not None and seconds_elapsed >= wait_secs ): @@ -111,6 +112,9 @@ async def _wait_for_finish(self, wait_secs: int | None = None) -> dict | None: if seconds_elapsed > DEFAULT_WAIT_WHEN_JOB_NOT_EXIST_SEC: return None + finally: + seconds_elapsed = math.floor((datetime.now(timezone.utc) - started_at).total_seconds()) + # It might take some time for database replicas to get up-to-date so sleep a bit before retrying await asyncio.sleep(0.25)