Skip to content

Fix streamable HTTP memory leak from unstable OpenAPI spec object identity - #335

Open
onematchfox wants to merge 1 commit into
makenotion:mainfrom
onematchfox:fix/streamable-http-spec-cache-memory-leak
Open

Fix streamable HTTP memory leak from unstable OpenAPI spec object identity#335
onematchfox wants to merge 1 commit into
makenotion:mainfrom
onematchfox:fix/streamable-http-spec-cache-memory-leak

Conversation

@onematchfox

Copy link
Copy Markdown

Description

Every new HTTP session called initProxy(), which re-read and JSON.parse()'d the OpenAPI spec from disk, producing a fresh object each time. openapi-client-axios dereferences that document through dereference-json-schema, which caches its output in a process-lifetime Map keyed by the input object's identity, with no eviction. A fresh object on every call defeated that cache on every session and permanently retained a full dereferenced copy of the spec, forever - see #144.

Cache the parsed spec by (specPath, baseUrl) so repeated sessions share the same object identity, letting the upstream cache actually hit instead of growing unbounded. Verified with heap snapshots: an isolated initProxy() loop went from +23.2MB/300 calls to +237KB/300 calls (98% reduction, remainder is one-time JIT warmup, not a leak), and a full end-to-end run (server as a separate process, sessions properly terminated via DELETE) plateaus after an initial JIT warmup with no further growth between 100 and 300 cycles.

Closes #144.

How was this change tested?

  • Automated test (unit, integration, etc.)
  • Manual test (provide reproducible testing steps below)

Screenshots

…ntity

Every new HTTP session called initProxy(), which re-read and JSON.parse()'d
the OpenAPI spec from disk, producing a fresh object each time. openapi-client-axios
dereferences that document through dereference-json-schema, which caches its
(expensive, fully-expanded) output in a process-lifetime Map keyed by the
input object's identity, with no eviction. A fresh object on every call
defeated that cache on every session and permanently retained a full
dereferenced copy of the spec, forever.

Cache the parsed spec by (specPath, baseUrl) so repeated sessions share the
same object identity, letting the upstream cache actually hit instead of
growing unbounded. Verified with heap snapshots: an isolated initProxy() loop
went from +23.2MB/300 calls to +237KB/300 calls (98% reduction, remainder is
one-time JIT warmup, not a leak), and a full end-to-end run (server as a
separate process, sessions properly terminated via DELETE) plateaus after an
initial JIT warmup with no further growth between 100 and 300 cycles.

Fixes makenotion#144

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@onematchfox

Copy link
Copy Markdown
Author

For reference - this shows memory use in our cluster after deploying this change
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Streamable HTTP container has memory leak

1 participant