Skip to content

Commit 1ff97e6

Browse files
authored
Merge pull request #12 from Zipstack/feat/UN-3230-FEAT_implement_backoff_retry_mechanism
UN-3230 [FEAT] Implement back-off retry mechanism for API deployment client
2 parents 2511336 + c2f9df2 commit 1ff97e6

File tree

14 files changed

+1940
-992
lines changed

14 files changed

+1940
-992
lines changed

.github/workflows/main.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@ jobs:
1717
with:
1818
ref: ${{ github.event.release.tag_name }}
1919

20-
- name: Setup PDM
21-
uses: pdm-project/setup-pdm@v4
20+
- name: Install uv
21+
uses: astral-sh/setup-uv@v7
2222
with:
23-
python-version: 3.11
24-
version: 2.10.0
23+
python-version: "3.12"
24+
enable-cache: true
25+
26+
- name: Build package
27+
run: uv build
2528

2629
- name: Publish package distributions to PyPI
27-
run: pdm publish
30+
run: uv publish

.gitignore

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,8 @@ ipython_config.py
101101
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102102
#poetry.lock
103103

104-
# pdm
105-
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106-
#pdm.lock
107-
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108-
# in version control.
109-
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
110-
.pdm.toml
111-
.pdm-python
112-
.pdm-build/
113-
114-
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
115-
__pypackages__/
104+
# uv
105+
.python-version
116106

117107
# Celery stuff
118108
celerybeat-schedule

.pre-commit-config.yaml

Lines changed: 11 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
# - Added pkgs feature flag auto generated code to flake8 exclude list
55
# Force all unspecified python hooks to run python 3.10
66
default_language_version:
7-
python: python3.9
7+
python: python3
88
default_stages:
9-
- commit
9+
- pre-commit
1010
repos:
1111
- repo: https://github.com/pre-commit/pre-commit-hooks
1212
rev: v4.5.0
@@ -48,46 +48,14 @@ repos:
4848
hooks:
4949
- id: actionlint-docker
5050
args: [-ignore, 'label ".+" is unknown']
51-
- repo: https://github.com/psf/black
52-
rev: 24.2.0
51+
- repo: https://github.com/astral-sh/ruff-pre-commit
52+
rev: v0.15.1
5353
hooks:
54-
- id: black
55-
args: [--config=pyproject.toml, -l 88]
56-
language: system
57-
exclude: |
58-
(?x)^(
59-
pkgs/unstract-flags/src/unstract/flags/evaluation_.*\.py|
60-
)$
61-
- repo: https://github.com/pycqa/flake8
62-
rev: 7.0.0
63-
hooks:
64-
- id: flake8
65-
args: [--max-line-length=88]
66-
exclude: |
67-
(?x)^(
68-
.*migrations/.*\.py|
69-
unstract-core/tests/.*|
70-
pkgs/unstract-flags/src/unstract/flags/evaluation_.*\.py|
71-
)$
72-
- repo: https://github.com/pycqa/isort
73-
rev: 5.13.2
74-
hooks:
75-
- id: isort
76-
files: "\\.(py)$"
77-
args:
78-
[
79-
"--profile",
80-
"black",
81-
"--filter-files",
82-
--settings-path=pyproject.toml,
83-
]
84-
- repo: https://github.com/hadialqattan/pycln
85-
rev: v2.4.0
86-
hooks:
87-
- id: pycln
88-
args: [--config=pyproject.toml]
54+
- id: ruff
55+
args: [--fix]
56+
- id: ruff-format
8957
- repo: https://github.com/pycqa/docformatter
90-
rev: v1.7.5
58+
rev: v1.7.7
9159
hooks:
9260
- id: docformatter
9361
# - repo: https://github.com/MarcoGorelli/absolufy-imports
@@ -154,7 +122,7 @@ repos:
154122
args: [--disable, MD013]
155123
- id: markdownlint-fix
156124
args: [--disable, MD013]
157-
- repo: https://github.com/pdm-project/pdm
158-
rev: 2.12.3
125+
- repo: https://github.com/astral-sh/uv-pre-commit
126+
rev: 0.10.2
159127
hooks:
160-
- id: pdm-lock-check
128+
- id: uv-lock

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ Then, create an instance of the `APIDeploymentsClient`:
2929
client = APIDeploymentsClient(api_url="url", api_key="your_api_key")
3030
```
3131

32+
> **Note:** Pass the raw API key **without** the `"Bearer "` prefix — the client adds it automatically.
33+
3234
Now, you can use the client to interact with the Unstract API deployments API:
3335

3436
```python
@@ -61,10 +63,42 @@ except APIDeploymentsClientException as e:
6163

6264
## Parameter Details
6365

66+
`api_url`: The URL of the Unstract API deployment.
67+
`api_key`: Your raw API key. **Do not** include the `"Bearer "` prefix — the client adds it automatically.
6468
`api_timeout`: Set a timeout for API requests, e.g., `api_timeout=10`.
6569
`logging_level`: Set logging verbosity (e.g., "`DEBUG`").
6670
`include_metadata`: If set to `True`, the response will include additional metadata (cost, tokens consumed and context) for each call made by the Prompt Studio exported tool.
6771

72+
## Retry Configuration
73+
74+
The client includes built-in exponential backoff retry with the following behavior:
75+
76+
- **Async mode** (`api_timeout=0`): POST requests are retried on transient failures (5xx, 429) and connection errors, since the server returns immediately after queuing.
77+
- **Sync mode** (`api_timeout > 0`, the default): POST requests are **not** retried, because the server blocks during processing — a failure may mean the request was processed but the response was lost.
78+
- **Status polling** (`check_execution_status`): GET requests are always retried, as they are idempotent.
79+
80+
Retries are enabled by default and can be customized:
81+
82+
```python
83+
client = APIDeploymentsClient(
84+
api_url="url",
85+
api_key="your_api_key",
86+
max_retries=4, # Max retry attempts (default: 4, set to 0 to disable)
87+
initial_delay=2.0, # Initial delay in seconds (default: 2.0)
88+
max_delay=60.0, # Maximum delay cap in seconds (default: 60.0)
89+
backoff_factor=2.0, # Multiplier per retry (default: 2.0)
90+
)
91+
```
92+
93+
| Parameter | Default | Description |
94+
|-----------|---------|-------------|
95+
| `max_retries` | `4` | Maximum number of retry attempts. Set to `0` to disable retries. |
96+
| `initial_delay` | `2.0` | Initial delay in seconds before the first retry. |
97+
| `max_delay` | `60.0` | Maximum delay cap in seconds between retries. |
98+
| `backoff_factor` | `2.0` | Multiplier applied to the delay for each subsequent retry. |
99+
100+
The retry logic uses exponential backoff with full jitter and respects the `Retry-After` header on 429 responses.
101+
68102

69103
## Questions and Feedback
70104

0 commit comments

Comments
 (0)