Merge pull request #759 from christianlouis/copilot/fix-config-settings-metadata
fix: add missing SETTING_METADATA entries for db pool and upload rate limit settings
This commit is contained in:
@@ -1115,6 +1115,45 @@ class Settings(BaseSettings):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Database Connection Pool Configuration
|
||||||
|
# Controls SQLAlchemy QueuePool behaviour for PostgreSQL/MySQL.
|
||||||
|
# SQLite uses NullPool and ignores these settings.
|
||||||
|
db_pool_size: int = Field(
|
||||||
|
default=5,
|
||||||
|
description="Number of persistent connections kept in the pool. Ignored for SQLite.",
|
||||||
|
)
|
||||||
|
db_max_overflow: int = Field(
|
||||||
|
default=10,
|
||||||
|
description=("Maximum number of connections that can be opened beyond db_pool_size. Ignored for SQLite."),
|
||||||
|
)
|
||||||
|
db_pool_timeout: int = Field(
|
||||||
|
default=30,
|
||||||
|
description="Seconds to wait for a connection from the pool before raising an error. Ignored for SQLite.",
|
||||||
|
)
|
||||||
|
db_pool_recycle: int = Field(
|
||||||
|
default=1800,
|
||||||
|
description=(
|
||||||
|
"Seconds after which a connection is recycled to prevent stale connections. "
|
||||||
|
"Ignored for SQLite. Default: 1800 (30 minutes)."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Per-user upload rate limiting (health-aware limiter)
|
||||||
|
# Controls how many uploads a single user may submit within a sliding window.
|
||||||
|
upload_rate_limit_per_user: int = Field(
|
||||||
|
default=20,
|
||||||
|
description=(
|
||||||
|
"Maximum number of uploads allowed per user within the upload_rate_limit_window. "
|
||||||
|
"The limiter may dynamically reduce this value when Redis queue depth or CPU load is high."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
upload_rate_limit_window: int = Field(
|
||||||
|
default=60,
|
||||||
|
description=(
|
||||||
|
"Sliding window in seconds over which upload_rate_limit_per_user is enforced. Default: 60 seconds."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
# Rate Limiting Configuration (see SECURITY_AUDIT.md and docs/API.md)
|
# Rate Limiting Configuration (see SECURITY_AUDIT.md and docs/API.md)
|
||||||
# Protects against DoS attacks and API abuse
|
# Protects against DoS attacks and API abuse
|
||||||
rate_limiting_enabled: bool = Field(
|
rate_limiting_enabled: bool = Field(
|
||||||
|
|||||||
+15
-1
@@ -10,6 +10,7 @@ from typing import Any
|
|||||||
from sqlalchemy import create_engine, exc
|
from sqlalchemy import create_engine, exc
|
||||||
from sqlalchemy.engine.url import make_url
|
from sqlalchemy.engine.url import make_url
|
||||||
from sqlalchemy.orm import Session, declarative_base, sessionmaker
|
from sqlalchemy.orm import Session, declarative_base, sessionmaker
|
||||||
|
from sqlalchemy.pool import NullPool, QueuePool
|
||||||
|
|
||||||
from app.config import settings
|
from app.config import settings
|
||||||
|
|
||||||
@@ -19,7 +20,20 @@ Base = declarative_base()
|
|||||||
|
|
||||||
# Parse the DATABASE_URL
|
# Parse the DATABASE_URL
|
||||||
DB_URL = settings.database_url
|
DB_URL = settings.database_url
|
||||||
engine = create_engine(DB_URL, connect_args={"check_same_thread": False})
|
_db_url = make_url(DB_URL)
|
||||||
|
if _db_url.get_backend_name() == "sqlite":
|
||||||
|
# SQLite does not benefit from connection pooling; NullPool avoids contention.
|
||||||
|
engine = create_engine(DB_URL, connect_args={"check_same_thread": False}, poolclass=NullPool)
|
||||||
|
else:
|
||||||
|
# PostgreSQL / MySQL / other: use a configurable QueuePool.
|
||||||
|
engine = create_engine(
|
||||||
|
DB_URL,
|
||||||
|
poolclass=QueuePool,
|
||||||
|
pool_size=settings.db_pool_size,
|
||||||
|
max_overflow=settings.db_max_overflow,
|
||||||
|
pool_timeout=settings.db_pool_timeout,
|
||||||
|
pool_recycle=settings.db_pool_recycle,
|
||||||
|
)
|
||||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2557,6 +2557,72 @@ SETTING_METADATA = {
|
|||||||
"required": False,
|
"required": False,
|
||||||
"restart_required": False,
|
"restart_required": False,
|
||||||
},
|
},
|
||||||
|
# Database Connection Pool
|
||||||
|
"db_pool_size": {
|
||||||
|
"category": "Core",
|
||||||
|
"description": (
|
||||||
|
"Number of persistent connections kept in the SQLAlchemy QueuePool. "
|
||||||
|
"Has no effect for SQLite databases. Default: 5."
|
||||||
|
),
|
||||||
|
"type": "integer",
|
||||||
|
"sensitive": False,
|
||||||
|
"required": False,
|
||||||
|
"restart_required": True,
|
||||||
|
},
|
||||||
|
"db_max_overflow": {
|
||||||
|
"category": "Core",
|
||||||
|
"description": (
|
||||||
|
"Maximum extra connections that can be opened beyond db_pool_size. "
|
||||||
|
"Has no effect for SQLite databases. Default: 10."
|
||||||
|
),
|
||||||
|
"type": "integer",
|
||||||
|
"sensitive": False,
|
||||||
|
"required": False,
|
||||||
|
"restart_required": True,
|
||||||
|
},
|
||||||
|
"db_pool_timeout": {
|
||||||
|
"category": "Core",
|
||||||
|
"description": (
|
||||||
|
"Seconds to wait for a connection from the pool before raising an error. "
|
||||||
|
"Has no effect for SQLite databases. Default: 30."
|
||||||
|
),
|
||||||
|
"type": "integer",
|
||||||
|
"sensitive": False,
|
||||||
|
"required": False,
|
||||||
|
"restart_required": True,
|
||||||
|
},
|
||||||
|
"db_pool_recycle": {
|
||||||
|
"category": "Core",
|
||||||
|
"description": (
|
||||||
|
"Seconds after which idle connections are recycled to prevent stale connections. "
|
||||||
|
"Has no effect for SQLite databases. Default: 1800 (30 minutes)."
|
||||||
|
),
|
||||||
|
"type": "integer",
|
||||||
|
"sensitive": False,
|
||||||
|
"required": False,
|
||||||
|
"restart_required": True,
|
||||||
|
},
|
||||||
|
# Per-user upload rate limiting
|
||||||
|
"upload_rate_limit_per_user": {
|
||||||
|
"category": "Security",
|
||||||
|
"description": (
|
||||||
|
"Maximum number of uploads a single user may submit within upload_rate_limit_window seconds. "
|
||||||
|
"The health-aware limiter may reduce this dynamically under high Redis queue depth or CPU load. "
|
||||||
|
"Default: 20."
|
||||||
|
),
|
||||||
|
"type": "integer",
|
||||||
|
"sensitive": False,
|
||||||
|
"required": False,
|
||||||
|
"restart_required": False,
|
||||||
|
},
|
||||||
|
"upload_rate_limit_window": {
|
||||||
|
"category": "Security",
|
||||||
|
"description": ("Sliding window in seconds over which upload_rate_limit_per_user is enforced. Default: 60."),
|
||||||
|
"type": "integer",
|
||||||
|
"sensitive": False,
|
||||||
|
"required": False,
|
||||||
|
"restart_required": False,
|
||||||
|
},
|
||||||
# Rate Limiting
|
# Rate Limiting
|
||||||
"rate_limiting_enabled": {
|
"rate_limiting_enabled": {
|
||||||
"category": "Security",
|
"category": "Security",
|
||||||
|
|||||||
Reference in New Issue
Block a user