fix(cpg): end an engine session with the transaction that owns it (M2)

The first session-enabled replay produced correct detections and no speedup,
reporting session_query_failed:census:session_request_failed on both sides. A
targeted probe ruled out the sequence I suspected: an overlay followed by a census
in one session both answer correctly, with the census confirming the overlays were
saved.

What the probe exposed instead is a leak. A build runs on a copy of the backend, so
the session started during the build belonged to that copy and was never closed,
leaving a JVM holding the configured 2 GB heap for the life of the process. Two
builds per transaction meant two of them, which is enough to exhaust a 3 GB
container and make every later request fail. It also matches the host running out
of memory during these runs.

The build now closes any session its copy started, and the driver ends the session
with the transaction, since that is what transaction-owned means. Controls cover
both: a build leaves nothing alive on the copy that started it, and a completed
scan closes the backend's session. Closing never fails a scan that found things.

This is a genuine defect found by measurement rather than by the suite, which
passed throughout. Whether it was the whole cause of the census failure is not yet
established; the next session-enabled run will say.

1,399 tests passed, nine skipped. Rollout stays NO-GO.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
Marius Ciepluch
2026-09-16 21:15:00 +02:00
co-authored by Claude Opus 5
parent d2362cd18d
commit 566b862b0a
3 changed files with 43 additions and 1 deletions
+9
View File
@@ -186,6 +186,15 @@ def scan_repository(
finally:
for cpg in owned:
_dispose(cpg)
# An engine session belongs to the transaction, so it ends with the transaction. Leaving it
# open leaks a JVM holding the configured heap, which is how the first session-enabled run
# exhausted its container and made every later request fail.
close = getattr(backend, "close_session", None)
if callable(close):
try:
close()
except Exception as error: # noqa: BLE001 -- tidying up must not fail a completed scan
logger.warning("could not end the engine session: %s", error)
diagnostics = list(result.degradations)
if execution_budget is not None:
if client is not None: