diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..9f8f13d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,28 @@ +[tool.ruff] +line-length = 120 +target-version = "py312" +[tool.ruff.lint] +select = [ + "E", "F", # pycodestyle errors, pyflakes (unused imports/variables, undefined names) + "I", # import sorting (replaces isort) + "B", # bugbear: likely bugs + "ASYNC", # async mistakes + "RUF006", # un-referenced asyncio.create_task (tasks can be garbage-collected) +] +ignore = ["E501"] + +[tool.ruff.lint.isort] +known-first-party = ["db_module", "metrics_server", "rabbitmq_handler", "secret_manager", + "simple_logger_handler", "uvicorn_logger_config", "validator"] + +[tool.ruff.format] +indent-style = "tab" + +[tool.ruff.lint.flake8-bugbear] +extend-immutable-calls = [ + "fastapi.Depends", + "fastapi.Query", + "fastapi.Header", + "fastapi.Body", + "fastapi.Security", +] \ No newline at end of file diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..92a80f4 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1 @@ +ruff==0.17.0 diff --git a/src/main.py b/src/main.py index 898bf6c..d4dea37 100644 --- a/src/main.py +++ b/src/main.py @@ -106,10 +106,10 @@ async def pull_notifications( ) except (AMQPException, OSError) as e: logger.error(f"[FastAPI] RabbitMQ unavailable for user_id={user_id}: {e}") - raise HTTPException(status_code=503, detail="Message broker unavailable") + raise HTTPException(status_code=503, detail="Message broker unavailable") from e except RuntimeError as e: logger.error(f"[FastAPI] Consumer not ready: {e}") - raise HTTPException(status_code=503, detail="Service not ready") + raise HTTPException(status_code=503, detail="Service not ready") from e logger.info(f"[FastAPI] Retrieved {len(messages)} message(s) for user_id={user_id}") return PullResponse(messages=messages, count=len(messages), has_more=len(messages) >= MAX_MESSAGES) diff --git a/src/metrics_server.py b/src/metrics_server.py index c3fdc9b..15e7fd1 100644 --- a/src/metrics_server.py +++ b/src/metrics_server.py @@ -1,5 +1,5 @@ from fastapi import FastAPI, Response -from prometheus_client import generate_latest, CONTENT_TYPE_LATEST, Counter +from prometheus_client import CONTENT_TYPE_LATEST, Counter, generate_latest metrics_api = FastAPI(title="Metrics Server", description="Prometheus metrics endpoint") diff --git a/src/rabbitmq_handler.py b/src/rabbitmq_handler.py index 2a45e20..5d2b19f 100644 --- a/src/rabbitmq_handler.py +++ b/src/rabbitmq_handler.py @@ -78,11 +78,11 @@ class RabbitMQConsumer: - Only one fetch per user runs at a time; different users run concurrently. - Messages are acked after the whole batch has been read, so an error mid-read - puts the batch back on the queue and re-raises. + puts the batch back on the queue and re-raises. - Undecodable messages are rejected without requeue (discarded). - Returns an empty list if nothing is queued. - Delivery is at-most-once towards the client: messages are acked before the - HTTP response is sent. + HTTP response is sent. """ if self._closing: