Skip to content

Conversation

@NathanFlurry
Copy link
Member

No description provided.

@vercel
Copy link

vercel bot commented Nov 3, 2025

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

Project Deployment Preview Comments Updated (UTC)
rivetkit-serverless Ready Ready Preview Comment Nov 4, 2025 7:00pm
3 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
rivet-cloud Ignored Ignored Nov 4, 2025 7:00pm
rivet-inspector Ignored Ignored Preview Nov 4, 2025 7:00pm
rivet-site Ignored Ignored Preview Nov 4, 2025 7:00pm

Copy link
Member Author

NathanFlurry commented Nov 3, 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 3, 2025

Code Review: Correctly stringify engine runner request IDs for logs

Summary

This PR improves logging by replacing the bufferToString function (which used base64 encoding) with idToStr (which properly formats UUIDs as strings). This is a valuable improvement for debugging and observability.

Positive Aspects ✅

  1. Improved Logging Clarity: Converting UUIDs from base64 to proper UUID string format significantly improves log readability and debugging experience.

  2. Consistent Naming: The rename from bufferToString to idToStr is more semantic and clearly indicates the function's purpose.

  3. Enhanced Debug Logging: Added new debug log statements (e.g., "send tunnel msg" at line 87-92 in tunnel.ts) that will help with troubleshooting tunnel message flows.

  4. Code Quality Improvements: Several formatting improvements and fixes:

    • Consistent use of const over let (lines 307, 609)
    • Better code organization with block scoping for switch cases
    • Removed empty lines (lines 624-625)
  5. Centralized Implementation: Moving the idToStr function to utils.ts promotes reusability across the codebase.

Issues & Concerns 🔍

1. Logic Error in Acknowledgment Handling (Critical)

Location: tunnel.ts:267-279

const pending = this.#pendingTunnelMessages.get(messageIdStr);
if (pending) {
    const didDelete = this.#pendingTunnelMessages.delete(messageIdStr);
    if (!didDelete) {
        logger()?.warn({
            msg: "received tunnel ack for nonexistent message",
            requestId: requestIdStr,
            messageId: messageIdStr,
        });
    }
}

Problem: This code checks if pending exists, then attempts to delete it, and warns if the delete fails. However, if pending exists, the delete should always succeed. This warning will never trigger in the intended scenario.

Suggested fix: The logic should be restructured:

const didDelete = this.#pendingTunnelMessages.delete(messageIdStr);
if (!didDelete) {
    logger()?.warn({
        msg: "received tunnel ack for nonexistent message",
        requestId: requestIdStr,
        messageId: messageIdStr,
    });
}

Or if you want to keep the check:

const pending = this.#pendingTunnelMessages.get(messageIdStr);
if (!pending) {
    logger()?.warn({
        msg: "received tunnel ack for nonexistent message",
        requestId: requestIdStr,
        messageId: messageIdStr,
    });
} else {
    this.#pendingTunnelMessages.delete(messageIdStr);
}

2. Missing UUID Package Dependency Verification

The PR adds uuid package to rivetkit/package.json, but it's already imported in tunnel.ts. Consider verifying that:

  • The uuid package is properly added to all necessary packages
  • Version consistency across the monorepo is maintained
  • The import in engine/sdks/typescript/runner/src/tunnel.ts has access to this dependency

3. Incomplete Import Updates

Location: actor-driver.ts:32-36

The PR adds imports for RivetEvent and RivetMessageEvent:

import type {
    RivetEvent,
    RivetMessageEvent,
    UniversalWebSocket,
} from "@/common/websocket-interface";

However, these types don't appear to be used in the visible diff. Consider:

  • Are these imports necessary for this PR?
  • If they're needed for future changes, they should be in a separate commit
  • If they're genuinely needed, ensure they're actually used in the file

Minor Suggestions 💡

  1. Logging Consistency: Consider using consistent message prefixes across all tunnel logging. You have "send tunnel msg", "receive tunnel msg", "ack tunnel msg", "ack ws msg" - this is good and consistent.

  2. Error Message Clarity: The message "received tunnel ack for nonexistent message" could be more descriptive. Consider adding context about whether this indicates a potential race condition or duplicate ack.

  3. Performance Consideration: The idToStr function is called frequently in hot paths (every message send/receive). While uuidstringify is relatively fast, consider if caching stringified IDs would be beneficial for frequently logged request IDs.

Testing Recommendations 🧪

Per the CLAUDE.md guidelines, when running tests, consider:

  1. Piping test output to a file in /tmp/
  2. Grepping for the new log messages to verify they're being generated correctly
  3. Validating that the UUID format in logs is now human-readable

Example test verification:

cargo test -p rivetkit 2>&1 | tee /tmp/test_output.log
grep "send tunnel msg" /tmp/test_output.log
grep "receive tunnel msg" /tmp/test_output.log

Security & Performance ✓

  • No security concerns identified: The change from base64 to UUID string format doesn't introduce security issues
  • No significant performance impact: Both encoding methods are O(n) with similar performance characteristics
  • Memory usage: Slightly better memory usage with proper UUID string format vs base64

Overall Assessment

This is a valuable improvement for observability and debugging. The main concern is the logic error in the acknowledgment handling code that should be addressed before merging. Once that's fixed, this PR will meaningfully improve the developer experience when debugging tunnel message flows.

Recommendation: Request changes to fix the acknowledgment logic, verify the unused imports, and then approve.

@NathanFlurry NathanFlurry force-pushed the 11-03-chore_rivetkit_correctly_stringify_engine_runner_request_ids_for_logs branch from cad68b3 to 6079f1f Compare November 4, 2025 00:36
@NathanFlurry NathanFlurry force-pushed the 11-03-fix_rivetkit_ack_ws_messages branch from f1efe27 to 7b1fd28 Compare November 4, 2025 00:36
@claude
Copy link

claude bot commented Nov 4, 2025

Code Review

Summary

This PR improves logging for the engine runner by correctly stringifying request IDs and message IDs using the uuid library's stringify function instead of base64 encoding. This makes logs more readable and consistent with UUID formatting standards.

Positive Changes ✅

  1. Improved Logging Readability: Converting from base64 encoding to proper UUID string formatting makes logs much easier to read and debug.

  2. Consistent Naming: The rename from bufferToString to idToStr better conveys the intent - these are UUID identifiers, not arbitrary buffers.

  3. Enhanced Debug Logging: Added comprehensive debug logging in tunnel.ts for both sending and receiving tunnel messages, which will greatly aid in debugging connection issues.

  4. Code Quality Improvements: Several formatting improvements align with project standards (proper indentation, better line breaks).

  5. Proper Dependency Management: Added uuid as an explicit dependency in rivetkit/package.json.

Issues & Concerns ⚠️

1. Potential Logic Error in Acknowledgment Handling (tunnel.ts:265-277)

if (pending) {
    const didDelete = this.#pendingTunnelMessages.delete(messageIdStr);
    if (!didDelete) {
        logger()?.warn({
            msg: "received tunnel ack for nonexistent message",
            requestId: requestIdStr,
            messageId: messageIdStr,
        });
    }
}

Issue: This logic is contradictory. If pending is truthy (meaning the message exists in the map), then delete() should always return true. The warning will never fire in the current structure.

Recommendation: Either:

  • Remove the nested check entirely: if (pending) { this.#pendingTunnelMessages.delete(messageIdStr); }
  • Or move the warning outside: check if !pending to warn about non-existent messages

2. Empty Function Bodies (tunnel.ts:373-374)

resolve: () => {},
reject: () => {},

Question: Are these intentionally no-ops? This seems like it could hide errors. If a request fails here, callers won't be notified. Consider adding a comment explaining why these are empty or whether they should have implementations.

3. Missing Type Safety in WebSocket Imports (actor-driver.ts:32-36)

The imports RivetEvent and RivetMessageEvent are added but not visibly used in the diff. Were these needed for something that was later removed, or are they used outside the diff context?

4. Unused Import (actor-driver.ts:48)

import { idToStr } from "@/utils";

This import is added but only used once in the file at line 472. While not a problem, it's worth verifying that this is the intended final usage.

Performance Considerations

UUID String Conversion: The change from base64 to UUID string formatting using uuidstringify should have negligible performance impact. However, this function is now called more frequently due to added logging. Consider:

  • Lazy evaluation of log strings if the logger level would skip debug logs
  • Caching stringified IDs if the same IDs are logged multiple times

Code Style & Best Practices

Good: Follows project conventions for lowercase log messages
Good: Uses structured logging with proper field names
Good: Preserves hard tabs as specified in CLAUDE.md
⚠️ Note: Some formatting changes (line breaks, spacing) are present - ensure these align with project formatter settings

Security Considerations

No security concerns identified. The change is purely about how identifiers are formatted for logging.

Test Coverage

Missing: No test files found for tunnel.ts or actor-driver.ts. Consider adding tests for:

  • UUID string conversion in idToStr()
  • Message acknowledgment logic
  • Edge cases around empty/invalid ArrayBuffers

Recommendations

  1. High Priority: Fix the acknowledgment logic bug (Issue [SVC-2555] Set up issue templates #1)
  2. Medium Priority: Review and document the empty resolve/reject functions (Issue [SVC-2479] Send cluster events to PostHog #2)
  3. Low Priority: Consider adding unit tests for the new idToStr utility function
  4. Low Priority: Verify unused imports are intentional

Overall Assessment

This is a solid improvement to logging infrastructure that will make debugging much easier. The main concern is the potential logic error in acknowledgment handling that should be addressed before merging. Otherwise, the changes are well-structured and follow project conventions.

Recommendation: Request changes to address the acknowledgment logic issue, then approve.

@claude
Copy link

claude bot commented Nov 4, 2025

Code Review for PR #3330

Overview

This PR improves request ID logging in the RivetKit engine runner by correctly stringifying RequestId and MessageId (which are ArrayBuffer types) to UUID strings using the uuid library's stringify function.


Positive Changes

1. Correct UUID Stringification

  • The change from bufferToString() (which used base64 encoding) to idToStr() (which uses uuid.stringify()) is correct and improves log readability
  • UUIDs are now properly formatted as xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx instead of base64 strings
  • This makes debugging and log correlation much easier

2. Improved Code Organization

  • Consolidating the idToStr() utility function in rivetkit-typescript/packages/rivetkit/src/utils.ts improves code reuse
  • The function is now shared across both the runner and actor-driver code
  • Proper dependency added to package.json for the uuid library

3. Enhanced Logging

  • Added a new debug log when sending tunnel messages (engine/sdks/typescript/runner/src/tunnel.ts:88-92) which improves observability
  • Updated all existing log statements to use the new idToStr() function for consistency

Issues Found

1. Logic Error in Tunnel Acknowledgment Handling ⚠️

In tunnel.ts:266-280, there's a logic issue:

const pending = this.#pendingTunnelMessages.get(messageIdStr);
if (pending) {
    const didDelete = this.#pendingTunnelMessages.delete(messageIdStr);
    if (!didDelete) {
        logger()?.warn({
            msg: "received tunnel ack for nonexistent message",
            requestId: requestIdStr,
            messageId: messageIdStr,
        });
    }
}

Problem: The didDelete check will always return true if we're inside the if (pending) block. The Map.delete() method returns false only if the key doesn't exist, but we already verified it exists with get(). This warning will never be triggered.

Suggested fix: Remove the redundant delete check or move the warning outside the if (pending) block:

const didDelete = this.#pendingTunnelMessages.delete(messageIdStr);
if (!didDelete) {
    logger()?.warn({
        msg: "received tunnel ack for nonexistent message",
        requestId: requestIdStr,
        messageId: messageIdStr,
    });
}

Minor Code Quality Observations

2. Formatting Changes ℹ️

Several formatting changes (like line breaks, spacing) are present throughout the PR. According to CLAUDE.md:

  • The repo uses hard tabs for Rust (but this is TypeScript)
  • Pre-commit hooks handle formatting
  • Developers should not run formatters manually

These auto-formatting changes are generally acceptable but add noise to the diff. Consider whether your IDE is auto-formatting on save.

3. Variable Declaration Style ℹ️

In tunnel.ts:312, the change from let _unhandled to const _unhandled is good:

const _unhandled = await this.#handleWebSocketMessage(

The _ prefix suggests the variable is intentionally unused, so const is more appropriate than let.


Performance & Security

Performance: ✅ No concerns. The uuid.stringify() function is efficient and the changes don't introduce any performance regressions.

Security: ✅ No concerns. The changes are purely cosmetic/logging improvements and don't affect security boundaries.


Test Coverage

Observation: No test files were modified in this PR. Consider adding tests to verify:

  • idToStr() correctly converts ArrayBuffer UUIDs to string format
  • Log messages contain properly formatted request/message IDs
  • The tunnel acknowledgment logic works correctly (especially given the issue noted above)

Summary

Approve with suggested fix: This PR makes a valuable improvement to logging clarity, but should address the logic issue in the tunnel acknowledgment handling before merging.

Action Items:

  1. ⚠️ Fix the tunnel acknowledgment logic error at tunnel.ts:266-280
  2. ✅ Consider adding unit tests for idToStr()
  3. ℹ️ (Optional) Review auto-formatting settings to reduce diff noise

Overall, this is a solid improvement that will make debugging significantly easier! 🚀

@claude
Copy link

claude bot commented Nov 4, 2025

PR Review: Correctly stringify engine runner request IDs for logs

Summary

This PR improves logging consistency by replacing the custom bufferToString() function (which used base64 encoding) with a new idToStr() function that properly stringifies UUIDs using the uuid library's stringify method. This makes request and message IDs in logs human-readable UUID strings instead of base64-encoded values.

Positive Aspects

Code Quality:

  • ✅ The change improves log readability significantly - UUID strings are much easier to correlate across services than base64-encoded buffers
  • ✅ Consistent naming: idToStr() is clearer and more descriptive than bufferToString()
  • ✅ Good separation of concerns: utility function is properly placed in utils.ts and reused across files
  • ✅ Import ordering fix (alphabetical) aligns with best practices

Logging Improvements:

  • ✅ Added helpful debug logs for sending tunnel messages (line 87-92 in tunnel.ts)
  • ✅ Changed "tunnel msg" to "receive tunnel msg" for clarity
  • ✅ Consistent structured logging following tracing patterns from CLAUDE.md

Code Consistency:

  • ✅ Replaces all instances of bufferToString() with idToStr() throughout the codebase
  • ✅ Formatting improvements (better line breaks, consistent style)

Issues Found

Critical Issue - Logic Error:
🔴 Lines 267-277 in tunnel.ts: There's a potential logic bug in the TunnelAck handling:

const pending = this.#pendingTunnelMessages.get(messageIdStr);
if (pending) {
    const didDelete = this.#pendingTunnelMessages.delete(messageIdStr);
    if (!didDelete) {
        logger()?.warn({
            msg: "received tunnel ack for nonexistent message",
            requestId: requestIdStr,
            messageId: messageIdStr,
        });
    }
}

The logic here is incorrect. If pending exists (truthy), then the delete() operation should always succeed. The warning will never trigger because:

  1. If pending is truthy, the message exists in the map
  2. Therefore delete() will return true
  3. The warning branch (!didDelete) will never execute

This code should likely be:

const didDelete = this.#pendingTunnelMessages.delete(messageIdStr);
if (!didDelete) {
    logger()?.warn({
        msg: "received tunnel ack for nonexistent message",
        requestId: requestIdStr,
        messageId: messageIdStr,
    });
}

Or keep the existing logic if you want to avoid the warning, but the didDelete check is redundant.

Minor Issues

Unnecessary Variable Declaration:
⚠️ Line 315 in tunnel.ts: The underscore prefix on _unhandled suggests it's intentionally unused, but it's also assigned unnecessarily:

const _unhandled = await this.#handleWebSocketMessage(
    message.requestId,
    message.messageKind.val,
);

Consider just calling the function without assignment if the return value is truly unused:

await this.#handleWebSocketMessage(
    message.requestId,
    message.messageKind.val,
);

Formatting Changes:
⚠️ Note from CLAUDE.md: "Do not run ./scripts/cargo/fix.sh. Do not format the code yourself." - The formatting changes in this PR should be verified they weren't done manually but through the standard tooling.

Performance Considerations

No performance concerns:

  • uuid.stringify() is likely as fast or faster than base64 encoding
  • The change is purely representational (both methods produce unique strings)
  • No additional allocations or computational overhead

Security Considerations

No security issues:

  • UUIDs in logs don't expose sensitive information
  • Both base64 and UUID string representations have similar information disclosure properties
  • The change actually improves security debugging by making request tracing easier

Test Coverage

⚠️ Missing test coverage:

  • No tests appear to verify the new idToStr() function behavior
  • Consider adding unit tests to verify:
    • Correct UUID stringification
    • Handling of various ArrayBuffer inputs
    • Consistency with the engine's expected format

Recommendation: Add tests in the rivetkit test suite to verify UUID stringification matches expected format.

Dependencies

Dependency management:

  • uuid package (v12.0.0) properly added to package.json
  • Workspace dependencies correctly updated in pnpm-lock.yaml
  • Following the pattern from CLAUDE.md for dependency management

Recommendations

  1. Fix the critical logic bug in the TunnelAck handling (lines 267-277)
  2. Remove unused variable assignment for _unhandled or use the return value
  3. Consider adding unit tests for idToStr() function
  4. Verify formatting changes were made through approved tooling, not manual editing

Overall Assessment

This is a solid improvement for debugging and log readability. The main refactoring from bufferToString() to idToStr() is well-executed. However, the logic error in the TunnelAck handling should be addressed before merging.

Verdict: ⚠️ Approve with changes requested - fix the TunnelAck logic bug before merging.

@NathanFlurry NathanFlurry force-pushed the 11-03-fix_rivetkit_ack_ws_messages branch from 5f837ae to 9d011a4 Compare November 4, 2025 19:24
@NathanFlurry NathanFlurry force-pushed the 11-03-chore_rivetkit_correctly_stringify_engine_runner_request_ids_for_logs branch from 8d1d88d to 35bf113 Compare November 4, 2025 19:24
@vercel
Copy link

vercel bot commented Nov 4, 2025

Deployment failed with the following error:

Too many requests - try again in 4 minutes (more than 120, code: "api-deployments-flood-pro").

Learn More: https://vercel.com/docs/limits#rate-limits

@claude
Copy link

claude bot commented Nov 4, 2025

Pull Request Review

Summary

This PR improves logging for engine runner request IDs by properly stringifying UUID ArrayBuffers using the uuid library's stringify function instead of base64 encoding. This change makes logs more human-readable and consistent with standard UUID formatting.

Positive Aspects

Correct UUID Handling: The change from bufferToString (base64) to idToStr (UUID stringify) is the right approach for displaying UUIDs in logs. This makes debugging significantly easier.

Consistent Naming: Renaming bufferToString to idToStr better conveys the function's purpose - it's not just converting a buffer to a string, it's specifically formatting UUIDs.

Improved Logging: Added debug logging in key places (e.g., send tunnel msg, receive tunnel msg) which improves observability.

Code Consolidation: Consolidating the utility function in utils.ts and removing duplication is a good practice.

Proper Dependency: Adding uuid to package.json dependencies ensures the library is available.

Issues & Concerns

1. Logic Bug in Ack Handling (Critical)

Location: tunnel.ts:266-278

if (pending) {
    const didDelete = this.#pendingTunnelMessages.delete(messageIdStr);
    if (!didDelete) {
        logger()?.warn({
            msg: "received tunnel ack for nonexistent message",
            requestId: requestIdStr,
            messageId: messageIdStr,
        });
    }
}

Problem: The code checks if pending exists, then attempts to delete, but warns if delete fails. This logic is flawed because:

  • If pending exists, the delete should always succeed (the key exists in the map)
  • The warning will never be reached in this structure
  • If pending is null/undefined, we should warn but don't

Recommendation: Simplify to:

const pending = this.#pendingTunnelMessages.get(messageIdStr);
if (pending) {
    this.#pendingTunnelMessages.delete(messageIdStr);
} else {
    logger()?.warn({
        msg: "received tunnel ack for nonexistent message",
        requestId: requestIdStr,
        messageId: messageIdStr,
    });
}

Or if you want to keep the deletion check:

const didDelete = this.#pendingTunnelMessages.delete(messageIdStr);
if (!didDelete) {
    logger()?.warn({
        msg: "received tunnel ack for nonexistent message",
        requestId: requestIdStr,
        messageId: messageIdStr,
    });
}

2. Formatting Changes Mixed with Logic Changes

The PR mixes formatting changes (prettier/auto-formatting) with the actual logic changes. This makes the diff harder to review. Examples:

  • Line breaks in function parameters
  • Reformatting of ternary operators
  • Changes to arrow function formatting

Recommendation: According to CLAUDE.md, you should not run formatting commands. These changes suggest auto-formatting was applied. Consider separating formatting from logic changes in future PRs.

3. Unnecessary Variable Reassignment

Location: tunnel.ts:312

case "ToClientWebSocketMessage": {
    this.#sendAck(message.requestId, message.messageId);
    
    const _unhandled = await this.#handleWebSocketMessage(
        message.requestId,
        message.messageKind.val,
    );
    break;
}

The let _unhandled was changed to const _unhandled which is good, but the variable is never used. The underscore prefix suggests it's intentionally unused.

Question: Is this return value important for future use, or can it be removed entirely?

4. Test Coverage

No tests were added or modified in this PR.

Recommendation: Given that this changes logging behavior and ID stringification, consider adding a test that:

  • Verifies idToStr correctly formats UUIDs
  • Ensures the stringified IDs are valid UUIDs
  • Validates the format matches expected UUID string format

Minor Observations

  1. Import Order: The import order change (stringify before v4) is stylistic but consistent with alphabetical ordering - good practice.

  2. Removed Empty Lines: Two empty lines removed at tunnel.ts:596-597 - good cleanup.

  3. Block Scoping: Adding block scope to the ToClientWebSocketMessage case is good practice to avoid variable leakage.

Security Considerations

✅ No security concerns identified. The change from base64 to UUID string formatting doesn't introduce vulnerabilities.

Performance Considerations

✅ Minimal performance impact. uuidstringify should have similar performance to base64 encoding. The added logging may have a small impact but only when debug logging is enabled.

Recommendations

High Priority:

  1. Fix the ack handling logic bug (see issue [SVC-2555] Set up issue templates #1)

Medium Priority:
2. Add tests for the idToStr function
3. Consider removing unused _unhandled variable or document why it needs to be captured

Low Priority:
4. In future PRs, avoid mixing formatting changes with logic changes

Overall Assessment

This is a good improvement for developer experience and debugging. The main issue is the logic bug in the ack handling that should be addressed before merging. Otherwise, the changes properly implement UUID stringification for better log readability.


🤖 Generated by Claude Code

@graphite-app
Copy link
Contributor

graphite-app bot commented Nov 4, 2025

Merge activity

  • Nov 4, 8:09 PM UTC: NathanFlurry added this pull request to the Graphite merge queue.
  • Nov 4, 8:11 PM UTC: CI is running for this pull request on a draft pull request (#3349) due to your merge queue CI optimization settings.
  • Nov 4, 8:41 PM UTC: The Graphite merge queue removed this pull request due to removal of a downstack PR #3342.
  • Nov 4, 8:52 PM UTC: NathanFlurry added this pull request to the Graphite merge queue.
  • Nov 4, 8:53 PM UTC: CI is running for this pull request on a draft pull request (#3353) due to your merge queue CI optimization settings.
  • Nov 4, 8:56 PM UTC: Merged by the Graphite merge queue via draft PR: #3353.

@NathanFlurry NathanFlurry force-pushed the 11-03-chore_rivetkit_correctly_stringify_engine_runner_request_ids_for_logs branch from 35bf113 to 2e78d0d Compare November 4, 2025 20:25
@NathanFlurry NathanFlurry force-pushed the 11-03-fix_rivetkit_ack_ws_messages branch from 9d011a4 to 0298a50 Compare November 4, 2025 20:25
@vercel
Copy link

vercel bot commented Nov 4, 2025

Deployment failed with the following error:

Too many requests - try again in 5 minutes (more than 120, code: "api-deployments-flood-pro").

Learn More: https://vercel.com/docs/limits#rate-limits

@claude
Copy link

claude bot commented Nov 4, 2025

Code Review

Summary

This PR improves logging for engine runner request IDs by replacing base64 encoding with proper UUID string formatting. The change makes logs more readable and debuggable.

Positive Changes ✅

  1. Improved Log Readability: Converting from base64-encoded strings to proper UUID format makes logs significantly more readable and easier to correlate across systems.

    • Before: YWJjZGVmZ2hpamtsbW5vcA==
    • After: 550e8400-e29b-41d4-a716-446655440000
  2. Consistent Naming: The rename from bufferToString to idToStr better reflects the actual purpose of the function (converting UUID buffers to strings).

  3. Enhanced Debug Logging: Added structured debug logs when sending tunnel messages (engine/sdks/typescript/runner/src/tunnel.ts:87-92) which will help with troubleshooting.

  4. Code Cleanup: Several formatting improvements and removal of redundant conversions throughout tunnel.ts.

  5. Proper Dependency Management: Added uuid package to rivetkit's package.json instead of relying on transitive dependencies.

Issues & Concerns 🔍

1. Logic Error in Tunnel Ack Handler (tunnel.ts:267-278)

There's a problematic code block:

const pending = this.#pendingTunnelMessages.get(messageIdStr);
if (pending) {
    const didDelete = this.#pendingTunnelMessages.delete(messageIdStr);
    if (!didDelete) {
        logger()?.warn({
            msg: "received tunnel ack for nonexistent message",
            requestId: requestIdStr,
            messageId: messageIdStr,
        });
    }
}

Problem: The warning will never fire because it's inside the if (pending) block. If pending exists, the delete will always succeed. The warning should either be moved outside the block to catch the case where pending doesn't exist, or removed entirely if it's redundant.

Suggestion:

const pending = this.#pendingTunnelMessages.get(messageIdStr);
if (pending) {
    this.#pendingTunnelMessages.delete(messageIdStr);
} else {
    logger()?.warn({
        msg: "received tunnel ack for nonexistent message",
        requestId: requestIdStr,
        messageId: messageIdStr,
    });
}

2. Breaking Change Risk

The switch from base64 to UUID strings could be a breaking change if:

  • Any external systems or logs are parsing these IDs expecting base64 format
  • There are stored references to these IDs in databases or caches
  • External monitoring/alerting tools have patterns matching the old format

Recommendation: Consider if this warrants a minor version bump and release notes mentioning the log format change.

3. Unused Import (actor-driver.ts:32-36)

import type {
    RivetEvent,
    RivetMessageEvent,
    UniversalWebSocket,
} from "@/common/websocket-interface";

The RivetEvent and RivetMessageEvent types appear to be added but never used in the file. If they're not needed, they should be removed.

Suggestions 💡

  1. Add Unit Test: Consider adding a test case that validates the UUID string format output from idToStr():

    test('idToStr converts UUID buffer to standard UUID string format', () => {
        const buffer = new Uint8Array([/* known UUID bytes */]).buffer;
        const result = idToStr(buffer);
        expect(result).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/);
    });
  2. Document the Change: Add a comment above idToStr explaining that it converts UUID buffers (ArrayBuffer/Uint8Array) to standard UUID string format for logging purposes.

  3. Performance Consideration: The uuidstringify function is called frequently in hot paths (every tunnel message). While unlikely to be a bottleneck, consider profiling if this becomes a concern in high-throughput scenarios.

Security & Performance ✓

  • No security concerns identified: The change doesn't introduce any security vulnerabilities
  • Performance impact: Negligible - UUID string conversion is fast
  • Memory impact: Minimal - UUID strings are slightly shorter than base64 (36 vs ~24 chars but UUIDs are more human-readable)

Test Coverage 📋

  • No new tests added for the idToStr function
  • Existing tests should still pass as this is primarily a logging change
  • Recommendation: Add tests to verify UUID string format output

Conclusion

This is a solid improvement to logging that will make debugging easier. The main issue to address is the logic error in the tunnel ack handler. After fixing that, this PR should be good to merge.

Approval Status: Request changes to fix the tunnel ack handler logic issue.

@claude
Copy link

claude bot commented Nov 4, 2025

PR Review: chore(rivetkit): correctly stringify engine runner request ids for logs

Summary

This PR refactors the ID stringification logic across the tunnel and actor driver code, replacing the base64-based bufferToString function with a UUID-specific idToStr function that uses the uuid library's stringify method. This provides more readable and standard UUID formatting in logs.

✅ Positives

  1. Improved Readability: Converting request IDs to standard UUID format (hyphenated) instead of base64 makes logs significantly more readable and debuggable
  2. Consistent Naming: The rename from bufferToString to idToStr better reflects the function's purpose - converting ArrayBuffer UUIDs to strings
  3. Code Consolidation: Moving idToStr to the shared utils.ts file reduces duplication between tunnel.ts and actor-driver.ts
  4. Enhanced Logging: Added debug logging at line 87-92 in tunnel.ts when sending tunnel messages, which will help with debugging tunnel communication
  5. Code Style Improvements: The PR includes several formatting improvements (spacing, line breaks) that improve code readability

🔍 Observations & Potential Issues

1. Performance Consideration - UUID String Allocation

Location: tunnel.ts:80-85, 255-260

The new implementation creates UUID strings eagerly even when logging is disabled:

const requestIdStr = idToStr(requestId);
const messageIdStr = idToStr(messageId);
logger()?.debug({
    msg: "send tunnel msg",
    requestId: requestIdStr,
    messageId: messageIdStr,
    message: messageKind,
});

Recommendation: Consider lazy evaluation when logger is optional:

if (logger()) {
    logger().debug({
        msg: "send tunnel msg",
        requestId: idToStr(requestId),
        messageId: idToStr(messageId),
        message: messageKind,
    });
}

This avoids unnecessary UUID string allocations in production when debug logging is disabled.

2. Inconsistent Error Handling

Location: tunnel.ts:265-274

The code checks if a message was deleted and logs a warning if it wasn't, but this seems contradictory:

const didDelete = this.#pendingTunnelMessages.delete(messageIdStr);
if (!didDelete) {
    logger()?.warn({
        msg: "received tunnel ack for nonexistent message",
        requestId: requestIdStr,
        messageId: messageIdStr,
    });
}

However, this logic is placed inside if (pending), meaning pending exists but delete failed. This scenario shouldn't be possible with a Map. The logic should probably be:

const pending = this.#pendingTunnelMessages.get(messageIdStr);
if (pending) {
    this.#pendingTunnelMessages.delete(messageIdStr);
} else {
    logger()?.warn({
        msg: "received tunnel ack for nonexistent message",
        requestId: requestIdStr,
        messageId: messageIdStr,
    });
}

3. Missing uuid Dependency Documentation

The PR adds uuid: ^12.0.0 to rivetkit's package.json but the TypeScript runner package (engine/sdks/typescript/runner) already imports from uuid without it being in its package.json. This might be relying on transitive dependencies which could cause issues.

Recommendation: Verify that all packages importing uuid have it listed in their dependencies.

4. Unrelated Formatting Changes

Location: Multiple locations throughout tunnel.ts

The PR includes many unrelated formatting changes (empty function bodies changed from () => { } to () => {}, line breaks added). While these improve consistency, they make the diff harder to review.

Per CLAUDE.md:

Do not run ./scripts/cargo/fix.sh. Do not format the code yourself.

Recommendation: Keep formatting changes separate from functional changes in future PRs.

🧪 Testing

Missing Test Coverage: There are no test files for the tunnel functionality. Given that this changes how IDs are stringified throughout the system, tests would be valuable to ensure:

  • UUID formatting is correct
  • IDs are properly stringified in all code paths
  • The new debug logging works as expected

Recommendation: Consider adding tests for idToStr function and the tunnel message flow.

🔒 Security

No security concerns identified. The change from base64 to UUID string representation doesn't introduce security issues.

📊 Performance

Minor performance considerations:

  • UUID stringification via uuidstringify may have different performance characteristics than base64 encoding, but both are fast operations
  • The main concern is the eager string allocation mentioned above

✨ Suggestions

  1. Fix the inconsistent delete check logic at tunnel.ts:265-274
  2. Consider lazy evaluation for debug log string formatting
  3. Verify uuid dependency is correctly declared in all consuming packages
  4. Add tests for the refactored ID stringification logic
  5. Consider separating formatting changes from functional changes in future PRs

Overall Assessment

This is a good quality refactoring that improves log readability and code organization. The functional changes are solid, though there's a minor logic issue with the delete check that should be addressed. The addition of debug logging is helpful. Main suggestions are around performance optimization for logging and fixing the delete check logic.

Recommendation: ✅ Approve with minor suggested improvements

@graphite-app graphite-app bot closed this Nov 4, 2025
@graphite-app graphite-app bot deleted the 11-03-chore_rivetkit_correctly_stringify_engine_runner_request_ids_for_logs branch November 4, 2025 20:56
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.

3 participants