Skip to content

fix: CMA event history is retained forever — unbounded memory growth and permanent 413 on the events endpoint #106

Description

@AsperforMias

Problem

The CMA memory store — the only shipped CmaStore implementation — has no TTL, no eviction, and no session deletion (src/stores/memory/cma-event-broker.ts:29-34, src/stores/memory/cma-memory-store.ts:77-85; the CmaStore interface has no delete operation, src/stores/cma-store.ts:184-207). Every lossless event (up to 1 MiB each) and every settled inbound claim (full command + result payload, kept for idempotency) is retained forever, including for terminated sessions.

Two concrete consequences:

  1. Unbounded memory growth. Steady heap growth across session churn → OOM kill of the service container over days/weeks of uptime.
  2. Permanent 413 on the events endpoint. listSessionEvents() always replays the full history with no cursor (cma-memory-store.ts:399-402), so once a session's cumulative events cross CMA_MAX_REPLAY_BYTES (8 MiB), GET /v1/sessions/:id/events throws RangeError → 413 (src/surfaces/cma-http/response.ts:151-153) on every subsequent request, and cursor-less SSE reconnects fail the same way. Because history is never pruned, the threshold is only ever crossed, never uncrossed — and there is no remediation API.

Reproduction

Persist lossless events totalling more than 8 MiB to one session (as few as 9 max-size events), then:

curl http://<host>/v1/sessions/<id>/events   # → 413, permanently

For the growth half: run sessions continuously against the memory store and observe monotonic heap increase with no eviction.

Impact

OOM of a long-lived service; per-session permanent API failure with total event-stream loss for consumers that did not persist a cursor.

Proposed direction

Add a retention/eviction policy (per-session cap and/or post-termination cleanup, including settled inbound claims), and make full-history listing cursor-aware rather than unconditionally replaying everything.

Acceptance criteria

  • Memory usage stays bounded across session churn and terminated sessions.
  • Sessions with large histories remain listable via cursors; no permanent 413 state.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions