Skip to content

refactor(display): collapse publisher + subscriber into display-realtime - #106

Merged
rghamilton3 merged 5 commits into
mainfrom
worktree-chore+simplify-display-subsystem
Apr 13, 2026
Merged

rghamilton3 merged 5 commits into
mainfrom
worktree-chore+simplify-display-subsystem

Conversation

@rghamilton3

Copy link
Copy Markdown
Contributor

Summary

  • Merge display-publisher.ts (429 LOC) and display-subscriber.ts (232 LOC) into a single display-realtime.ts (231 LOC)
  • Drop 3 failure state machines (silent-drop warning, terminal failure escalation, removeChannel failure counter), PublisherMode enum, and duplicated removeChannelSafe
  • Replace 3 test files that unit-tested Supabase channel internals with a single display-realtime.test.ts covering observable behavior

Net change: -1,010 LOC source, -610 LOC tests

Test plan

  • bun run build passes (TypeScript clean)
  • bun run test -- 126 files / 2440 tests passing
  • display-realtime.ts exports same public API as the two modules it replaces (callers changed import path only)
  • Behavioral tests verify: correct event+payload on publish, handlers fire on incoming broadcast, hello handshake round-trip, removeChannel called on destroy

@vercel

vercel Bot commented Apr 12, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ardent-forge Ready Ready Preview, Comment Apr 13, 2026 0:15am

Merge display-publisher.ts (429 LOC) and display-subscriber.ts (232 LOC)
into a single display-realtime.ts (231 LOC). Drops three failure state
machines (silent-drop warning, terminal failure escalation, removeChannel
failure counter), the PublisherMode enum, and the duplicated
removeChannelSafe helper.

Replace three test files that unit-tested Supabase channel internals
with a single display-realtime.test.ts testing observable behavior:
channel.send receives correct event and payload, handlers fire on
incoming broadcasts, hello handshake round-trip.

Net: -1,010 LOC source, -610 LOC tests, 2440 tests passing.
- P16-001: null-client branch in scheduleRetry stops reconnect loop,
  calls onStatusChange('disconnected') instead of silently abandoning
- P16-002: clearTimeout pending retry before re-subscribing prevents
  stale-gymId ghost subscription on useEffect re-run
- P16-004: removeSafe logs warn when client is null instead of silent return
- P16-005: unfocus broadcast handler wrapped in try-catch matching the
  display_hello responder pattern — prevents throw propagating into Supabase
- P16-006: subscriber CHANNEL_ERROR/TIMED_OUT logged at error, CLOSED at info,
  mirroring the publisher's existing conditional
- P16-007: empty-string gymId guard added to configureDisplayPublisher and
  subscribeToDisplay — prevents display:gym: channel name
- P16-011: validated() logs r.error.toString() + raw payload instead of raw
  ZodError instance — serializes correctly in Sentry/Datadog
- P16-014: pubSend widened to unknown payload, removes double-cast in
  publishDisplaySnapshot

Review: Context/Reviews/0016-pr106-simplify-display-subsystem-2026-04-12.md
Tasks: S015-T through S021-T added to Steps.md for missing display-realtime
test coverage (subscribeToDisplay throw, onStatusChange, focus/unfocus/idle
handlers, gym-switch teardown, backoff sequencing, auto-publishHello, getters)

ADR-015: documents shared _client teardown contract — publisher and subscriber
are mutually exclusive by route structure; P16-001/P16-002 fixes mitigate the
retry-window race without requiring a new co-existence mechanism

Review: Context/Reviews/0016-pr106-simplify-display-subsystem-2026-04-12.md
…21-T)

Adds 21 new tests across 7 task items from the P16 review:

- S015-T: subscribeToDisplay throws when uninitialized or gymId is empty
- S016-T: publishHello fires on reconnect but not on first connect
- S017-T: onStatusChange asserted for SUBSCRIBED/TIMED_OUT/CHANNEL_ERROR/CLOSED
- S018-T: focus, unfocus, idle_snapshot broadcast handler coverage
- S019-T: gym-switch tears down old channel and creates new one
- S020-T: backoff delay math (2000ms first, resets on reconnect, cap at 30s)
- S021-T: getActiveGymId and getSubscriberStatus state transitions

Introduces autoSubscribe option on createMockClient to accumulate
_subRetryAttempt across consecutive errors without SUBSCRIBED resetting it.

Tasks: S015-T, S016-T, S017-T, S018-T, S019-T, S020-T, S021-T
Feature: 008-display-broadcast-infrastructure
@rghamilton3
rghamilton3 force-pushed the worktree-chore+simplify-display-subsystem branch from a59a54c to ded0e3e Compare April 13, 2026 00:09
@rghamilton3
rghamilton3 force-pushed the worktree-chore+simplify-display-subsystem branch from ded0e3e to f68501b Compare April 13, 2026 00:14
@rghamilton3
rghamilton3 merged commit 9646a4a into main Apr 13, 2026
3 of 4 checks passed
@rghamilton3
rghamilton3 deleted the worktree-chore+simplify-display-subsystem branch April 13, 2026 00:15

This branch was successfully deployed

1 active deployment
Preview — f68501b0 Deployed Apr 13, 2026 by vercel[bot]
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