-
Notifications
You must be signed in to change notification settings - Fork 129
fix(runner): do not send websocket close on tunnel shutdown since pegboard-runner takes care of this #3385
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
3 Skipped Deployments
|
3e95003 to
a232088
Compare
fb0fa44 to
30a829e
Compare
PR Review: Fix WebSocket Close on Tunnel ShutdownOverviewThis PR addresses an issue where the TypeScript runner was attempting to send WebSocket close messages during tunnel shutdown, even though the Pegboard WebSocket is already closed at that point. The fix appropriately delegates teardown logic to pegboard-runner. Code Quality & Best PracticesStrengths:
Issues Found:
Potential BugsSilent Error Suppression (tunnel.ts:427-428) if (error instanceof RunnerShutdownError) {
this.log?.debug({ msg: "catught runner shutdown error" });
}During shutdown, if a fetch handler throws a
Recommendation: Verify that this is the intended behavior. If the pegboard WebSocket is already closed, sending a response would fail anyway, but it might be worth adding a comment explaining why no response is sent. Performance Considerations✅ No performance concerns. The changes are minimal and occur during shutdown, which is not a hot path. Security Concerns✅ No security issues identified. The changes improve correctness by preventing attempts to send data over a closed WebSocket. Test CoverageI don't see any test files in this PR. Given that this fixes a specific shutdown race condition, consider adding tests for:
Example test structure: describe('Tunnel shutdown', () => {
it('should not send WebSocket close messages during shutdown', async () => {
// Setup tunnel with mock WebSocket
// Call shutdown()
// Verify no tunnel messages were sent
});
it('should reject pending requests with RunnerShutdownError', async () => {
// Setup tunnel with pending request
// Call shutdown()
// Verify request was rejected with RunnerShutdownError
});
});Additional NotesGood Context Reference: The link to pegboard-runner code (line 79) is helpful but uses a specific commit hash ( SummaryThis is a solid fix that addresses a real issue in the shutdown sequence. The main action items are:
Overall: Approve with minor fixes recommended ✅ |
More templates
@rivetkit/actor
@rivetkit/cloudflare-workers
@rivetkit/core
@rivetkit/db
@rivetkit/framework-base
@rivetkit/next-js
@rivetkit/react
rivetkit
@rivetkit/sql-loader
@rivetkit/engine-runner
@rivetkit/engine-runner-protocol
commit: |
PR Review: Fix WebSocket Close Handling on Runner ShutdownSummaryThis PR fixes a race condition where the TypeScript runner was attempting to send WebSocket close messages over the Pegboard tunnel after the connection had already been closed by pegboard-runner. The fix introduces proper shutdown handling that avoids sending messages over a closed connection while still properly cleaning up local state. Code Quality ✅Good Practices:
Improvements Made:
Potential Issues 🔍1. Typo in Log Message (line 428): this.log?.debug({ msg: "catught runner shutdown error" });Should be: 2. TODO Comment Needs Clarification (line 81-82): // TODO: Trigger close event, but do not send anything over the tunnel
ws.__closeWithoutCallback(1000, "ws.tunnel_shutdown");The current implementation does trigger the close event via 3. Missing Close Event Trigger:
Architecture Considerations 💡Shutdown Flow:
This is a good architectural decision. Error Handling Pattern:
Performance Considerations ⚡
Security Concerns 🔒
Test Coverage 📋Current Tests:
Recommendations:
Suggested ChangesRequired:
Recommended:
Verdict: ✅ Approve with Minor FixesThis is a solid fix for a real race condition. The approach is sound and the implementation is clean. The only required change is fixing the typo. The recommended changes would improve code quality but are not blockers. Impact: Low risk - This prevents errors during shutdown without changing happy-path behavior. Review generated by Claude Code |
Code ReviewSummaryThis PR addresses a WebSocket cleanup issue during runner shutdown by preventing the TypeScript runner from sending close messages over a WebSocket that's already been closed by pegboard-runner. The approach uses a new custom error type and a flag to control callback behavior. Positive Aspects✅ Good problem identification: The PR correctly identifies that the Pegboard WS is already closed during shutdown, so attempting to send messages is pointless Issues & Suggestions1. Typo in error handling (tunnel.ts:428)this.log?.debug({ msg: "catught runner shutdown error" });Should be: 2. Incomplete TODO comment (tunnel.ts:81-82)// TODO: Trigger close event, but do not send anything over the tunnel
ws.__closeWithoutCallback(1000, "ws.tunnel_shutdown");The TODO says "Trigger close event" but the code already does trigger the close event (via
3. Error handling logic may be overly broad (tunnel.ts:427-436)The
Recommendation: if (error instanceof RunnerShutdownError) {
this.log?.debug({
msg: "caught runner shutdown error",
requestId: idToStr(requestId),
actorId: req.actorId
});
} else {
// ... existing error handling
}4. API design concern: Double-underscore prefixThe new
Consider:
5. Race condition considerationDuring shutdown, the code rejects all pending requests with
The code looks correct, but a comment explaining that pegboard-runner has already closed the connection (so no new messages can arrive) would be helpful. 6. Test coverageNo test changes are included. Consider adding tests for:
Performance & Security✅ No performance concerns - the changes are minimal and in cleanup paths Best Practices (per CLAUDE.md)✅ Uses structured logging with tracing-style approach (though this is TypeScript, not Rust) RecommendationApprove with minor changes: Fix the typo, clarify/remove the TODO, and consider adding basic test coverage for the shutdown path. The core logic is sound and addresses a real issue with attempting to send messages over a closed WebSocket during shutdown. |
a232088 to
d5276a3
Compare
30a829e to
f612c0f
Compare
Code Review for PR #3385SummaryThis PR fixes an issue where the TypeScript runner was incorrectly attempting to send WebSocket close messages over the tunnel during shutdown, even though the pegboard-runner WebSocket is already closed at that point. The changes properly handle the shutdown sequence by introducing a new error type and a close method that doesn't send messages over the tunnel. Positive Aspects✅ Good separation of concerns: The new Issues Found1. Typo in Error Handling (tunnel.ts:428)Severity: Low this.log?.debug({ msg: "catught runner shutdown error" });Should be Location: 2. TODO Comment Without Close Event Firing (tunnel.ts:81-82)Severity: Medium - Potential Bug // TODO: Trigger close event, but do not send anything over the tunnel
ws.__closeWithoutCallback(1000, "ws.tunnel_shutdown");The comment says "Trigger close event" but looking at
So the TODO comment is misleading - the close event is being triggered. Either:
Question for author: During runner shutdown, should the WebSocket adapters fire close events to user code, or should they silently close? The current implementation fires the event. Location: 3. Inconsistent Error Handling PatternSeverity: Low The
For consistency, if WebSocket handlers throw 4. Missing Type Safety for Close CodesSeverity: Low ws.__closeWithoutCallback(1000, "ws.tunnel_shutdown");WebSocket close codes have specific meanings per RFC 6455. Consider:
Location: Architectural Considerations5. Race Condition RiskSeverity: Medium The shutdown sequence (tunnel.ts:57-85):
If new requests arrive between steps 1-3, they could be accepted but never properly cleaned up. Consider:
6. Memory Leak PreventionSeverity: Low The shutdown clears:
But doesn't clear:
Is this intentional? If the tunnel is shutting down, pending acks will never arrive, so this map could be cleared too. Testing Concerns7. No Tests for New BehaviorSeverity: High The PR doesn't include tests for:
Recommendation: Add tests to test('shutdown rejects pending requests with RunnerShutdownError', async () => {
// Setup runner with pending request
// Call shutdown()
// Assert request rejected with RunnerShutdownError
});
test('shutdown closes websockets without tunnel messages', async () => {
// Setup runner with active WebSocket
// Mock tunnel message sending
// Call shutdown()
// Assert no tunnel messages sent
// Assert WS in CLOSED state
});Security Considerations✅ No security issues identified. The changes are internal refactoring and don't expose new attack surfaces. Performance Considerations✅ Performance impact is minimal/positive:
Recommendations SummaryMust Fix:
Should Fix: Consider: VerdictOverall: Approve with Minor Changes ✅ The core fix is sound - not sending WebSocket close messages over an already-closed tunnel prevents errors. However, the typo should be fixed and test coverage should be added before merging. The TODO comment needs clarification, and the architectural improvements (shutdown flag, pending message cleanup) would make the code more robust, though they're not blockers for this PR. Review generated by Claude Code following CLAUDE.md conventions |
PR Review: Fix runner websocket close on tunnel shutdownSummaryThis PR addresses a race condition where the TypeScript runner was sending WebSocket close messages over the tunnel during shutdown, even though the pegboard WebSocket connection had already been closed. The fix introduces a new error type and a conditional close method to prevent sending messages when the runner is shutting down. Code Quality & Best PracticesPositive aspects:
Issues identified:
Potential Bugs
Architecture & DesignGood design decisions:
Concerns:
Performance Considerations
Security Concerns
Test CoverageMissing test coverage:
Recommendations
Related Questions
Overall, this is a good fix for a specific race condition, but it would benefit from better test coverage and some minor polish around error messages and API design. |
…board-runner takes care of this
f612c0f to
f5907de
Compare
d5276a3 to
7a186f6
Compare
Merge activity
|
…board-runner takes care of this (#3385)

No description provided.