diff --git a/hive/server/db.py b/hive/server/db.py index f8136f7d..b39272b3 100644 --- a/hive/server/db.py +++ b/hive/server/db.py @@ -16,14 +16,6 @@ CACHE_NAMESPACE = "hivemind" -# Per-query execution timeout (milliseconds). PostgreSQL cancels any statement -# running longer than this, immediately releasing the connection back to the -# pool. This is the safety net that prevents a single pathological query (e.g. -# 160s get_discussion lookups) from exhausting the aiopg pool. The pool's -# acquire `timeout` only bounds how long we wait for a free connection, NOT -# query execution time. See connection-pool-exhaustion incident. -STATEMENT_TIMEOUT_MS = 30000 # 30 seconds - # Sentinel value to represent 'record not found' in cache. # Using a string marker that can be easily serialized/deserialized. # This allows us to distinguish between: @@ -105,21 +97,6 @@ def __init__(self): async def init(self, url, redis_url, pool_size=20): """Initialize the aiopg.sa engine.""" conf = make_url(url) - # statement_timeout (ms) cancels runaway queries server-side so a single - # slow query cannot hold a pool connection indefinitely. See note on - # STATEMENT_TIMEOUT_MS above. Passed via the standard libpq `options` - # string (every psycopg2/libpq version accepts this); the newer - # `server_settings` dict is rejected as an invalid DSN option by the - # older psycopg2 shipped in the runtime image. Merge into conf.query - # (rather than a separate kwarg) so a DATABASE_URL that already carries - # an `options=...` query param does not cause a duplicate-keyword error; - # any pre-existing options string is preserved and appended to. - query = dict(conf.query) - timeout_opt = '-c statement_timeout=%d' % STATEMENT_TIMEOUT_MS - if 'options' in query and query['options']: - query['options'] = query['options'] + ' ' + timeout_opt - else: - query['options'] = timeout_opt self.db = await create_engine(user=conf.username, database=conf.database, password=conf.password, @@ -127,7 +104,7 @@ async def init(self, url, redis_url, pool_size=20): port=conf.port, maxsize=pool_size, timeout=10, - **query) + **conf.query) # Lightweight isolated engine (1 connection) for health checks. A short # acquire timeout keeps health checks responsive instead of blocking. self.health_db = await create_engine(user=conf.username, @@ -137,7 +114,7 @@ async def init(self, url, redis_url, pool_size=20): port=conf.port, maxsize=1, timeout=2, - **query) + **conf.query) if redis_url is not None: self.redis_cache = Cache.from_url(redis_url) self.redis_cache.serializer = SafeUniversalSerializer()