Skip to content

Commit b9a24dc

Browse files
vdusekclaude
andcommitted
fix: correct deadline logic in _wait_for_finish
Make the not-found deadline lazy (starts on the first observed 404 and resets after any successful response) and honor the user-provided wait_duration in the 404 branch. This prevents a single transient 404 from aborting a long poll early, and prevents overruns when the user's deadline is shorter than DEFAULT_WAIT_WHEN_JOB_NOT_EXIST. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3e9fc3d commit b9a24dc

1 file changed

Lines changed: 22 additions & 12 deletions

File tree

src/apify_client/_resource_clients/_resource_client.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,8 @@ def _wait_for_finish(
294294
Raises:
295295
ApifyApiError: If API returns errors other than 404.
296296
"""
297-
now = datetime.now(UTC)
298-
deadline = (now + wait_duration) if wait_duration is not None else None
299-
not_found_deadline = now + DEFAULT_WAIT_WHEN_JOB_NOT_EXIST
297+
deadline = (datetime.now(UTC) + wait_duration) if wait_duration is not None else None
298+
not_found_deadline: datetime | None = None
300299
actor_job: dict = {}
301300

302301
while True:
@@ -317,6 +316,9 @@ def _wait_for_finish(
317316
actor_job_response = ActorJobResponse.model_validate(result)
318317
actor_job = actor_job_response.data.model_dump()
319318

319+
# Reset the not-found streak so a later transient 404 gets its own grace window.
320+
not_found_deadline = None
321+
320322
is_terminal = actor_job_response.data.status in TERMINAL_STATUSES
321323
is_timed_out = deadline is not None and datetime.now(UTC) >= deadline
322324

@@ -326,9 +328,12 @@ def _wait_for_finish(
326328
except ApifyApiError as exc:
327329
catch_not_found_or_throw(exc)
328330

329-
# If there are still not found errors after DEFAULT_WAIT_WHEN_JOB_NOT_EXIST, we give up
330-
# and return None. In such case, the requested record probably really doesn't exist.
331-
if datetime.now(UTC) > not_found_deadline:
331+
now = datetime.now(UTC)
332+
if deadline is not None and now >= deadline:
333+
return None
334+
if not_found_deadline is None:
335+
not_found_deadline = now + DEFAULT_WAIT_WHEN_JOB_NOT_EXIST
336+
elif now > not_found_deadline:
332337
return None
333338

334339
# It might take some time for database replicas to get up-to-date so sleep a bit before retrying
@@ -474,9 +479,8 @@ async def _wait_for_finish(
474479
Raises:
475480
ApifyApiError: If API returns errors other than 404.
476481
"""
477-
now = datetime.now(UTC)
478-
deadline = (now + wait_duration) if wait_duration is not None else None
479-
not_found_deadline = now + DEFAULT_WAIT_WHEN_JOB_NOT_EXIST
482+
deadline = (datetime.now(UTC) + wait_duration) if wait_duration is not None else None
483+
not_found_deadline: datetime | None = None
480484
actor_job: dict = {}
481485

482486
while True:
@@ -497,6 +501,9 @@ async def _wait_for_finish(
497501
actor_job_response = ActorJobResponse.model_validate(result)
498502
actor_job = actor_job_response.data.model_dump()
499503

504+
# Reset the not-found streak so a later transient 404 gets its own grace window.
505+
not_found_deadline = None
506+
500507
is_terminal = actor_job_response.data.status in TERMINAL_STATUSES
501508
is_timed_out = deadline is not None and datetime.now(UTC) >= deadline
502509

@@ -506,9 +513,12 @@ async def _wait_for_finish(
506513
except ApifyApiError as exc:
507514
catch_not_found_or_throw(exc)
508515

509-
# If there are still not found errors after DEFAULT_WAIT_WHEN_JOB_NOT_EXIST, we give up
510-
# and return None. In such case, the requested record probably really doesn't exist.
511-
if datetime.now(UTC) > not_found_deadline:
516+
now = datetime.now(UTC)
517+
if deadline is not None and now >= deadline:
518+
return None
519+
if not_found_deadline is None:
520+
not_found_deadline = now + DEFAULT_WAIT_WHEN_JOB_NOT_EXIST
521+
elif now > not_found_deadline:
512522
return None
513523

514524
# It might take some time for database replicas to get up-to-date so sleep a bit before retrying

0 commit comments

Comments
 (0)