Skip to content

refactor: extract SessionWebSocketManager from SessionDO#74

Merged
ColeMurray merged 2 commits intomainfrom
refactor/session-websocket-manager
Feb 7, 2026
Merged

refactor: extract SessionWebSocketManager from SessionDO#74
ColeMurray merged 2 commits intomainfrom
refactor/session-websocket-manager

Conversation

@ColeMurray
Copy link
Owner

Summary

  • Extracts all Cloudflare WebSocket API usage (ctx.acceptWebSocket, ctx.getWebSockets, ctx.getTags, ctx.setWebSocketAutoResponse) from SessionDO into a new SessionWebSocketManager module
  • Replaces 5+ inline tag-parsing sites with a single classify() method and consolidates hibernation recovery, auth timeout enforcement, and broadcast filtering into one testable unit
  • The manager is a registry for ClientInfo, not a factory — the DO builds ClientInfo with domain knowledge (avatar URLs, name fallback) and stores it via setClient/getClient
  • Net reduction of ~150 lines in durable-object.ts

Design decisions

  • Atomic sandbox accept: acceptAndSetSandboxSocket() combines accept + replace + set to prevent misuse of a split sequence
  • Internal sandbox ID validation: getSandboxSocket() reads the expected sandbox ID from the repository internally — callers cannot accidentally omit validation
  • Broadcast filtering: forEachClientSocket() supports "all_clients" and "authenticated_only" modes; the latter checks both in-memory state and persisted DB mappings for post-hibernation correctness
  • Phase 1: All broadcasts use "all_clients" mode (behavior-preserving). A follow-up will switch to "authenticated_only" with prerequisite tests
  • Lazy initialization: Same getter pattern as lifecycleManager to ensure the logger has session context

Test plan

  • 46 new unit tests covering:
    • Tag parsing / classification
    • Sandbox socket accept, replacement, and hibernation recovery (incl. sandbox ID validation)
    • Client identity registry and hibernation recovery via persisted mappings
    • Auth timeout enforcement
    • Broadcast filtering (all_clients and authenticated_only modes)
    • Send/close safety, connected client counting
  • All 325 existing tests pass
  • Validated in production deployment

Centralizes all Cloudflare WebSocket API usage (ctx.acceptWebSocket,
ctx.getWebSockets, ctx.getTags, ctx.setWebSocketAutoResponse) into a
single testable module. This replaces 5+ inline tag-parsing sites with
a single classify() method and consolidates hibernation recovery,
auth timeout enforcement, and broadcast filtering.

The manager is a registry for ClientInfo, not a factory — the DO builds
ClientInfo with domain knowledge (GitHub avatars, name fallback) and
stores it via setClient/getClient. For hibernation recovery, the manager
returns raw DB mappings; the DO converts them to ClientInfo.

Key changes:
- New SessionWebSocketManager interface + SessionWebSocketManagerImpl
- Atomic acceptAndSetSandboxSocket (accept + replace + set)
- getSandboxSocket reads expected sandbox ID from repository internally
- forEachClientSocket supports "all_clients" and "authenticated_only"
- 46 unit tests with FakeCtx and mock repository
- Net reduction of ~150 lines in durable-object.ts

Phase 1: all broadcasts use "all_clients" mode (behavior-preserving).
Phase 2 (follow-up) will switch to "authenticated_only" with DB-backed
auth check for post-hibernation correctness.
@github-actions
Copy link

github-actions bot commented Feb 7, 2026

Terraform Validation Results

Step Status
Format ⚠️
Init
Validate

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

@greptile-apps
Copy link

greptile-apps bot commented Feb 7, 2026

Greptile Overview

Greptile Summary

Extracted WebSocket management logic from SessionDO into a dedicated, testable SessionWebSocketManager module with 46 new unit tests.

Key improvements:

  • Consolidated 5+ tag-parsing sites into single classify() method
  • Atomic acceptAndSetSandboxSocket() prevents split-sequence misuse
  • Internal sandbox ID validation in getSandboxSocket() ensures hibernation recovery safety
  • Broadcast filtering with "all_clients" and "authenticated_only" modes
  • Net reduction of ~150 lines in durable-object.ts

Testing:

  • 46 new unit tests covering tag parsing, hibernation recovery, auth timeout enforcement, broadcast filtering, and sandbox socket lifecycle
  • All 325 existing tests pass
  • Validated in production deployment

Minor observation:

  • enableAutoPingPong() is called on every client subscribe, but setWebSocketAutoResponse() is a DO-global setting. Consider moving this to initialization to avoid redundant calls.

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

…ribe

setWebSocketAutoResponse is a DO-global setting. Calling it on every
subscribe was harmless but redundant. Move to ensureInitialized() so
it runs once per DO instance lifecycle.
@github-actions
Copy link

github-actions bot commented Feb 7, 2026

Terraform Validation Results

Step Status
Format ⚠️
Init
Validate

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

@ColeMurray ColeMurray merged commit 0e31318 into main Feb 7, 2026
10 checks passed
@ColeMurray ColeMurray deleted the refactor/session-websocket-manager branch February 7, 2026 08:01
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