Skip to content

fix(kap-server): release session event resources - #1652

Open
wbxl2000 wants to merge 1 commit into
mainfrom
codex/kap-broadcaster-lifecycle
Open

fix(kap-server): release session event resources#1652
wbxl2000 wants to merge 1 commit into
mainfrom
codex/kap-broadcaster-lifecycle

Conversation

@wbxl2000

Copy link
Copy Markdown
Collaborator

Related Issue

No standalone issue. This is a focused resource-lifecycle follow-up requested during the long-running server audit. It is stacked on #1623 because that PR changes the same broadcaster tests and snapshot state.

Problem

The v1 WebSocket broadcaster kept every activated session state until server shutdown. A closed or archived session therefore retained its journal tail, targets, agent/session listeners, and journal writer. Concurrent first activation could also create two owners for the same session (or global stream), causing duplicate listeners, missed subscribers, and duplicate sequence advancement.

Lifecycle release also had persistence races: an initialization or core event already awaiting could publish or append after the old owner began closing, allowing an immediate restore to overlap the previous journal writer.

What changed

  • Share one initialization Promise per session and for the global stream; rejected initialization is removed by identity so the next call can retry.
  • Subscribe to session close/archive events and retire the matching owner once. Retirement stops producers, drains already-queued frames, clears targets, closes the journal, then compare-deletes the same state. New callers wait for retirement and never borrow the old owner.
  • Recheck the captured lifecycle handle before publishing an initialized state, and clean up partial listener attachment on every failure path.
  • Guard async core-event enqueue against closed, retiring, or replaced state. A restored owner reopens the existing journal without changing its epoch or duplicating sequence numbers.
  • Share one close Promise so concurrent server-close callers await the same initialization, retirement, queue, and journal barrier.
  • Add a repeatable 3 rounds × 8 sessions resource regression plus a real REST archive/restore and /api/v1/ws cursor-continuity contract.

This PR currently targets #1623's head branch (8fae3d8fc) so its diff contains only this follow-up. It can be retargeted to main after #1623 merges.

Validation

  • Reproduction before the fix: two concurrent first subscribers created 2 agent-bus handlers instead of 1.
  • Broadcaster + real v1 WS targeted tests: 49/49.
  • Full @moonshot-ai/kap-server suite, single worker: 56 files / 657 tests.
  • @moonshot-ai/kap-server typecheck.
  • @moonshot-ai/agent-core-v2 lint:domain (848 files).
  • Targeted type-aware oxlint: 0 errors (existing warnings only).
  • git diff --check.
  • pnpm changeset status --since=8fae3d8fc9e025437547841d80d000cecd07830c (CLI patch).
  • Independent fixed-diff review: no actionable findings; no internal identifiers found.

3×8 diagnostic samples (not pass/fail RSS thresholds):

Round Active owners after retirement Heap used RSS
1 0 139,659,608 262,127,616
2 0 140,493,312 262,307,840
3 0 140,632,064 262,406,144

gen-docs was evaluated. This internal lifecycle fix adds no command, configuration, or user workflow to document; the skill's expected changelog sync helper is absent on the base branch, so this PR does not invent or modify documentation tooling.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

@changeset-bot

changeset-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a41120b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex review

@pkg-pr-new

pkg-pr-new Bot commented Jul 14, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@6aaf8af
npx https://pkg.pr.new/@moonshot-ai/kimi-code@6aaf8af

commit: 6aaf8af

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: 3491795360

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 962365123a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

for (const d of state.lifecycleDisposables) d.dispose();
for (const d of state.agentDisposables.values()) d.dispose();
await state.queue;
state.targets.clear();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve live WS subscriptions across archive/restore

When a session is archived or closed while a WebSocket remains connected, this clears the broadcaster's target set without notifying WsConnectionV1, whose own subscriptions map is only updated by explicit unsubscribe/close. If that same session is later restored in the same socket lifetime, the connection still believes it is subscribed but the fresh broadcaster owner has no target for it, so subsequent session events are silently missed until the client reconnects or manually subscribes again. Either keep enough subscription state to reattach on restore, or send/remove the subscription explicitly before dropping these targets.

Useful? React with 👍 / 👎.

@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex review

1 similar comment
@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: 6aaf8af479

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@wbxl2000
wbxl2000 force-pushed the codex/kap-broadcaster-lifecycle branch from 6aaf8af to a41120b Compare July 15, 2026 06:05
@wbxl2000
wbxl2000 changed the base branch from fix/kap-server-subagent-roster to main July 15, 2026 06:05
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.

1 participant