feat(live-streaming): implement live streaming and spectator mode - #459
Merged
Mkalbani merged 1 commit intoSep 28, 2026
Conversation
…ndFlowInteractive#441) Add a self-contained LiveStreamingModule covering the issue's acceptance criteria: - stream creation and lifecycle (scheduled/live/ended/cancelled, host-only start/end/cancel, recording finalised on end) - spectator join/leave, idempotent joins, and roster-derived viewer counts with a monotonic peak - real-time chat over a Socket.IO gateway (/streams) plus REST history, with soft deletes that preserve the audit trail - deterministic bandwidth -> quality adaptation - moderator tools (ban/unban/timeout/delete/pin/clear) with an immutable action log; host and assigned moderators only - viewership analytics (current/peak/total, chat, moderation, quality distribution, duration, recording state) - a migration creating the four tables and indexes, and a module README 42 unit tests cover lifecycle, permissions, chat, moderation, recording, quality and analytics.
|
@mubashqoz-eng Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #441
Overview
Adds a self-contained backend module for live streaming and spectator mode:
stream lifecycle, spectator joining, real-time chat, viewer tracking, adaptive
quality, recording, moderator tools and viewership analytics. It follows the
src/community-eventsmodule shape (entities + DTOs + service + controller +module) and adds a Socket.IO gateway on the
/streamsnamespace.The issue asks for ten tasks; this implements all of the acceptance criteria
through a single new
src/live-streamingmodule and wires it intoAppModule.Related Issue
Closes #441
Changes
src/live-streaming/entities/—LiveStream(status machine, cachedand peak viewer counts, recording state),
StreamViewer(soft membership soviewership is analysable),
StreamChatMessage(soft deletes keep the audittrail),
StreamModerationAction(immutable decisions; enforcement reads them).src/live-streaming/dto/— validated create/join/chat/moderationDTOs with Swagger metadata.
src/live-streaming/live-streaming.service.ts— the behaviour:create/start/end/cancel, join/leave/count, deterministic
qualityForBandwidth, chat post/history, moderator tools, recording, and agetAnalyticsaggregate. Host and moderator permissions are enforced in theservice; a finished stream cannot be started or joined, a banned viewer cannot
join or chat, and an unexpired timeout blocks both.
src/live-streaming/live-streaming.controller.ts— REST surface forevery operation. The caller's id travels in
x-user-id; binding that header tothe JWT guard is a gateway-shell decision, and the service is where the real
host/moderator check lives.
src/live-streaming/gateways/live-streaming.gateway.ts—stream:join,stream:leave,stream:chat,stream:quality. Chat broadcasts to thestream:<id>room; counts are re-read from the roster so two sockets cannotdrift the number; a disconnect leaves on behalf of the socket's stored user.
src/live-streaming/live-streaming.module.tsandsrc/migrations/1760000000000-CreateLiveStreamingTables.ts— module wiring andthe four-table schema with indexes.
src/app.module.ts— importLiveStreamingModule.src/live-streaming/README.md— model, routes, gateway events,quality ladder and migration.
Verification Results
npx jest src/live-streaming npx tsc --noEmit npx eslint "src/live-streaming/**/*.ts"Acceptance check:
stream:chatbroadcasts to the stream room; REST history excludes deleted messagesqualityForBandwidthladder, unit-tested at every boundarynpx jest src/live-streaming: 2 suites, 42 tests, all passing.npx jest test/spectator/spectator.service.spec.ts: passing (unchanged).npx tsc --noEmit: 207 pre-existing errors across the repo; none in any filethis PR touches.
npx eslint "src/live-streaming/**/*.ts": 3 errors, all theno-unsafe-return/no-unsafe-assignmentpattern in the generic test-repomock that existing specs (
community-events.service.spec.ts) also carry.Blockers and pre-existing failures (not from this diff)
mainis red before this change.npm run typecheckfails with 207errors in files unrelated to this diff (for example
src/skill-rating/elo.service.spec.tsimporting../elo.servicefrom thewrong directory,
src/users/users.service.tsimporting a missingcommon/pagination,src/replay/tests/replay.integration.spec.tsreferencingan undefined
analyticRepo). Because CI'stypecheckstep is nottolerated (
lint:checkandformat:checkare), CI cannot go green for any PRuntil those are fixed separately.
test/spectator/multiplayer.spectator.spec.tsfails onmainwithNest can't resolve dependencies of the MultiplayerGateway ... EventEmitter,independent of this change.
npx jeston the whole suite is large and mixed; I verified the suites thismodule can affect and left the unrelated pre-existing failures alone.
Notes for the reviewer
x-user-idand enforces host andmoderator authority inside the service. If the repo standard is to attach
JwtAuthGuardat the controller, that is a one-line change I can fold in.getAnalyticsderivescurrentViewersand the quality distribution from theactive roster (source of truth) while
LiveStream.viewerCountis a cachedread; a reconciliation job is not needed but the two are deliberately both
asserted in tests.