Is there an existing issue for this?
Current Behavior
get_retriever() in lettuce/components/embeddings.py (~line 162-179) opens a new SQLAlchemy
session directly from the raw sessionmaker:
return PGVectorQuery(
db_session(), # <-- opens a session, never closed
...
)
This bypasses the get_session() context manager defined in lettuce/omop/db_manager.py
(lines 28-35), which is the safe pattern used everywhere else in the codebase
(search_routes.py, omop_match.py, lettuce-ui/src/ui.py, lettuce-ui/src/search/__init__.py
all use with get_session() as session:).
The session returned by db_session() is stored on PGVectorQuery._connection and used in
run() (embeddings.py:62), but .close() is never called on it anywhere — no with, no
try/finally.
Impact: every call to GET /search/vector-search/{term} and GET /search/ai-search/{term}
(and their UI equivalents) leaks a pooled DB connection. The engine
(lettuce/omop/db_manager.py:23) uses SQLAlchemy's default pool sizing (5 + 10 overflow, no
pool_pre_ping), so under moderate traffic this will exhaust the pool
(QueuePool limit ... reached timeouts / hung requests). It leaks even faster on errors since
there's no finally fallback if query_vector() raises.
Suggested fix direction: have get_retriever() obtain its session via get_session(),
with the connection's lifetime tied to a with block/try-finally owned by the caller, or give
PGVectorQuery/Embeddings a close() guaranteed to run.
Expected Behavior
No response
Steps To Reproduce
No response
Environment
- OS:
- Other environment details:
I'm part of a Project Team
No response
Anything else?
No response
Are you willing to contribute to resolve this issue?
None
Is there an existing issue for this?
Current Behavior
get_retriever()inlettuce/components/embeddings.py(~line 162-179) opens a new SQLAlchemysession directly from the raw
sessionmaker:This bypasses the
get_session()context manager defined inlettuce/omop/db_manager.py(lines 28-35), which is the safe pattern used everywhere else in the codebase
(
search_routes.py,omop_match.py,lettuce-ui/src/ui.py,lettuce-ui/src/search/__init__.pyall use
with get_session() as session:).The session returned by
db_session()is stored onPGVectorQuery._connectionand used inrun()(embeddings.py:62), but.close()is never called on it anywhere — nowith, notry/finally.Impact: every call to
GET /search/vector-search/{term}andGET /search/ai-search/{term}(and their UI equivalents) leaks a pooled DB connection. The engine
(
lettuce/omop/db_manager.py:23) uses SQLAlchemy's default pool sizing (5 + 10 overflow, nopool_pre_ping), so under moderate traffic this will exhaust the pool(
QueuePool limit ... reachedtimeouts / hung requests). It leaks even faster on errors sincethere's no
finallyfallback ifquery_vector()raises.Suggested fix direction: have
get_retriever()obtain its session viaget_session(),with the connection's lifetime tied to a
withblock/try-finallyowned by the caller, or givePGVectorQuery/Embeddingsaclose()guaranteed to run.Expected Behavior
No response
Steps To Reproduce
No response
Environment
I'm part of a Project Team
No response
Anything else?
No response
Are you willing to contribute to resolve this issue?
None