Orion Client Utilities

Copyright (C) 2023 Cadence Design Systems, Inc. (Cadence)

class orionclient.utils.Backoff(cap: float = 90.0, base: float = 0.1, backoff_dict: Optional[Dict[int, Tuple[int, int]]] = None)

Utility for Jittered Backoff

Instantiate and call sleep() as many times as necessary

Uses the decorrelated jitter backoff mechanism described here: https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/

@param

default maximum sleep in seconds

Type

cap

@param

default initial sleep in seconds

Type

base

@param

f: status_code –> (base, cap)

Type

backoff_dict

If backoff_dict does not contain a key for a status_code, then the default cap and base are used.

Previously OrionClient was using the same session for interactive and non-interactive sessions this caused problems with timeouts and retries. Now they have seperate sessions, with interactive sessions having shorter timeouts and less retries, and the non-interactive sessions have had their defaults increased.

Given a base backoff of 0.1 seconds, a cap of 90 seconds, and roughly doubling the sleep between each retry 10 attempts will be made in about 192 seconds.

0.2 + 0.4 + 0.8 + 1.6 + 3.2 + 6.4 + 12.8 + 25.6 + 51.2 + 90 = 192.2

A 404 Not Found error will be retried 8 times, or 51 seconds.

A 429 Too Many Requests error will be retried up to 45 times or an hour, whichever is reached first. The additional 35 retries, paced about 90 seconds apart (the cap), will be attempted after the first 10 attempts.

If you wanted to modify the behavior to retry only 300 seconds, you would only need to modify the retry_timeout. 192 seconds for the first 10 retries, leaving 108 seconds left, or 2 more requests (rounding up).

Example:

from requests import session

from orionclient.utils import Backoff


def retry_get_with_backoff(url, attempts=10, request_timeout=10):
    sess = session()
    tries = 0
    sleeper = Backoff()
    resp = None
    while tries < attempts:
        resp = sess.get(url, timeout=request_timeout)
        if not resp.ok:
            tries += 1
            sleeper.sleep()
            continue
        return resp
    return resp

Download code

backoff_requests.py

sleep()

Exponential sleep based on the number of tries

class orionclient.utils.TemporaryPath(suffix='', prefix='tmp', dir=None, delete=True)

Provides a temporary file path, suggested usage is as a context manager.

This is safe to use cross-platform where NamedTemporaryFile is not.

Usage

with TemporaryPath(suffix="bar") as path:
    with open(path, "wb") as ofs:
        ofs.write(b"bytes")