mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 05:30:46 +08:00
Harden runtime budgets: DB pool, CLI concurrency, timeouts, and metrics.
Add shared CLI budget/timeout with force-close, parallel port-traffic dispatch, unified shutdown, bounded audit queue, output/log caps, and /metrics probes. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
2068ce3d04
commit
d56020d84c
23 changed files with 824 additions and 102 deletions
|
|
@ -1,7 +1,10 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import DeclarativeBase, sessionmaker
|
||||
from sqlalchemy.pool import QueuePool
|
||||
|
||||
from .config import settings
|
||||
|
||||
|
|
@ -10,7 +13,26 @@ class Base(DeclarativeBase):
|
|||
pass
|
||||
|
||||
|
||||
engine = create_engine(settings.database_url, future=True, pool_pre_ping=True)
|
||||
def _engine_kwargs() -> dict[str, Any]:
|
||||
url = str(settings.database_url or "")
|
||||
kwargs: dict[str, Any] = {"future": True, "pool_pre_ping": True}
|
||||
# SQLite (tests / local) does not use QueuePool the same way.
|
||||
if url.startswith("sqlite"):
|
||||
kwargs["connect_args"] = {"check_same_thread": False}
|
||||
return kwargs
|
||||
kwargs.update(
|
||||
{
|
||||
"poolclass": QueuePool,
|
||||
"pool_size": max(1, int(getattr(settings, "db_pool_size", 20) or 20)),
|
||||
"max_overflow": max(0, int(getattr(settings, "db_max_overflow", 20) or 20)),
|
||||
"pool_recycle": max(60, int(getattr(settings, "db_pool_recycle_sec", 1800) or 1800)),
|
||||
"pool_timeout": max(1, int(getattr(settings, "db_pool_timeout_sec", 30) or 30)),
|
||||
}
|
||||
)
|
||||
return kwargs
|
||||
|
||||
|
||||
engine = create_engine(settings.database_url, **_engine_kwargs())
|
||||
SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False, expire_on_commit=False)
|
||||
|
||||
|
||||
|
|
@ -20,3 +42,26 @@ def get_db():
|
|||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def db_pool_status() -> dict[str, Any]:
|
||||
"""Best-effort QueuePool snapshot for readiness / metrics."""
|
||||
pool = getattr(engine, "pool", None)
|
||||
if pool is None:
|
||||
return {"backend": "none"}
|
||||
out: dict[str, Any] = {"backend": type(pool).__name__}
|
||||
for key, meth in (
|
||||
("size", "size"),
|
||||
("checked_in", "checkedin"),
|
||||
("checked_out", "checkedout"),
|
||||
("overflow", "overflow"),
|
||||
):
|
||||
fn = getattr(pool, meth, None)
|
||||
if callable(fn):
|
||||
try:
|
||||
out[key] = int(fn())
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
out["pool_size_cfg"] = int(getattr(settings, "db_pool_size", 20) or 20)
|
||||
out["max_overflow_cfg"] = int(getattr(settings, "db_max_overflow", 20) or 20)
|
||||
return out
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue