Retries
vespa.retries
Retry strategies used across pyvespa.
Every retry policy in the library is defined here, once, as a tenacity
Retrying/AsyncRetrying object. Call sites either wrap a function with
POLICY.wraps (decorator style) or invoke POLICY.copy()(fn, ...) directly.
Both create a fresh copy per call, so the module-level objects are never mutated.
Defining them in one place makes the differences between strategies visible and
deliberate, gives users a documented default they can inspect or adapt via
POLICY.copy(stop=..., wait=...), and gives tests a stable patch target.
QUERY_RETRY = AsyncRetrying(wait=wait_random_exponential(multiplier=1.5, max=60), stop=stop_after_attempt(5))
module-attribute
Default for VespaAsync.query: retry any exception up to 5 attempts with
random exponential backoff. Does not inspect the status code.
DOCV1_RETRY = AsyncRetrying(wait=wait_exponential(multiplier=1), retry=RETRY_ON_503_OR_EXCEPTION, stop=stop_after_attempt(3), retry_error_callback=_return_last_outcome)
module-attribute
Outer layer for async document/v1 operations (feed/get/update/delete): retry
any exception or a 503 response up to 3 attempts. On exhaustion the last
exception is re-raised or the last response is returned, never RetryError.
THROTTLE_RETRY = AsyncRetrying(wait=wait_random_exponential(multiplier=1, max=10), retry=RETRY_ON_429, stop=stop_never)
module-attribute
Inner layer for async document/v1 operations: retry a 429 response.
Deliberately unbounded (stop_never) so that sustained backpressure from
Vespa slows the feed down instead of failing it. feed_async_iterable has
no adaptive throttler, so this is the only backpressure mechanism on that path.
The wait is randomised (uniform between 0 and min(2**n, 10) seconds) so
that many concurrent tasks hitting 429 together do not retry in lockstep.
SYNC_REQUEST_RETRY = Retrying(retry=retry_any(retry_if_exception(is_connection_error), RETRY_ON_429), wait=wait_golden_jitter(), stop=stop_after_attempt(11), retry_error_callback=_return_last_outcome)
module-attribute
Used by every sync data-plane request (VespaSync._request_with_retry):
retry a 429 response or a connection error. The stop is overridden per client
from VespaSync.num_retries_429 (default 10 retries, i.e. 11 attempts).
On exhaustion the last response is returned or the last exception re-raised.
VISIT_RETRY = Retrying(retry=retry_if_exception_type(HTTPError), stop=stop_after_attempt(3))
module-attribute
Per-slice retry in Vespa.visit on top of SYNC_REQUEST_RETRY: retry an
HTTPError raised by raise_for_status up to 3 attempts, no wait.
CONTROL_PLANE_RETRY = Retrying(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, max=3), reraise=True)
module-attribute
VespaCloud control-plane requests: 3 attempts, exponential wait capped at 3s.
URL_VALIDATION_RETRY = Retrying(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=1, max=10), reraise=True)
module-attribute
Validation of external model URLs in vespa.models: 3 attempts, 1-10s wait.
wait_golden_jitter
Bases: wait_base
Wait 0.1 * 1.618**n + uniform(0, 1) seconds, where n is the zero-based
attempt index. Used by the sync client for 429 and connection-error retries.
retry_if_status(*codes)
Retry when the returned response has one of the given HTTP status codes.
Works with any object exposing get_status_code() (VespaResponse) or a
status_code attribute (httpr.Response).
is_connection_error(e)
Check if an exception is a connection-related error.
This handles both requests.ConnectionError and httpr exceptions (RequestError, ConnectError) as well as generic network errors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
e
|
BaseException
|
The exception to check |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if this is a connection/network error, False otherwise |