Skip to content

Commit 00e8621

Browse files
vdusekclaude
andauthored
fix: prevent infinite loop in _wait_for_finish on persistent 404s (#619)
## Summary - `_wait_for_finish` could spin indefinitely when polling a non-existent job - `seconds_elapsed` was only updated inside the `try` block (on success), so on persistent 404 errors the timeout check `seconds_elapsed > 3` always evaluated as `0 > 3 = False` - Moved the `seconds_elapsed` update into a `finally` block so it is always updated regardless of success or failure (both sync and async variants) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1030dab commit 00e8621

File tree

1 file changed

+6
-2
lines changed

1 file changed

+6
-2
lines changed

src/apify_client/clients/base/actor_job_base_client.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ def _wait_for_finish(self, wait_secs: int | None = None) -> dict | None:
3939
)
4040
job = parse_date_fields(pluck_data(response.json()))
4141

42-
seconds_elapsed = math.floor((datetime.now(timezone.utc) - started_at).total_seconds())
4342
if ActorJobStatus(job['status']).is_terminal or (
4443
wait_secs is not None and seconds_elapsed >= wait_secs
4544
):
@@ -57,6 +56,9 @@ def _wait_for_finish(self, wait_secs: int | None = None) -> dict | None:
5756
if seconds_elapsed > DEFAULT_WAIT_WHEN_JOB_NOT_EXIST_SEC:
5857
return None
5958

59+
finally:
60+
seconds_elapsed = math.floor((datetime.now(timezone.utc) - started_at).total_seconds())
61+
6062
# It might take some time for database replicas to get up-to-date so sleep a bit before retrying
6163
time.sleep(0.25)
6264

@@ -93,7 +95,6 @@ async def _wait_for_finish(self, wait_secs: int | None = None) -> dict | None:
9395
)
9496
job = parse_date_fields(pluck_data(response.json()))
9597

96-
seconds_elapsed = math.floor((datetime.now(timezone.utc) - started_at).total_seconds())
9798
if ActorJobStatus(job['status']).is_terminal or (
9899
wait_secs is not None and seconds_elapsed >= wait_secs
99100
):
@@ -111,6 +112,9 @@ async def _wait_for_finish(self, wait_secs: int | None = None) -> dict | None:
111112
if seconds_elapsed > DEFAULT_WAIT_WHEN_JOB_NOT_EXIST_SEC:
112113
return None
113114

115+
finally:
116+
seconds_elapsed = math.floor((datetime.now(timezone.utc) - started_at).total_seconds())
117+
114118
# It might take some time for database replicas to get up-to-date so sleep a bit before retrying
115119
await asyncio.sleep(0.25)
116120

0 commit comments

Comments
 (0)