Skip to content

fix(js-streamer): clean up player connections - #1128

Merged
mcottontensor merged 2 commits into
EpicGames:masterfrom
snowyukitty:fix/js-streamer-peer-cleanup
Oct 27, 2026
Merged

mcottontensor merged 2 commits into
EpicGames:masterfrom
snowyukitty:fix/js-streamer-peer-cleanup

Conversation

@snowyukitty

@snowyukitty snowyukitty commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Relevant components

JavaScript streamer (Extras/JSStreamer) and frontend integration tests.

Problem statement

Fixes #944.

Players are assigned as properties on playerMap, so the Map.values() loop in
stopStreaming() never sees them. Stopping leaves their peer connections and
stats intervals alive. Individual player disconnection clears its interval but
does not close its local peer connection.

Solution

Use the Map API consistently for player insertion, lookup and removal. Both
shutdown and player disconnection release the stats interval and peer connection
through the same cleanup method. Repeated cleanup is safe, while the existing
disconnect notifications, transport close code/reason and caller-owned media
tracks are preserved.

Documentation

Added a JSStreamer patch changeset.

Test Plan and Compatibility

  • Built Common, Signalling, SignallingWebServer, the frontend and UI libraries,
    the TypeScript frontend implementation, and JSStreamer with Node v22.14.0.
  • Ran the complete Chromium Playwright suite with the real signalling server,
    JSStreamer, media streams and data channels: 14 passed, 3 existing skips.
    The new tests cover two-player shutdown, individual disconnection, repeated and
    unknown disconnection, idle/repeated shutdown, timer cleanup, transport close,
    and media-track ownership. The shutdown tests contain no protocol/settings
    delivery assertions.
  • The same test-only changes on the audited upstream source fail at both
    peer-cleanup assertions; the other 12 tests pass, with the same 3 skips.
  • The frontend library's Jest suite previously passed 71 tests on October 21;
    it was not rerun for this test-only follow-up.

Browser tests ran in an isolated Linux container using a local TURN fixture.
Firefox's existing basic-stream test could not gather usable ICE candidates in
the original isolated validation, so Firefox compatibility is not established.
An Unreal Editor smoke test was not run.

The October 21 comparison found JSStreamer's existing unsafe-typing lint errors
(39 on the base, 22 on the candidate), and the same 7 existing diagnostics in an
additional frontend-test type check, with none in the new test. Those lint/type
checks were not rerun for this follow-up; production code is unchanged from the
previous PR head.

@changeset-bot

changeset-bot Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 818fda5

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

This PR includes changesets to release 2 packages
Name Type
@epicgames-ps/js-streamer Patch
@epicgames-ps/frontend-tests Patch

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

@mcottontensor

Copy link
Copy Markdown
Collaborator

Thanks for picking this up, and for the thorough test plan. Switching to the Map API plus a single removePlayer() path looks right to me. Two small requests before we merge:

  1. Drop the protocol/settings check from the shutdown test

In streamer_shutdown.spec.ts, the first test also checks that the data protocol and initial settings are delivered (the messages handle and the sendDataProtocol / sendInitialSettings round-trip, roughly lines 75–108). That isn't about cleanup, and it ends up depending on an existing bug: sendDataProtocol's second loop writes into streamerProto instead of playerProto, so the Direction: 1 message is basically empty. That's why the assertion can only use objectContaining({ Direction: 1 }). If someone fixes that later, a test about shutdown would break for an unrelated reason.

Could you remove that block so the test only covers shutdown? If you'd like to keep the protocol coverage, a separate test is fine. Better still, fix the playerProto loop in a follow-up PR and assert the full message there.

  1. Add a scope to the title

Could you rename the PR to fix(js-streamer): clean up player connections? That matches how we scope titles elsewhere. We squash-merge, so the PR title becomes the commit message.

@snowyukitty snowyukitty changed the title fix: clean up JSStreamer player connections fix(js-streamer): clean up player connections Oct 26, 2026
@mcottontensor
mcottontensor merged commit 46470bc into EpicGames:master Oct 27, 2026
2 checks passed
saba-abi pushed a commit to saba-abi/PixelStreamingInfrastructure that referenced this pull request Nov 2, 2026
* fix: clean up JSStreamer player connections

* test(js-streamer): focus shutdown coverage on cleanup

---------

Co-authored-by: snowyukitty <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

JSStreamer: playerMap is a Map but accessed via bracket indexing, so stopStreaming() never closes peer connections

2 participants