Still making little progress fixing my stray engine problem.

This commit is contained in:
Yaro Kasear 2025-09-24 16:17:42 -05:00
parent c6165af40e
commit 085905557d
6 changed files with 171 additions and 53 deletions

View file

@ -132,8 +132,19 @@ class CRUDService(Generic[T]):
self._session_factory = session_factory
self.polymorphic = polymorphic
self.supports_soft_delete = hasattr(model, 'is_deleted')
# Cache backend info once. If not provided, derive from session bind.
bind = session_factory().get_bind()
# Derive engine WITHOUT leaking a session/connection
bind = getattr(session_factory, "bind", None)
if bind is None:
tmp_sess = session_factory()
try:
bind = tmp_sess.get_bind()
finally:
try:
tmp_sess.close()
except Exception:
pass
eng: Engine = bind.engine if isinstance(bind, Connection) else cast(Engine, bind)
self.backend = backend or make_backend_info(eng)
@ -147,6 +158,14 @@ class CRUDService(Generic[T]):
return self.session.query(poly), poly
return self.session.query(self.model), self.model
def _debug_bind(self, where: str):
try:
bind = self.session.get_bind()
eng = getattr(bind, "engine", bind)
print(f"SERVICE BIND [{where}]: engine_id={id(eng)} url={getattr(eng, 'url', '?')} session={type(self.session).__name__}")
except Exception as e:
print(f"SERVICE BIND [{where}]: failed to introspect bind: {e}")
def _apply_not_deleted(self, query, root_alias, params) -> Any:
if self.supports_soft_delete and not _is_truthy((params or {}).get("include_deleted")):
return query.filter(getattr(root_alias, "is_deleted") == False)
@ -224,6 +243,7 @@ class CRUDService(Generic[T]):
- forward/backward seek via `key` and `backward`
Returns a SeekWindow with items, first/last keys, order spec, limit, and optional total.
"""
self._debug_bind("seek_window")
session = self.session
query, root_alias = self.get_query()
@ -455,6 +475,7 @@ class CRUDService(Generic[T]):
def get(self, id: int, params=None) -> T | None:
"""Fetch a single row by id with conflict-free eager loading and clean projection."""
self._debug_bind("get")
query, root_alias = self.get_query()
# Defaults so we can build a projection even if params is None
@ -549,6 +570,7 @@ class CRUDService(Generic[T]):
def list(self, params=None) -> list[T]:
"""Offset/limit listing with smart relationship loading and clean projection."""
self._debug_bind("list")
query, root_alias = self.get_query()
# Defaults so we can reference them later even if params is None