From 0d9ebc9cc7760ccfceb4b454e794f96ff32d626d Mon Sep 17 00:00:00 2001 From: Travis Herbranson Date: Sun, 24 May 2026 23:33:13 -0400 Subject: [PATCH] embeddings: register pool close() at interpreter exit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this, every `second-brain process` run prints couldn't stop thread 'pool-1-worker-N' within 5.0 seconds during interpreter shutdown — psycopg_pool's background workers don't get a clean stop signal before Python's threading shutdown deadline. Registering close_pool via atexit the first time we open the pool fixes it without changing any API. `close_pool` is already idempotent, so the explicit teardown path in the smoke test (which calls it directly) and the atexit path coexist safely. --- src/second_brain/embeddings/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/second_brain/embeddings/__init__.py b/src/second_brain/embeddings/__init__.py index 61b43b9..c11ea5d 100644 --- a/src/second_brain/embeddings/__init__.py +++ b/src/second_brain/embeddings/__init__.py @@ -23,6 +23,7 @@ index, not authoritative state. from __future__ import annotations +import atexit import logging import os from typing import Any @@ -73,6 +74,11 @@ def _get_pool() -> ConnectionPool | None: if not dsn: return None _pool = ConnectionPool(dsn, min_size=1, max_size=4, open=True, timeout=10) + # Make sure the pool's worker threads get a clean shutdown when the + # interpreter exits; without this psycopg_pool prints + # "couldn't stop thread pool-1-worker-N within 5.0 seconds" on every + # `second-brain process` run. + atexit.register(close_pool) return _pool