Skip to content

Commit c9a4c6c

Browse files
committed
Handle polling timeouts directrly
1 parent 9ef2314 commit c9a4c6c

File tree

3 files changed

+46
-23
lines changed

3 files changed

+46
-23
lines changed

src/gradient/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
UnprocessableEntityError,
3737
APIResponseValidationError,
3838
IndexingJobError,
39+
IndexingJobTimeoutError,
3940
)
4041
from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient
4142
from ._utils._logs import setup_logging as _setup_logging
@@ -67,6 +68,7 @@
6768
"RateLimitError",
6869
"InternalServerError",
6970
"IndexingJobError",
71+
"IndexingJobTimeoutError",
7072
"Timeout",
7173
"RequestOptions",
7274
"Client",

src/gradient/_exceptions.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"RateLimitError",
1717
"InternalServerError",
1818
"IndexingJobError",
19+
"IndexingJobTimeoutError",
1920
]
2021

2122

@@ -111,11 +112,25 @@ class InternalServerError(APIStatusError):
111112

112113
class IndexingJobError(GradientError):
113114
"""Raised when an indexing job fails, encounters an error, or is cancelled."""
114-
115+
115116
uuid: str
116117
phase: str
117-
118+
118119
def __init__(self, message: str, *, uuid: str, phase: str) -> None:
119120
super().__init__(message)
120121
self.uuid = uuid
121122
self.phase = phase
123+
124+
125+
class IndexingJobTimeoutError(GradientError):
126+
"""Raised when polling for an indexing job times out."""
127+
128+
uuid: str
129+
phase: str
130+
timeout: int
131+
132+
def __init__(self, message: str, *, uuid: str, phase: str, timeout: int) -> None:
133+
super().__init__(message)
134+
self.uuid = uuid
135+
self.phase = phase
136+
self.timeout = timeout

src/gradient/resources/knowledge_bases/indexing_jobs.py

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import httpx
88

99
from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
10-
from ..._exceptions import IndexingJobError
10+
from ..._exceptions import IndexingJobError, IndexingJobTimeoutError
1111
from ..._utils import maybe_transform, async_maybe_transform
1212
from ..._compat import cached_property
1313
from ..._resource import SyncAPIResource, AsyncAPIResource
@@ -301,14 +301,14 @@ def wait_for_completion(
301301
The final IndexingJobRetrieveResponse when the job completes successfully.
302302
303303
Raises:
304-
TimeoutError: If the job doesn't complete within the specified timeout.
304+
IndexingJobTimeoutError: If the job doesn't complete within the specified timeout.
305305
IndexingJobError: If the job fails, errors, or is cancelled.
306306
"""
307307
if not uuid:
308308
raise ValueError(f"Expected a non-empty value for `uuid` but received {uuid!r}")
309309

310310
start_time = time.time()
311-
311+
312312
while True:
313313
response = self.retrieve(
314314
uuid,
@@ -321,11 +321,11 @@ def wait_for_completion(
321321
# Check if job is in a terminal state
322322
if response.job and response.job.phase:
323323
phase = response.job.phase
324-
324+
325325
# Success state
326326
if phase == "BATCH_JOB_PHASE_SUCCEEDED":
327327
return response
328-
328+
329329
# Failure states
330330
if phase == "BATCH_JOB_PHASE_FAILED":
331331
raise IndexingJobError(
@@ -335,31 +335,34 @@ def wait_for_completion(
335335
uuid=uuid,
336336
phase=phase,
337337
)
338-
338+
339339
if phase == "BATCH_JOB_PHASE_ERROR":
340340
raise IndexingJobError(
341341
f"Indexing job {uuid} encountered an error",
342342
uuid=uuid,
343343
phase=phase,
344344
)
345-
345+
346346
if phase == "BATCH_JOB_PHASE_CANCELLED":
347347
raise IndexingJobError(
348348
f"Indexing job {uuid} was cancelled",
349349
uuid=uuid,
350350
phase=phase,
351351
)
352-
352+
353353
# Still in progress (UNKNOWN, PENDING, or RUNNING)
354354
# Check timeout
355355
if timeout is not None:
356356
elapsed = time.time() - start_time
357357
if elapsed >= timeout:
358-
raise TimeoutError(
358+
raise IndexingJobTimeoutError(
359359
f"Indexing job {uuid} did not complete within {timeout} seconds. "
360-
f"Current phase: {phase}"
360+
f"Current phase: {phase}",
361+
uuid=uuid,
362+
phase=phase,
363+
timeout=timeout,
361364
)
362-
365+
363366
# Wait before next poll
364367
time.sleep(poll_interval)
365368

@@ -633,14 +636,14 @@ async def wait_for_completion(
633636
The final IndexingJobRetrieveResponse when the job completes successfully.
634637
635638
Raises:
636-
TimeoutError: If the job doesn't complete within the specified timeout.
639+
IndexingJobTimeoutError: If the job doesn't complete within the specified timeout.
637640
IndexingJobError: If the job fails, errors, or is cancelled.
638641
"""
639642
if not uuid:
640643
raise ValueError(f"Expected a non-empty value for `uuid` but received {uuid!r}")
641644

642645
start_time = time.time()
643-
646+
644647
while True:
645648
response = await self.retrieve(
646649
uuid,
@@ -653,11 +656,11 @@ async def wait_for_completion(
653656
# Check if job is in a terminal state
654657
if response.job and response.job.phase:
655658
phase = response.job.phase
656-
659+
657660
# Success state
658661
if phase == "BATCH_JOB_PHASE_SUCCEEDED":
659662
return response
660-
663+
661664
# Failure states
662665
if phase == "BATCH_JOB_PHASE_FAILED":
663666
raise IndexingJobError(
@@ -667,31 +670,34 @@ async def wait_for_completion(
667670
uuid=uuid,
668671
phase=phase,
669672
)
670-
673+
671674
if phase == "BATCH_JOB_PHASE_ERROR":
672675
raise IndexingJobError(
673676
f"Indexing job {uuid} encountered an error",
674677
uuid=uuid,
675678
phase=phase,
676679
)
677-
680+
678681
if phase == "BATCH_JOB_PHASE_CANCELLED":
679682
raise IndexingJobError(
680683
f"Indexing job {uuid} was cancelled",
681684
uuid=uuid,
682685
phase=phase,
683686
)
684-
687+
685688
# Still in progress (UNKNOWN, PENDING, or RUNNING)
686689
# Check timeout
687690
if timeout is not None:
688691
elapsed = time.time() - start_time
689692
if elapsed >= timeout:
690-
raise TimeoutError(
693+
raise IndexingJobTimeoutError(
691694
f"Indexing job {uuid} did not complete within {timeout} seconds. "
692-
f"Current phase: {phase}"
695+
f"Current phase: {phase}",
696+
uuid=uuid,
697+
phase=phase,
698+
timeout=timeout,
693699
)
694-
700+
695701
# Wait before next poll
696702
await asyncio.sleep(poll_interval)
697703

0 commit comments

Comments
 (0)