Skip to content

feat(core): subscribe to events before connect#1146

Closed
jog1t wants to merge 598 commits intomainfrom
07-29-feat_subscribe_to_events_before_connect
Closed

feat(core): subscribe to events before connect#1146
jog1t wants to merge 598 commits intomainfrom
07-29-feat_subscribe_to_events_before_connect

Conversation

@jog1t
Copy link
Copy Markdown
Collaborator

@jog1t jog1t commented Jul 28, 2025

Fixes KIT-185

TL;DR

Added support for pre-subscribing to events when establishing connections to actors, and implemented an onConnect handler for actors.

What changed?

  • Added an onConnect handler to the actor definition that gets called when a new connection is established
  • Implemented the ability to pre-subscribe to events when creating a connection
  • Added a new create() method on actor handles that returns a connection that must be manually connected
  • Added support for passing subscriptions in WebSocket and SSE connections
  • Updated the protocol to include subscriptions in headers and WebSocket protocols
  • Added debugging logs for event broadcasting

How to test?

  1. Use the new create() method to create a connection without immediately connecting:
const connection = client.counter.getOrCreate(["test-id"]).create();
connection.on("some-event", (data) => console.log(data));
connection.connect();
  1. Test the onConnect handler by creating an actor with the handler:
const myActor = actor({
  onConnect: (c, conn) => {
    c.broadcast("connected", "New connection established");
    conn.send("welcome", "Hello new connection!");
  },
  // other actor properties
});
  1. Pre-subscribe to events when connecting:
const connection = client.counter.getOrCreate(["test-id"]).create();
connection.on("onconnect:broadcast", (data) => console.log(data));
connection.on("onconnect:msg", (data) => console.log(data));
connection.connect();

Why make this change?

This change improves the developer experience by:

  1. Allowing actors to send initial data to clients when they connect
  2. Enabling clients to set up event listeners before the connection is established, ensuring no events are missed
  3. Reducing the need for multiple round-trips when setting up connections with subscriptions
  4. Providing more flexibility in how connections are established and managed

These improvements make it easier to build real-time applications with proper initialization sequences and event handling.

NathanFlurry and others added 30 commits May 22, 2025 13:08
Release-As: 0.9.0-rc.1
Release-As: 0.9.0-rc.1
Release-As: 0.9.0-rc.1
NathanFlurry and others added 20 commits September 15, 2025 20:14
* chore(core): update engine runner

* chore(core): add logger to engine runner

* chore(core): add readme

* chore(fs): remove unneeded warning for onRunnerStart

* chore(core): add welcome message

* chore(core): remove engine runner addresses config

* chore(core): simplify engine keys
* chore(core): update engine runner

* chore(core): add logger to engine runner

* chore(core): add readme

* chore(fs): remove unneeded warning for onRunnerStart

* chore(core): add welcome message

* chore(core): remove engine runner addresses config

* chore(core): simplify engine keys

* chore(core): fix simple engine test
* chore(core): update engine runner

* chore(core): add logger to engine runner

* chore(core): add readme

* chore(fs): remove unneeded warning for onRunnerStart

* chore(core): add welcome message

* chore(core): remove engine runner addresses config

* chore(core): simplify engine keys

* chore(core): fix simple engine test

* fix(core): fix issue deserializing WebSocket message with BARE
* chore(core): remove manager driver

* fix(inspector): make inspector work again (#1228)

* fix(core): fix websockets (#1229)

* fix(inspector): make inspector work again

* fix(core): fix websockets

---------

Co-authored-by: Kacper Wojciechowski <39823706+jog1t@users.noreply.github.com>

---------

Co-authored-by: Kacper Wojciechowski <39823706+jog1t@users.noreply.github.com>
* chore(release): limit built packages

* chore: release 2.0.4

Release-As: 2.0.4
Release-As: 2.0.4
@jog1t jog1t force-pushed the 07-29-feat_subscribe_to_events_before_connect branch from 6432ea3 to 0127964 Compare September 17, 2025 16:45
@vercel
Copy link
Copy Markdown

vercel bot commented Sep 17, 2025

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

Project Deployment Preview Comments Updated (UTC)
rivetkit-express Error Error Sep 17, 2025 5:03pm

@jog1t jog1t force-pushed the 07-29-feat_subscribe_to_events_before_connect branch from 0127964 to d98968e Compare September 17, 2025 17:02
@claude
Copy link
Copy Markdown

claude bot commented Sep 17, 2025

Claude finished @jog1t's task —— View job


PR Review: feat(core): subscribe to events before connect

Review Checklist:

  • Read and understand all changed files
  • Analyze code quality and adherence to best practices
  • Identify potential bugs and issues
  • Evaluate performance considerations
  • Assess security concerns
  • Review test coverage
  • Provide comprehensive feedback and recommendations

Feature Overview ✅

This PR implements the ability to subscribe to events before establishing a WebSocket connection, plus an onConnect handler for actors. Key changes include:

  1. Protocol Enhancement: Added subscriptions parameter to connection schemas (packages/rivetkit/src/manager/protocol/query.ts:74-87)
  2. Actor Handle API: New create() method that returns ActorManualConn requiring manual connection (packages/rivetkit/src/client/actor-handle.ts:175-192)
  3. Connection Logic: Enhanced WebSocket connection to pass subscription list during handshake (packages/rivetkit/src/client/actor-conn.ts:281)
  4. Actor Lifecycle: Added onConnect handler support with broadcast and direct messaging capabilities
  5. Pre-subscription Processing: Subscriptions are processed during connection creation in actor instance

This is a valuable optimization that eliminates the round-trip delay for event subscriptions after connection establishment.


Code Quality Analysis ✅

Strengths:

  • Consistent Implementation: Follows existing codebase patterns and conventions
  • Type Safety: Proper TypeScript types and Zod schemas throughout
  • Backwards Compatibility: The subscriptions parameter is optional, maintaining compatibility
  • Clean API Design: The new create() method provides clear distinction from connect()

Architecture:

  • Clean Separation: Changes properly distributed across protocol, transport, and client layers
  • Interface Consistency: Maintains API consistency across WebSocket, SSE, and HTTP connections

Issues and Bugs Found 🔍

1. Console.log Usage - packages/rivetkit/src/actor/instance.ts:1026,1499

console.log("subscribing to event", { eventName, connId: conn.id });
console.log("broadcasting event", {

Issue: Direct console.log usage instead of the project's logging framework.
Recommendation: Replace with logger().debug() per CLAUDE.md guidelines.

2. Missing Subscription Validation

Issue: No validation of subscription event names beyond basic JSON parsing in protocol handling.
Recommendation: Add validation to prevent subscription to internal/system events that shouldn't be accessible to clients.

3. Potential Race Condition

Issue: In packages/rivetkit/src/actor/instance.ts:954-958, subscriptions are processed after connection creation but before onConnect handler.
Recommendation: Consider if this ordering could cause missed events from the onConnect handler.


Performance Considerations ⚡

Improvements:

  • Reduced Latency: Eliminates post-connection subscription round-trips
  • Better UX: Events can be received immediately upon connection
  • Network Efficiency: Fewer messages required for connection setup

Impact Assessment:

  • Memory: Minimal impact - subscription tracking already exists
  • CPU: No significant computational overhead
  • Network: Reduces overall message count for typical connection patterns

Potential Concerns:

  • Connection Setup Time: Slightly increased due to subscription parsing, but offset by eliminated round-trips
  • WebSocket Payload: Subscription data adds to initial connection payload

Security Assessment 🔒

Low Risk Issues:

  1. Event Name Validation: Currently no restrictions on which events can be subscribed to during connection
  2. Subscription Scope: No apparent filtering or access control for subscription requests

Recommendations:

  • Consider adding an event whitelist or validation mechanism for subscribable events
  • Ensure internal events (like system events) cannot be subscribed to by clients
  • Add basic rate limiting considerations for subscription requests

Positive Aspects:

  • ✅ Maintains existing authentication and authorization patterns
  • ✅ Subscription data passed through secure channels (headers/protocols)
  • ✅ No new attack vectors beyond existing connection security
  • ✅ JSON parsing includes proper error handling

Test Coverage Assessment 📋

Positive: Good Baseline Coverage

The PR includes updates to test files:

  • packages/rivetkit/src/driver-test-suite/tests/actor-conn.ts shows comprehensive connection tests
  • Tests cover various connection methods and event handling scenarios
  • Test fixture updated to demonstrate onConnect functionality

Area for Improvement: Pre-Connection Subscription Tests

While existing tests cover connections and events, specific tests for pre-connection subscription behavior would strengthen coverage:

  1. Pre-connection subscription behavior: Verifying events are received immediately upon connection
  2. Subscription parameter validation: Testing invalid subscription JSON or event names
  3. Mixed subscription scenarios: Pre-connection + post-connection subscriptions
  4. onConnect handler integration: Testing that pre-subscribed clients receive onConnect events

Test Quality:

  • Existing Tests Updated: Good integration with existing test suite
  • Real-world Usage: Test fixture demonstrates practical usage patterns
  • ⚠️ Missing Edge Cases: Could benefit from more specific pre-subscription test scenarios

Overall Assessment 📝

Strengths:

  • Valuable Feature: Addresses real performance optimization need
  • Clean Implementation: Well-integrated with existing architecture
  • Type Safety: Proper TypeScript usage throughout
  • Backwards Compatible: Optional parameters maintain compatibility
  • Good Test Integration: Updates existing test suite appropriately

Issues Requiring Attention:

High Priority:

  1. Replace console.log statements with proper logging (packages/rivetkit/src/actor/instance.ts:1026,1499)

Medium Priority:
2. Add validation for subscription event names to prevent access to internal events
3. Consider subscription processing order relative to onConnect handler

Low Priority:
4. Add more specific tests for pre-connection subscription functionality
5. Improve inline documentation for new subscription behavior


Recommendation: Approve with Minor Changes

This is a well-implemented feature that provides clear value. The issues identified are minor and can be addressed in follow-up work if needed. The core functionality is sound and follows project patterns well.

Files needing attention:

  • packages/rivetkit/src/actor/instance.ts:1026,1499 - Replace console.log with logger()
  • Consider adding subscription parameter validation
  • Optional: Add more specific tests for pre-connection subscription scenarios

The implementation successfully delivers the intended functionality while maintaining code quality and backwards compatibility.


@NathanFlurry NathanFlurry deleted the 07-29-feat_subscribe_to_events_before_connect branch March 30, 2026 22:20
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.

4 participants