Skip to content

Conversation

@NathanFlurry
Copy link
Member

No description provided.

@vercel
Copy link

vercel bot commented Nov 21, 2025

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

Project Deployment Preview Comments Updated (UTC)
rivetkit-serverless Error Error Nov 21, 2025 1:28am
3 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
rivet-cloud Ignored Ignored Nov 21, 2025 1:28am
rivet-inspector Ignored Ignored Preview Nov 21, 2025 1:28am
rivet-site Ignored Ignored Preview Nov 21, 2025 1:28am

Copy link
Member Author

NathanFlurry commented Nov 21, 2025

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more


How to use the Graphite Merge Queue

Add the label merge-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@claude
Copy link

claude bot commented Nov 21, 2025

Code Review: Buffer Outbound Tunnel Messages

Summary

This PR implements message buffering for outbound tunnel messages when the WebSocket connection is not ready. The implementation follows the same pattern as the existing KV request buffering system and addresses the issue of dropped tunnel messages during connection interruptions.


Positive Aspects

  1. Consistent Pattern: The buffering implementation mirrors the existing KV request buffering, maintaining consistency across the codebase.

  2. Type Safety Improvement: The __webSocketReady() method now uses a type predicate which provides type narrowing for TypeScript - excellent use of TypeScript type system.

  3. Better Logging: The change from warn to debug level for buffering messages (line 488 in tunnel.ts) is appropriate since buffering is expected behavior during reconnection, not an error condition.

  4. Proper Resend Ordering: The resend sequence at mod.ts:833-836 is correct - KV requests first, event acknowledgments second, tunnel messages last.


Issues and Concerns

1. Memory Leak Risk - Unbounded Buffer Growth - HIGH PRIORITY

Location: tunnel.ts:60-65

The bufferedMessages array has no size limit. If the WebSocket remains disconnected for an extended period while tunnel messages continue to be sent, this buffer will grow unbounded, potentially causing an out-of-memory error.

Recommendation: Add a maximum buffer size with appropriate handling (FIFO eviction when full).

2. Missing Buffer Cleanup on Shutdown - MEDIUM PRIORITY

Location: tunnel.ts:97-124

The shutdown() method does not clear bufferedMessages. While the buffer will be garbage collected when the object is destroyed, explicitly clearing it is a best practice.

Recommendation: Add this.bufferedMessages = [] at the start of shutdown().

3. Potential Message Ordering Issue - MEDIUM PRIORITY

Location: tunnel.ts:481-495 and tunnel.ts:79-95

When resendBufferedEvents() is called, it attempts to send all buffered messages. However, if sendMessage() encounters an actor that does not exist (line 504-511), it logs a warning and returns without sending. This means the message is lost (not re-buffered), subsequent messages for valid actors are still sent, and message ordering guarantees may be violated.

Recommendation: Consider whether dropped messages should be re-buffered or if actors are guaranteed to exist when resending. Document this behavior or add re-buffering logic.

4. Race Condition Possibility - LOW PRIORITY

Location: tunnel.ts:89-93

The pattern of copying the buffer and clearing it is good. If sendMessage recursively buffers (which it does on line 493), those messages go into the new empty array and will be sent on next reconnect. This is actually correct behavior, but could use a comment explaining it.


Minor Issues

5. Inconsistent Access Modifier - STYLE

Location: mod.ts:198

Changed from pegboardWebSocket (private) to __pegboardWebSocket (public but name-mangled). While this is necessary for the type predicate to work across classes, it is inconsistent with TypeScript privacy conventions.

Consideration: This is acceptable given the type predicate requirement, but document why it is public in a comment.

6. Missing Test Coverage - TESTING

No tests appear to cover the new buffering logic. Consider adding tests for: messages buffered when disconnected, messages sent on reconnection, buffer behavior during rapid connect/disconnect cycles, and buffer overflow scenarios.


Security Concerns

No significant security issues identified. The buffering mechanism does not introduce new attack vectors.


Performance Considerations

  1. Resend Performance: If many messages are buffered, the resend loop (tunnel.ts:92-94) processes them synchronously. For very large buffers, this could cause a spike in processing time.

  2. Memory Usage: Each buffered message stores three IDs. Estimate ~100-200 bytes per buffered message. 10,000 buffered messages is approximately 1-2MB, which is reasonable.


Recommendations Summary

  • HIGH: Unbounded buffer growth - Add max buffer size with FIFO eviction
  • MEDIUM: Missing buffer cleanup - Clear buffer in shutdown()
  • MEDIUM: Message ordering with missing actors - Document or add re-buffering logic
  • LOW: Add test coverage - Write tests for buffering scenarios
  • LOW: Document public WebSocket field - Add comment explaining __pegboardWebSocket visibility

Approval Status

The core implementation is solid and follows good patterns. However, I recommend addressing the unbounded buffer growth issue before merging, as it could cause production issues under poor network conditions. The other issues can be addressed in follow-up PRs if needed.

Suggested action: Add a maximum buffer size limit and explicitly clear the buffer on shutdown, then this PR is ready to merge.

@graphite-app
Copy link
Contributor

graphite-app bot commented Nov 21, 2025

Merge activity

  • Nov 21, 2:40 AM UTC: NathanFlurry added this pull request to the Graphite merge queue.
  • Nov 21, 2:42 AM UTC: CI is running for this pull request on a draft pull request (#3515) due to your merge queue CI optimization settings.
  • Nov 21, 2:43 AM UTC: Merged by the Graphite merge queue via draft PR: #3515.

@graphite-app graphite-app bot closed this Nov 21, 2025
@graphite-app graphite-app bot deleted the 11-20-chore_rivetkit_buffer_outbound_tunnel_messages branch November 21, 2025 02:43
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