mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-03 09:12:55 +00:00
* feat: postgres tests * feat: mongo cutoff * feat: mongo cutoff * feat: adjust docs and compose files * fix: mini code mongo removals * fix: tests and k8s mongo stuff * feat: test fixes * fix: ruff * fix: vale * Potential fix for pull request finding 'CodeQL / Clear-text logging of sensitive information' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * fix: mini suggestions * vale lint fix 2 * fix: codeql columns thing * fix: test mongo * fix: tests coverage * feat: better tests 4 * feat: more tests * feat: decent coverage * fix: ruff fixes * fix: remove mongo mock * feat: enhance workflow engine and API routes; add document retrieval and source handling * feat: e2e tests * fix: mcp, mongo and more * fix: mini codeql warning * fix: agent chunk view * fix: mini issues * fix: more pg fixes * feat: postgres prep on start * feat: qa tests * fix: mini improvements * fix: tests --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: Siddhant Rai <siddhant.rai.5686@gmail.com>
92 lines
3.2 KiB
Python
92 lines
3.2 KiB
Python
"""SQLAlchemy Core engine factory for the user-data Postgres database.
|
|
|
|
The engine is lazily constructed on first use and cached as a module-level
|
|
singleton. Repositories and the Alembic env module both obtain connections
|
|
through this factory, so pool tuning lives in one place.
|
|
|
|
``POSTGRES_URI`` can be written in any of the common Postgres URI forms::
|
|
|
|
postgres://user:pass@host:5432/docsgpt
|
|
postgresql://user:pass@host:5432/docsgpt
|
|
|
|
Both are accepted and normalized internally to the psycopg3 dialect
|
|
(``postgresql+psycopg://``) by ``application.core.settings``. Operators
|
|
don't need to know about SQLAlchemy dialect prefixes.
|
|
"""
|
|
|
|
from typing import Optional
|
|
|
|
from sqlalchemy import Engine, create_engine
|
|
|
|
from application.core.settings import settings
|
|
|
|
_engine: Optional[Engine] = None
|
|
|
|
|
|
def _resolve_uri() -> str:
|
|
"""Return the Postgres URI for user-data tables.
|
|
|
|
Raises:
|
|
RuntimeError: If ``settings.POSTGRES_URI`` is unset. Callers that
|
|
reach this path without a configured URI have a setup bug — the
|
|
error message points them at the right setting.
|
|
"""
|
|
if not settings.POSTGRES_URI:
|
|
raise RuntimeError(
|
|
"POSTGRES_URI is not configured. Set it in your .env to a "
|
|
"psycopg3 URI such as "
|
|
"'postgresql+psycopg://user:pass@host:5432/docsgpt'."
|
|
)
|
|
return settings.POSTGRES_URI
|
|
|
|
|
|
#: Per-statement wall-clock cap applied to every connection handed out by
|
|
#: the engine. 30s is generous for interactive hot paths (reads under a few
|
|
#: hundred ms are normal) but still catches a runaway query before it
|
|
#: stacks up on PgBouncer or holds locks indefinitely. Override by
|
|
#: rebuilding the engine with a different ``connect_args`` in tests.
|
|
STATEMENT_TIMEOUT_MS = 30_000
|
|
|
|
|
|
def get_engine() -> Engine:
|
|
"""Return the process-wide SQLAlchemy Engine, creating it if needed.
|
|
|
|
The engine applies a server-side ``statement_timeout`` to every
|
|
connection it hands out, so both :func:`db_session` and
|
|
:func:`db_readonly` inherit the same guardrail.
|
|
|
|
Returns:
|
|
A SQLAlchemy ``Engine`` configured with a pooled connection to
|
|
Postgres via psycopg3.
|
|
"""
|
|
global _engine
|
|
if _engine is None:
|
|
_engine = create_engine(
|
|
_resolve_uri(),
|
|
pool_size=10,
|
|
max_overflow=20,
|
|
pool_pre_ping=True, # survive PgBouncer / idle-disconnect recycles
|
|
pool_recycle=1800,
|
|
future=True,
|
|
connect_args={
|
|
# ``-c`` passes a GUC to the backend at connect time. This
|
|
# covers *all* sessions — interactive, Celery, seeder — so
|
|
# no route-handler can opt out by accident.
|
|
"options": f"-c statement_timeout={STATEMENT_TIMEOUT_MS}",
|
|
},
|
|
)
|
|
return _engine
|
|
|
|
|
|
def dispose_engine() -> None:
|
|
"""Dispose the pooled connections and reset the singleton.
|
|
|
|
Called from the Celery ``worker_process_init`` signal so each forked
|
|
worker gets a fresh pool instead of sharing file descriptors with the
|
|
parent process (which corrupts the pool on fork).
|
|
"""
|
|
global _engine
|
|
if _engine is not None:
|
|
_engine.dispose()
|
|
_engine = None
|