Skip to content

Phase 7: Typed event system + centralized timer manager - #2336

Open
Brainicism wants to merge 7 commits into
masterfrom
refactor/session-phase7-events
Open

Phase 7: Typed event system + centralized timer manager#2336
Brainicism wants to merge 7 commits into
masterfrom
refactor/session-phase7-events

Conversation

@Brainicism

Copy link
Copy Markdown
Owner

Session Architecture Redesign — Phase 7 of 8

What

Add type-safe event emitter, centralized timer management, and session lifecycle events.

New Files

  • typed_event_emitter.ts: TypedEventEmitter<T> wrapping Node's EventEmitter with compile-time event name + payload type checking
  • session_events.ts: SessionEvents interface — roundStart, roundEnd, stateChange, sessionEnd
  • timer_manager.ts: TimerManager with named set()/clear()/setInterval()/clearInterval()/clearAll() — guarantees all timers cleaned on session end

Changes to Existing Files

session.ts:

  • Added events (TypedEventEmitter) and timers (TimerManager) properties
  • Replaced guessTimeoutFunc field with timers.set('guessTimeout', ...)
  • stopGuessTimeout()timers.clear('guessTimeout')
  • endSession(): timers.clearAll(), emit sessionEnd, events.removeAllListeners()

game_session.ts:

  • Removed hiddenUpdateTimer field
  • startHiddenUpdateTimer()timers.setInterval('hiddenUpdate', ...)
  • stopHiddenUpdateTimer()timers.clearInterval('hiddenUpdate')

Risk: Low

Existing timer behavior is preserved — just centralized under named slots. The clearAll() call in endSession() is the key safety improvement: no timer can survive past session teardown.

Stack Order

  Phase 1 — Foundation
  Phase 2 — Enforce state machine
  Phase 3 — Consolidate mutex
  Phase 4 — Voice manager extraction
  Phase 5 — Scoreboard hardening
  Phase 6 — Clean API surface
► Phase 7 (this PR) — Event system + timer manager (depends on Phase 1)
  Phase 8 — Registry replaces State maps

Race Conditions Addressed

  • RACE-15: Guess timeout timer guaranteed cleanup on session end
  • RACE-24: Hidden update interval guaranteed cleanup on session end
  • Listener leak prevention via events.removeAllListeners() on dispose

@Brainicism
Brainicism requested a review from taahamahdi as a code owner April 30, 2026 08:38
@Brainicism
Brainicism force-pushed the refactor/session-phase7-events branch from 242be72 to 9400b74 Compare April 30, 2026 09:08
@Brainicism
Brainicism force-pushed the refactor/session-phase1-foundation branch from 6da0139 to c71e0f2 Compare May 1, 2026 03:37
Base automatically changed from refactor/session-phase1-foundation to master May 1, 2026 04:57
@Brainicism
Brainicism force-pushed the refactor/session-phase7-events branch from 42c0759 to 1229cd5 Compare May 1, 2026 06:05
Comment thread src/structures/game_session.ts Outdated
@Brainicism
Brainicism force-pushed the refactor/session-phase7-events branch 3 times, most recently from accdc07 to f499038 Compare May 2, 2026 19:34
Brainicism added 6 commits May 2, 2026 19:35
New files:
- src/structures/typed_event_emitter.ts — TypedEventEmitter<T> for
  compile-time event name and payload checking
- src/structures/session_events.ts — SessionEvents interface with
  roundStart, roundEnd, stateChange, sessionEnd events
- src/structures/timer_manager.ts — TimerManager class with named
  set/clear/setInterval/clearInterval/clearAll for leak-proof timer mgmt

Session base class:
- Add events (TypedEventEmitter<SessionEvents>) and timers (TimerManager)
- Replace guessTimeoutFunc field with timers.set('guessTimeout', ...)
- stopGuessTimeout() now uses timers.clear('guessTimeout')
- endSession(): calls timers.clearAll(), emits sessionEnd, removes listeners

GameSession:
- Remove hiddenUpdateTimer field
- startHiddenUpdateTimer() uses timers.setInterval('hiddenUpdate', ...)
- stopHiddenUpdateTimer() uses timers.clearInterval('hiddenUpdate')

Risk: Low — existing timer behavior preserved, just centralized.
Timer cleanup on session end is now guaranteed.

Addresses: RACE-15, RACE-24 (timer/interval leaks on session end)
- TimerManager: remove unused logger import, remove noisy clearAll log
- TimerManager: remove restating JSDoc comments
- TypedEventEmitter: remove restating removeAllListeners comment
- session.ts: remove restating cleanup comment
- Remove roundStart, roundEnd, stateChange from SessionEvents — they
  were declared but never emitted. Kept sessionEnd which IS emitted.
  Added comment noting future events will be wired with state machine.
- Remove unused SessionState import from session_events.ts
- Add comprehensive TimerManager unit tests covering set/clear,
  intervals, replacement, clearAll, and has()
Introduces a SessionTimerName enum in timer_manager.ts that documents
all named timer/interval keys. Replaces raw string literals at callsites
in session.ts and game_session.ts with enum values. TimerManager's API
stays string-based for flexibility (tests use arbitrary names).

Addresses PR review comment from taahamahdi.
@Brainicism
Brainicism force-pushed the refactor/session-phase7-events branch from f499038 to c19b2ec Compare May 2, 2026 19:36
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.

2 participants