refactor(db)!: finalize pooled WNDB v2 migration

This commit is contained in:
2026-08-27 17:26:22 +08:00
parent fa188af0b1
commit b74799a39d
105 changed files with 4988 additions and 5565 deletions
+20
View File
@@ -11,6 +11,7 @@ from psycopg_pool import ConnectionPool
from app.core.config import settings
from app.infra.db.project_routing import get_project_pgconn_string
_check_connection = ConnectionPool.check_connection
_pools: OrderedDict[str, ConnectionPool] = OrderedDict()
_pool_conninfo: dict[str, str] = {}
_pool_borrows: dict[str, int] = {}
@@ -21,6 +22,10 @@ _active_project_connection: ContextVar[tuple[str, Connection] | None] = ContextV
"wndb_active_project_connection",
default=None,
)
_active_model_mutation_locks: ContextVar[frozenset[str]] = ContextVar(
"wndb_active_model_mutation_locks",
default=frozenset(),
)
def _close_pool(pool: ConnectionPool) -> None:
@@ -78,6 +83,7 @@ def get_project_pool(name: str) -> ConnectionPool:
min_size=settings.PROJECT_PG_POOL_MIN_SIZE,
max_size=settings.PROJECT_PG_POOL_SIZE + settings.PROJECT_PG_MAX_OVERFLOW,
kwargs={"autocommit": True, "row_factory": dict_row},
check=_check_connection,
open=True,
)
_pools[name] = pool
@@ -140,6 +146,7 @@ def get_admin_pool() -> ConnectionPool:
min_size=settings.PROJECT_PG_POOL_MIN_SIZE,
max_size=settings.PROJECT_PG_POOL_SIZE,
kwargs={"autocommit": True, "row_factory": dict_row},
check=_check_connection,
open=True,
)
_admin_pools[conninfo] = pool
@@ -192,10 +199,12 @@ def project_transaction(name: str) -> Iterator[Connection]:
try:
with pool.connection() as conn:
token = _active_project_connection.set((name, conn))
lock_token = _active_model_mutation_locks.set(frozenset())
try:
with conn.transaction():
yield conn
finally:
_active_model_mutation_locks.reset(lock_token)
_active_project_connection.reset(token)
finally:
with _registry_lock:
@@ -208,6 +217,17 @@ def is_project_transaction_active(name: str) -> bool:
return active is not None and active[0] == name
def is_model_mutation_lock_active(name: str) -> bool:
"""Return whether the current project transaction already owns its model lock."""
return name in _active_model_mutation_locks.get()
def mark_model_mutation_lock_active(name: str) -> None:
"""Record a transaction-scoped advisory lock to avoid duplicate round trips."""
locks = _active_model_mutation_locks.get()
_active_model_mutation_locks.set(locks | {name})
@contextmanager
def admin_connection() -> Iterator[Connection]:
"""Borrow a PostgreSQL administration connection from its pool."""