From 1c0eded074a910f46478bffcd7d7d9bdbdacaabf Mon Sep 17 00:00:00 2001 From: Joe Licata Date: Mon, 19 Jan 2026 21:30:16 +0000 Subject: [PATCH 1/3] chore: Update state archive configuration to reduce TTL - Changed the default value of `STATE_ARCHIVE_TTL_DAYS` from 7 to 1 day in `.env.example`, `CONFIGURATION.md`, and `STATE_PERSISTENCE.md` for clarity and consistency. - Updated the description in the `Settings` class to reflect the new default value. --- .env.example | 4 ++-- docs/CONFIGURATION.md | 2 +- docs/STATE_PERSISTENCE.md | 2 +- src/config/__init__.py | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.env.example b/.env.example index d477502..dc45a80 100644 --- a/.env.example +++ b/.env.example @@ -130,8 +130,8 @@ STATE_CAPTURE_ON_ERROR=false STATE_ARCHIVE_ENABLED=true # Archive to MinIO after this inactivity period (default: 1 hour) STATE_ARCHIVE_AFTER_SECONDS=3600 -# Keep archived states in MinIO for this many days -STATE_ARCHIVE_TTL_DAYS=7 +# Keep archived states in MinIO for this many days (default: 1 day / 24 hours) +STATE_ARCHIVE_TTL_DAYS=1 # How often to check for states to archive STATE_ARCHIVE_CHECK_INTERVAL_SECONDS=300 diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 4cde9c2..70c3a6c 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -263,7 +263,7 @@ Inactive states are automatically archived to MinIO for long-term storage. | -------------------------------------- | ------- | -------------------------------------- | | `STATE_ARCHIVE_ENABLED` | `true` | Enable MinIO cold storage archival | | `STATE_ARCHIVE_AFTER_SECONDS` | `3600` | Archive after this inactivity (1 hour) | -| `STATE_ARCHIVE_TTL_DAYS` | `7` | Keep archives for this many days | +| `STATE_ARCHIVE_TTL_DAYS` | `1` | Keep archives for this many days (24h) | | `STATE_ARCHIVE_CHECK_INTERVAL_SECONDS` | `300` | Archival check frequency (5 min) | ### Security Configuration diff --git a/docs/STATE_PERSISTENCE.md b/docs/STATE_PERSISTENCE.md index eae9018..661f36a 100644 --- a/docs/STATE_PERSISTENCE.md +++ b/docs/STATE_PERSISTENCE.md @@ -121,7 +121,7 @@ When a session resumes after Redis expiry: | -------------------------------------- | ------- | -------------------------------------- | | `STATE_ARCHIVE_ENABLED` | `true` | Enable MinIO archival | | `STATE_ARCHIVE_AFTER_SECONDS` | `3600` | Archive after this inactivity (1 hour) | -| `STATE_ARCHIVE_TTL_DAYS` | `7` | Keep archives for this many days | +| `STATE_ARCHIVE_TTL_DAYS` | `1` | Keep archives for this many days (24h) | | `STATE_ARCHIVE_CHECK_INTERVAL_SECONDS` | `300` | Check frequency (5 minutes) | ### Disabling State Persistence diff --git a/src/config/__init__.py b/src/config/__init__.py index 00f8bda..5e836e5 100644 --- a/src/config/__init__.py +++ b/src/config/__init__.py @@ -287,10 +287,10 @@ class Settings(BaseSettings): description="Archive state to MinIO after this many seconds of inactivity. Default: 1 hour", ) state_archive_ttl_days: int = Field( - default=7, + default=1, ge=1, le=30, - description="Keep archived states in MinIO for this many days. Default: 7 days", + description="Keep archived states in MinIO for N days. Default: 1 (24 hours)", ) state_archive_check_interval_seconds: int = Field( default=300, From 82e56ee935b3576dd31512a0e0463a1dec50cdbb Mon Sep 17 00:00:00 2001 From: Joe Licata Date: Tue, 20 Jan 2026 16:49:53 +0000 Subject: [PATCH 2/3] chore: Update dependencies and Docker base images - Upgraded FastAPI to version 0.128.0 and other dependencies in `requirements.txt` including `requests-unixsocket`, `flake8`, and `python-dotenv`. - Updated Dockerfiles for D, Fortran, and PHP to use Ubuntu 24.04 and PHP 8.5-cli respectively. - Modified error response handling in file upload tests to reflect changes in the API response structure. --- docker/d.Dockerfile | 2 +- docker/fortran.Dockerfile | 2 +- docker/php.Dockerfile | 2 +- requirements.txt | 10 +++++----- src/dependencies/services.py | 1 - tests/integration/test_file_api.py | 6 +++--- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/docker/d.Dockerfile b/docker/d.Dockerfile index 84968e0..a564ca3 100644 --- a/docker/d.Dockerfile +++ b/docker/d.Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1.4 # D execution environment with BuildKit optimizations -FROM ubuntu:22.04 +FROM ubuntu:24.04 ARG BUILD_DATE ARG VERSION diff --git a/docker/fortran.Dockerfile b/docker/fortran.Dockerfile index 15bab2e..a9d160c 100644 --- a/docker/fortran.Dockerfile +++ b/docker/fortran.Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1.4 # Fortran execution environment with BuildKit optimizations -FROM ubuntu:22.04 +FROM ubuntu:24.04 # Prevent interactive prompts during package installation ENV DEBIAN_FRONTEND=noninteractive diff --git a/docker/php.Dockerfile b/docker/php.Dockerfile index ae1d369..8db5c8b 100644 --- a/docker/php.Dockerfile +++ b/docker/php.Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1.4 # PHP execution environment with BuildKit optimizations -FROM php:8.2-cli +FROM php:8.5-cli # Install system dependencies and PHP extensions RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/requirements.txt b/requirements.txt index 4ffaca7..2dcd7ed 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ requests>=2.31.0,<3 # Core API framework -fastapi==0.127.1 +fastapi==0.128.0 uvicorn[standard]==0.40.0 # Data validation and serialization @@ -21,7 +21,7 @@ minio==7.2.20 # Docker client for container management docker==7.1.0 -requests-unixsocket==0.3.0 +requests-unixsocket==0.4.1 # Date/time parsing utilities python-dateutil==2.9.0.post0 @@ -35,11 +35,11 @@ pytest-mock==3.12.0 # Development tools black>=24.3.0 -flake8==6.1.0 +flake8==7.3.0 mypy==1.7.1 # Environment management -python-dotenv==1.0.0 +python-dotenv==1.2.1 # Logging structlog==25.5.0 @@ -52,4 +52,4 @@ Unidecode==1.4.0 psutil==5.9.6 # Stress testing -locust==2.43.0 +locust==2.43.1 diff --git a/src/dependencies/services.py b/src/dependencies/services.py index ce21af2..3532134 100644 --- a/src/dependencies/services.py +++ b/src/dependencies/services.py @@ -72,7 +72,6 @@ def inject_container_pool_to_execution_service(): Called after pool is initialized to wire it into the cached execution service. """ - global _container_pool if _container_pool: execution_service = get_execution_service() execution_service.container_pool = _container_pool diff --git a/tests/integration/test_file_api.py b/tests/integration/test_file_api.py index 6419f4f..67cce2b 100644 --- a/tests/integration/test_file_api.py +++ b/tests/integration/test_file_api.py @@ -203,7 +203,7 @@ def test_upload_blocked_exe_file(self, client, auth_headers): response = client.post("/upload", files=files, headers=auth_headers) assert response.status_code == 415 - assert "File type not allowed" in response.json()["detail"] + assert "File type not allowed" in response.json()["error"] def test_upload_blocked_dll_file(self, client, auth_headers): """Test that .dll files are blocked with 415 status.""" @@ -218,7 +218,7 @@ def test_upload_blocked_dll_file(self, client, auth_headers): response = client.post("/upload", files=files, headers=auth_headers) assert response.status_code == 415 - assert "File type not allowed" in response.json()["detail"] + assert "File type not allowed" in response.json()["error"] def test_upload_blocked_bin_file(self, client, auth_headers): """Test that .bin files are blocked with 415 status.""" @@ -233,7 +233,7 @@ def test_upload_blocked_bin_file(self, client, auth_headers): response = client.post("/upload", files=files, headers=auth_headers) assert response.status_code == 415 - assert "File type not allowed" in response.json()["detail"] + assert "File type not allowed" in response.json()["error"] def test_upload_allowed_txt_file(self, client, auth_headers): """Test that allowed file types still work.""" From 621946325e1911521da367661f795ebd7e94dfb5 Mon Sep 17 00:00:00 2001 From: Joe Licata Date: Tue, 20 Jan 2026 16:55:16 +0000 Subject: [PATCH 3/3] chore: Clean up logger initialization across multiple files - Removed unnecessary blank lines before logger initialization in various modules including main.py, files.py, health.py, auth.py, metrics.py, security.py, file.py, health.py, metrics.py, sqlite_metrics.py, and shutdown.py for improved code readability. --- src/api/files.py | 1 - src/api/health.py | 1 - src/dependencies/auth.py | 1 - src/main.py | 1 - src/middleware/metrics.py | 1 - src/middleware/security.py | 1 - src/services/file.py | 1 - src/services/health.py | 1 - src/services/metrics.py | 1 - src/services/sqlite_metrics.py | 6 ++---- src/utils/shutdown.py | 1 - 11 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/api/files.py b/src/api/files.py index 048beb9..1d0ada1 100644 --- a/src/api/files.py +++ b/src/api/files.py @@ -18,7 +18,6 @@ from ..services.execution.output import OutputProcessor from ..utils.id_generator import generate_session_id - logger = structlog.get_logger(__name__) router = APIRouter() diff --git a/src/api/health.py b/src/api/health.py index 79db3da..0472e11 100644 --- a/src/api/health.py +++ b/src/api/health.py @@ -9,7 +9,6 @@ from ..dependencies.auth import verify_api_key from ..config import settings - logger = structlog.get_logger(__name__) router = APIRouter() diff --git a/src/dependencies/auth.py b/src/dependencies/auth.py index ee69f57..2c32156 100644 --- a/src/dependencies/auth.py +++ b/src/dependencies/auth.py @@ -12,7 +12,6 @@ from ..services.auth import get_auth_service from ..utils.request_helpers import extract_api_key - logger = structlog.get_logger(__name__) security = HTTPBearer(auto_error=False) diff --git a/src/main.py b/src/main.py index 0fab6d6..58e95a6 100644 --- a/src/main.py +++ b/src/main.py @@ -32,7 +32,6 @@ from .utils.logging import setup_logging from .utils.shutdown import setup_graceful_shutdown, shutdown_handler - # Setup logging setup_logging() logger = structlog.get_logger() diff --git a/src/middleware/metrics.py b/src/middleware/metrics.py index 3512d24..e853d61 100644 --- a/src/middleware/metrics.py +++ b/src/middleware/metrics.py @@ -13,7 +13,6 @@ from ..services.metrics import metrics_collector, APIMetrics from ..config import settings - logger = structlog.get_logger(__name__) diff --git a/src/middleware/security.py b/src/middleware/security.py index ee43a7c..68f434b 100644 --- a/src/middleware/security.py +++ b/src/middleware/security.py @@ -14,7 +14,6 @@ from ..services.auth import get_auth_service from ..utils.request_helpers import extract_api_key, get_client_ip - logger = structlog.get_logger(__name__) diff --git a/src/services/file.py b/src/services/file.py index 0eda01d..4b9730f 100644 --- a/src/services/file.py +++ b/src/services/file.py @@ -17,7 +17,6 @@ from ..models import FileInfo, FileUploadRequest from ..utils.id_generator import generate_file_id - logger = structlog.get_logger() diff --git a/src/services/health.py b/src/services/health.py index b09ec3c..8959060 100644 --- a/src/services/health.py +++ b/src/services/health.py @@ -17,7 +17,6 @@ # Local application imports from ..config import settings - logger = structlog.get_logger(__name__) diff --git a/src/services/metrics.py b/src/services/metrics.py index 96de408..33090a7 100644 --- a/src/services/metrics.py +++ b/src/services/metrics.py @@ -16,7 +16,6 @@ # Local application imports from ..config import settings - logger = structlog.get_logger(__name__) diff --git a/src/services/sqlite_metrics.py b/src/services/sqlite_metrics.py index dc80372..2bacc4b 100644 --- a/src/services/sqlite_metrics.py +++ b/src/services/sqlite_metrics.py @@ -646,15 +646,13 @@ async def get_api_keys_list(self) -> List[Dict[str, Any]]: if not self._db: return [] - cursor = await self._db.execute( - """ + cursor = await self._db.execute(""" SELECT DISTINCT api_key_hash, COUNT(*) as usage_count FROM executions GROUP BY api_key_hash ORDER BY usage_count DESC LIMIT 50 - """ - ) + """) return [ {"key_hash": row["api_key_hash"], "usage_count": row["usage_count"]} diff --git a/src/utils/shutdown.py b/src/utils/shutdown.py index 42f93fc..ff6bd2d 100644 --- a/src/utils/shutdown.py +++ b/src/utils/shutdown.py @@ -7,7 +7,6 @@ from ..services.health import health_service from ..services.metrics import metrics_collector - logger = structlog.get_logger(__name__)