Repository navigation
perf(http): monitoring_integration test_connection sites leak _active_requests (pre-#12989 recipe) #12992
Description
Activity
- added 3 commits that reference this issue
on Jul 29, 2026 github-actions commented
on Jul 30, 2026 on Jul 30, 2026 – with GitHub ActionsContributorMore actionsClosed by PR #12996, merged to
Dev_new_guiasade45c09d.Counter fix (the defect):
get_json()/post_json()incremented_active_requestsand never decremented it on the success path. Sinceutilization = _active_requests / _current_pool_sizedrives pool auto-sizing, and deferred session recreation is gated onif self._active_requests == 0, the counter drifting upward meant the pool would grow without cause and never recreate its session. Measured before the fix: 16 after 16 requests; after: 0.Both now route through a
tracked_request()async context manager that decrements infinally, so the release point is the sameasync withthat releases the connection.Convergence guard (why this issue needed more than the fix):
autobot-backend/tests/test_raw_client_session_ceiling_12992.pyasserts an AST-counted ceiling on rawaiohttp.ClientSession(...)constructions, because #12979 could not converge by subtraction — origin gained ~8 new constructions during two in-flight batches. Counting is AST-based, not grep: three textual matches are string literals (a docstring example, aprint(), and a regex replacement template) and grep reads 3 high in both directions.The guard also carries a vacuity check —
test_walker_scans_a_nonempty_treeasserts the walk finds >1000 files and specifically reachesintegrations/monitoring_integration.py, so a directory rename or a broadened exclusion cannot silently reduce the walk to zero and let the ceiling pass while checking nothing.Verified on the merged tip (
origin/Dev_new_gui): walker scans 2184 files, actual count 71.Known follow-up, tracked here so it is not lost: the ceiling constant merged at 87, which was correct against its own base but is now 16 slack because #12999 (−16) landed on top of it. PR #13000 removes a further 15 (the two densest files,
telegram_bot_service.pyandtts_client.py). Rather than tighten twice, the ceiling will be lowered once to the re-measured count after #13000 merges. Batch briefs for #12979 now require the ceiling to be lowered in the same PR that removes the sessions, re-measured against a freshly-synced tree immediately before push — a count taken early in a worktree is a snapshot of that worktree.- added a commit that references this issue
on Oct 10, 2026
Split out of #12979 while converting batch 3 (
integrations/cicd_integration.py,integrations/version_control_integration.py).Problem
The pilot conversion (PR #12982, merged as
8e2203c2a) predates #12989. Its two status-inspecting sites use the recipe that was current at the time:autobot-backend/integrations/monitoring_integration.py:69(DatadogIntegration.test_connection)autobot-backend/integrations/monitoring_integration.py:278(NewRelicIntegration.test_connection)That form releases the connection correctly — the
async withis the release point, and the accompanying comment says so. Butget()isrequest(), which increments_active_requestsand delegates the success-path decrement to the caller. Neither site callsdecrement_active(), so the counter only grows.This is exactly the defect #12981 described and #12989 fixed by introducing
tracked_request(), which owns the counter as well as the response block. The*_json()helpers in the same file were fixed by that change; these two raw-response sites were not, because they cannot use*_json()— they must inspectresponse.statusand return a structuredIntegrationHealthrather than raise.Evidence
Both
test_connection()methods driven five times each against a local aiohttp server:Connections released, counter leaked 1:1 with requests.
Why it matters
_active_requestsis not cosmetic. It drivesutilization = _active_requests / _current_pool_sizein_adjust_pool_size(), and gates the_active_requests == 0condition indecrement_active()that applies deferred session recreation. A monotonically rising counter pushes the pool toward_pool_maxand makes deferred recreation unreachable.Datadog and New Relic health checks are polled, so this accrues continuously wherever those integrations are enabled.
Fix
Swap both sites to
tracked_request(), keeping the existing status-inspection logic unchanged:Both sites already catch, log, and encode the failure as
IntegrationStatus.UNHEALTHY, sosuppress_error_log=Trueis appropriate — the manager's default ERROR log would duplicate a message the call site already emits.Verification
Reuse the per-batch method from #12979: exercise both
test_connection()paths (200 and non-2xx) against a local aiohttp server and assertconnector._acquired_per_hoststill-acquired is 0 and_active_requestsreturns to 0. Today the second assertion fails.Not fixed in the batch-3 PR because it is a different file and outside that batch's stated scope.
Refs #12979, #12981, #12989.