Files
unstract/backend/pyproject.toml
Chandrasekharan M 0c0c8c1034 UN-2793 [FEAT] Add retry logic with exponential backoff to SDK1 (#1564)
* UN-2793 [FEAT] Add retry logic with exponential backoff to SDK1

Implemented automatic retry logic for platform and prompt service calls
with configurable exponential backoff, comprehensive test coverage, and
CI integration.

Features:
- Exponential backoff with jitter for transient failures
- Configurable via environment variables (MAX_RETRIES, MAX_TIME, BASE_DELAY, etc.)
- Retries ConnectionError, Timeout, HTTPError (502/503/504), OSError
- 67 tests with 100% pass rate
- CI integration with test reporting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* [SECURITY] Use full commit SHA for sticky-pull-request-comment action

Replace tag reference with full commit SHA for better security:
- marocchino/sticky-pull-request-comment@v2 → @7737449 (v2.9.4)

This prevents potential supply chain attacks where tags could be moved
to point to malicious code. Commit SHAs are immutable.

Fixes SonarQube security hotspot for external GitHub action.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* [FIX] Allow retryable HTTP errors (502/503/504) to propagate for retry

Fixed HTTPError handling in _get_adapter_configuration to check status
codes and re-raise retryable errors (502, 503, 504) so the retry
decorator can handle them. Non-retryable errors are still converted
to SdkError as before.

Changes:
- Check HTTPError status code before converting to SdkError
- Re-raise HTTPError for 502/503/504 to allow retry decorator to retry
- Added parametrized test for all retryable status codes (502, 503, 504)
- All 12 platform tests pass

This fixes a bug where 502/503/504 errors were not being retried
because they were converted to SdkError before the retry decorator
could see them.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* [FIX] Use pytest.approx() for floating point comparisons in tests

Replaced direct equality comparisons (==) with pytest.approx() for
floating point values to avoid precision issues and satisfy SonarQube
code quality check (python:S1244).

Changes in test_retry_utils.py:
- test_exponential_backoff_without_jitter: Use pytest.approx() for 1.0, 2.0, 4.0, 8.0
- test_max_delay_cap: Use pytest.approx() for 5.0

This is the proper way to compare floating point values in tests,
accounting for floating point precision limitations.

All 4 TestCalculateDelay tests pass.

Fixes SonarQube: python:S1244 - Do not perform equality checks with
floating point values.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* minor: Addressed code smells, ruff fixes

* misc: Fixed tox config for sdk1 tests

* misc: Ruff issues fixed

* misc: tox tests fixed

* prompt service lock file for venv

* updated lock files for backend and prompt-service

* UN-2793 [FEAT] Update to unstract-sdk v0.78.0 with retry logic support (#1567)

[FEAT] Update unstract-sdk to v0.78.0 across all services and tools

- Updated unstract-sdk dependency from v0.77.3 to v0.78.0 in all pyproject.toml files
  - Main repository, backend, workers, platform-service, prompt-service
  - filesystem and tool-registry modules
- Updated tool requirements.txt files (structure, classifier, text_extractor)
- Bumped tool versions in properties.json:
  - Structure tool: 0.0.88 → 0.0.89
  - Classifier tool: 0.0.68 → 0.0.69
  - Text extractor tool: 0.0.64 → 0.0.65
- Updated tool versions in backend/sample.env and public_tools.json
- Regenerated all uv.lock files with new SDK version

This update brings in the retry logic with exponential backoff from unstract-sdk v0.78.0

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>

---------

Signed-off-by: Chandrasekharan M <117059509+chandrasekharan-zipstack@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-10-09 10:48:19 +05:30

159 lines
5.4 KiB
TOML

[project]
name = "unstract-backend"
version = "0.0.1"
description = "Unstract backend built with Django to build and schedule ETL pipelines around unstructured data."
authors = [{ name = "Zipstack Inc.", email = "devsupport@zipstack.com" }]
requires-python = ">=3.12,<3.13"
readme = "README.md"
classifiers = [
"Private :: Do Not Upload",
"Framework :: Django",
"Programming Language :: Python",
]
dependencies = [
"Authlib==1.2.1", # For Auth plugins
"boto3~=1.34.0", # For Unstract-cloud-storage
"celery[amqp]>=5.3.4", # For Celery
"flower>=2.0.1", # Celery Monitoring
"cron-descriptor==1.4.0", # For cron string description
"cryptography>=41.0.7",
"django==4.2.1",
"djangorestframework==3.14.0",
"django-cors-headers==4.3.1",
# Pinning django-celery-beat to avoid build issues
"django-celery-beat==2.5.0",
"django-log-request-id>=2.1.0",
"django-redis==5.4.0",
"django-tenants==3.5.0",
"drf-standardized-errors>=0.12.6",
"drf-yasg==1.21.7", # For API docs
"psycopg2-binary==2.9.9",
"python-dotenv==1.0.1",
"python-magic==0.4.27", # For file upload/download
"python-socketio==5.9.0", # For log_events
"social-auth-app-django==5.3.0", # For OAuth
"social-auth-core==4.4.2", # For OAuth
"unstract-sdk[aws,gcs,azure]~=0.78.0",
"azure-identity==1.16.0",
"azure-mgmt-apimanagement==3.0.0",
"croniter>=3.0.3",
"django-filter>=24.3",
"httpx>=0.27.0",
# Hence required to add all indirect local dependencies too here.
"unstract-connectors",
"unstract-core",
"unstract-filesystem",
"unstract-flags",
"unstract-sdk1[aws,gcs,azure]",
"unstract-tool-registry",
"unstract-tool-sandbox",
"unstract-workflow-execution",
"unstract-filesystem",
"google-cloud-recaptcha-enterprise>=1.28.2",
"gunicorn>=23.0.0",
"stripe>=12.5.1",
]
[dependency-groups]
dev = [
"unstract-connectors",
"unstract-core",
"unstract-flags",
"unstract-tool-registry",
"unstract-tool-sandbox",
"unstract-workflow-execution",
"unstract-filesystem",
# For file watching
"inotify>=0.2.10",
"poethepoet>=0.33.1",
"debugpy>=1.8.14",
"pytest>=8.3.5",
"responses>=0.25.7",
"psutil>=7.0.0",
]
test = ["pytest>=8.0.1", "pytest-dotenv==0.5.2"]
deploy = [
"gunicorn~=23.0", # For serving the application
# Keep versions empty and let uv decide version
# since we use no code instrumentation and don't use in code
"opentelemetry-distro",
"opentelemetry-exporter-otlp",
]
[tool.uv.sources]
unstract-connectors = { path = "../unstract/connectors", editable = true }
unstract-core = { path = "../unstract/core", editable = true }
unstract-filesystem = { path = "../unstract/filesystem", editable = true }
unstract-flags = { path = "../unstract/flags", editable = true }
unstract-sdk1 = { path = "../unstract/sdk1", editable = true }
unstract-tool-registry = { path = "../unstract/tool-registry", editable = true }
unstract-tool-sandbox = { path = "../unstract/tool-sandbox", editable = true }
unstract-workflow-execution = { path = "../unstract/workflow-execution", editable = true }
[tool.uv]
constraint-dependencies = [
# (unstract-connectors) To address issue with Python 3.12 and Numpy 2.0
# https://github.com/numpy/numpy/issues/26710
"numpy<2.0.0", "pandas<2.2.0"
]
[tool.pytest.ini_options]
env_files = "test.env" # Load env from particular env file
addopts = "-s"
[tool.poe]
envfile = ".env"
[tool.poe.tasks.backend]
cmd = "./entrypoint.sh"
help = "Runs the Unstract backend (Gunicorn)"
[tool.poe.tasks.migrate-db]
cmd = "uv run manage.py migrate"
help = "Performs DB migrations for Unstract backend"
[tool.poe.tasks.worker]
cmd = "celery -A backend worker --loglevel=info -Q celery --autoscale 4,1"
help = "Runs the Unstract default worker"
[tool.poe.tasks.worker-logging]
cmd = "celery -A backend worker --loglevel=info -Q celery_periodic_logs,celery_log_task_queue --autoscale 4,1"
help = "Runs the Unstract log management worker"
[tool.poe.tasks.worker-api-deployment]
cmd = "celery -A backend worker --loglevel=info -Q celery_api_deployments --autoscale 4,1"
help = "Runs the Unstract API deployment worker"
[tool.poe.tasks.worker-file-processing]
cmd = "celery -A backend.workers.file_processing worker --loglevel=info -Q file_processing --autoscale 4,1"
help = "Runs the Unstract file processing worker"
[tool.poe.tasks.worker-api-file-processing]
cmd = "celery -A backend.workers.file_processing worker --loglevel=info -Q api_file_processing --autoscale 4,1"
help = "Runs the Unstract file processing api worker"
[tool.poe.tasks.worker-file-processing-callback]
cmd = "celery -A backend.workers.file_processing_callback worker --loglevel=info -Q file_processing_callback --autoscale 4,1"
help = "Runs the Unstract file processing callback worker"
[tool.poe.tasks.worker-api-file-processing-callback]
cmd = "celery -A backend.workers.file_processing_callback worker --loglevel=info -Q api_file_processing_callback --autoscale 4,1"
help = "Runs the Unstract api file processing callback worker"
[tool.poe.tasks.flower]
cmd = "celery -A backend flower --port=5555"
help = "Runs the Unstract Celery Monitoring Tool"
[tool.poe.tasks.beat]
cmd = "celery -A backend beat --loglevel=info"
help = "Runs the Unstract Celery Beat service"
# [build-system]
# requires = ["hatchling"]
# build-backend = "hatchling.build"
# [tool.hatch.build.targets.wheel]
# packages = ["unstract"]