diff --git a/modules/connectors/connectorDbPostgre.py b/modules/connectors/connectorDbPostgre.py index 115f25e4..6dca1db9 100644 --- a/modules/connectors/connectorDbPostgre.py +++ b/modules/connectors/connectorDbPostgre.py @@ -233,6 +233,31 @@ _BORROW_WAIT_TIMEOUT_S = 30.0 _BORROW_WAIT_BACKOFF_S = 0.05 _shuttingDown = False +# Tables whose schema has been verified/created in this process. Avoids repeating +# two information_schema round-trips on every getRecordset() — under concurrent +# load (pool tests: 20×50 reads) that was the dominant latency source. +_ensuredTables: set[tuple[str, str, str]] = set() +_ensuredTablesLock = threading.Lock() + + +def _tableEnsureCacheKey(dbHost: str, dbDatabase: str, table: str) -> tuple[str, str, str]: + return (dbHost, dbDatabase, table.lower()) + + +def _isTableEnsured(key: tuple[str, str, str]) -> bool: + with _ensuredTablesLock: + return key in _ensuredTables + + +def _markTableEnsured(key: tuple[str, str, str]) -> None: + with _ensuredTablesLock: + _ensuredTables.add(key) + + +def _clearEnsuredTablesCache() -> None: + with _ensuredTablesLock: + _ensuredTables.clear() + def _resolvePoolMax() -> int: """Pool size is configurable via `DB_POOL_MAX_CONN` (default 20).""" @@ -324,6 +349,7 @@ def closeAllPools() -> None: """ global _shuttingDown _shuttingDown = True + _clearEnsuredTablesCache() _PoolRegistry.closeAll() @@ -791,10 +817,19 @@ class DatabaseConnector: def _ensureTableExists(self, model_class: type) -> bool: """Ensures a table exists, creates it if it doesn't.""" table = model_class.__name__ + cache_key = _tableEnsureCacheKey( + self.dbHost, + self.dbDatabase, + self._systemTableName if table == "SystemTable" else table, + ) + if _isTableEnsured(cache_key): + return True if table == "SystemTable": - # Handle system table specially - it uses _system as the actual table name - return self._ensureSystemTableExists() + ok = self._ensureSystemTableExists() + if ok: + _markTableEnsured(cache_key) + return ok try: with self.borrowConn() as conn: @@ -904,6 +939,7 @@ class DatabaseConnector: logger.warning( f"Could not ensure columns for existing table '{table}': {ensure_err}" ) + _markTableEnsured(cache_key) return True except Exception as e: logger.error(f"Error ensuring table {table} exists: {e}")