Skip to content

Add pub/sub channels for SSE (#1914)#1940

Open
bpamiri wants to merge 2 commits intodevelopfrom
peter/sse-channels-pubsub
Open

Add pub/sub channels for SSE (#1914)#1940
bpamiri wants to merge 2 commits intodevelopfrom
peter/sse-channels-pubsub

Conversation

@bpamiri
Copy link
Collaborator

@bpamiri bpamiri commented Mar 13, 2026

Summary

  • Adds channel-based pub/sub layer on top of existing SSE primitives (renders, streams, events all unchanged)
  • In-memory adapter (Channel.cfc) — ConcurrentHashMap-backed, instant delivery, single-server
  • Database adapter (DatabaseAdapter.cfc) — _wheels_events table with auto-create, poll-based, multi-server
  • Global publish() function — call from controllers, models, jobs, anywhere
  • Controller mixin (subscribeToChannel()) — long-lived SSE stream with heartbeats, timeout, disconnect detection
  • JS client (wheels-sse.js) — zero-dependency EventSource wrapper with auto-reconnect + exponential backoff
  • Tests — Channel engine core, DatabaseAdapter round-trip, controller mixin availability
  • Docs — Full API reference at .ai/wheels/channels/channels.md

Files

File Type Purpose
vendor/wheels/Channel.cfc New Core in-memory pub/sub engine
vendor/wheels/channel/DatabaseAdapter.cfc New Database-backed adapter (auto-creates _wheels_events table)
vendor/wheels/controller/channels.cfc New Controller mixin (auto-loaded)
vendor/wheels/Global.cfc Modified publish() and $getChannelEngine()
vendor/wheels/public/assets/js/wheels-sse.js New JS client library (~120 lines)
vendor/wheels/tests/specs/controller/channelSpec.cfc New Channel engine + mixin tests
vendor/wheels/tests/specs/channel/DatabaseAdapterSpec.cfc New Database adapter tests
.ai/wheels/channels/channels.md New API docs + usage patterns

Closes #1914

Test plan

  • CI passes — channel engine tests (in-memory subscribe/publish/unsubscribe, error isolation)
  • CI passes — database adapter tests (publish/poll round-trip, channel filtering, lastEventId, cleanup)
  • Controller mixin methods available on dummy controller
  • Existing SSE tests still pass (no changes to sse.cfc)
  • Manual: publish() from model callback delivers to subscribeToChannel() client

🤖 Generated with Claude Code

Adds a higher-level channel abstraction over the existing SSE primitives
with in-memory and database adapters, a global publish() function,
controller mixin for subscribeToChannel(), JS client library, and tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added docs enhancement javascript Pull requests that update javascript code labels Mar 13, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Mar 13, 2026

Wheels Test Matrix

Engine MySQL PostgreSQL SQL Server H2 Oracle SQLite
lucee5 ❌ 6
lucee6 ❌ 6
lucee7 ❌ 55 ❌ 55 ❌ 55 ❌ 55 ❌ 61 ❌ 55
adobe2018 -- ❌ 6 --
adobe2021 -- ❌ 6
adobe2023 -- ❌ 6
adobe2025 -- ❌ 6
boxlang -- ❌ 6

Results for commit 0ac9e74.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 13, 2026

Wheels Test Results

    42 files  ±    0   3 780 suites  +84   25m 23s ⏱️ -43s
78 162 tests +1 260  77 403 ✅ +882  381 💤 ±0  338 ❌ +338  40 🔥 +40 
80 808 runs  +1 260  80 049 ✅ +882  381 💤 ±0  338 ❌ +338  40 🔥 +40 

For more details on these failures and errors, see this check.

Results for commit d468c09. ± Comparison against base commit e5e2d59.

♻️ This comment has been updated with latest results.

MySQL DATETIME and Oracle TIMESTAMP have second-level precision, so
events published within the same second get identical createdAt values.
The previous > comparison missed events in the same second as the
reference event. Switch to >= with an explicit id != exclusion to
handle all databases correctly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs enhancement javascript Pull requests that update javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pub/Sub for SSE channels

1 participant