Skip to content

fix(envoy): use global instance, add signal handlers#4565

Merged
MasterPtato merged 1 commit intomainfrom
04-06-fix_envoy_use_global_instance_add_signal_handlers
Apr 8, 2026
Merged

fix(envoy): use global instance, add signal handlers#4565
MasterPtato merged 1 commit intomainfrom
04-06-fix_envoy_use_global_instance_add_signal_handlers

Conversation

@MasterPtato
Copy link
Copy Markdown
Contributor

Description

Please include a summary of the changes and the related issue. Please also include relevant motivation and context.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

@railway-app
Copy link
Copy Markdown

railway-app bot commented Apr 6, 2026

🚅 Deployed to the rivet-pr-4565 environment in rivet-frontend

Service Status Web Updated (UTC)
frontend-inspector ❌ Build Failed (View Logs) Web Apr 8, 2026 at 8:58 pm
frontend-cloud ❌ Build Failed (View Logs) Web Apr 8, 2026 at 8:58 pm
kitchen-sink ❌ Build Failed (View Logs) Web Apr 8, 2026 at 8:57 pm
mcp-hub ✅ Success (View Logs) Web Apr 6, 2026 at 8:22 pm
website ❌ Build Failed (View Logs) Web Apr 6, 2026 at 8:07 pm
ladle ❌ Build Failed (View Logs) Web Apr 6, 2026 at 8:07 pm

@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-4565 April 6, 2026 19:54 Destroyed
@claude
Copy link
Copy Markdown

claude bot commented Apr 6, 2026

Code Review

Overall: This PR simplifies the envoy client by introducing a global singleton and OS signal handlers, removing per-actor serverless shutdown tracking. The direction is correct, but there are a few things worth addressing.


Issues

1. notGlobal is negative/inverted naming
engine/sdks/typescript/envoy-client/src/config.ts

notGlobal?: boolean is a double-negative when used (notGlobal: true means "yes, use a new instance"). Consider isolated?: boolean or flipping to an opt-in: useGlobal?: boolean defaulting to true. Negative boolean flags are easy to misread.

2. Non-global instances get no signal handlers
engine/sdks/typescript/envoy-client/src/tasks/envoy/index.ts lines 126-133

Signal handlers (SIGINT/SIGTERM) are only registered when creating the global instance. If notGlobal: true is used (e.g. in tests), those instances will not be cleaned up on signal. If that's intentional, it should be documented in the notGlobal JSDoc.

3. GLOBAL_ENVOY is never cleared after shutdown

If handle.shutdown() is called and the process later calls startEnvoySync again (without notGlobal), it will return the already-shut-down handle. This is likely safe in practice since the process exits, but the stale state is worth guarding against or documenting.

4. Removed "Already started serverless actor" guard
engine/sdks/typescript/envoy-client/src/tasks/envoy/index.ts (renamed startServerlessActor)

The original startServerless had:

if (ctx.serverless) throw new Error("Already started serverless actor");
ctx.serverless = true;

The rename removes this guard entirely. Is there a replacement? Calling startServerlessActor twice on the same envoy handle would now silently start a second actor. If the global singleton means only one is ever started, that should be documented; otherwise the guard should be restored.

5. SSE abort no longer triggers shutdown
rivetkit-typescript/packages/rivetkit/src/drivers/engine/actor-driver.ts lines 514-522

The old code called this.shutdown(false) on SSE abort specifically because Rivet may not close the connection gracefully. The removed comment read:

"We cannot assume that the request will always be closed gracefully by Rivet."

Now an SSE abort just logs. What's the replacement mechanism? Without a shutdown call, a serverless actor whose SSE connection drops could run until it hits an unrelated timeout. If the ping loop's writeSSE throws on abort, that exits the function, but the envoy/actor itself isn't told to stop.

6. #envoyStopped is now dead code
rivetkit-typescript/packages/rivetkit/src/drivers/engine/actor-driver.ts

#envoyStopped is still created and resolved in onShutdown, but its .promise is never awaited anywhere after the removal of the post-loop block. This is dead code and can be removed along with #isEnvoyStopped if it's no longer read.

7. Removed "stopping" SSE event

The old code sent { event: "stopping" } when a serverless actor stopped naturally (via "serverless-early-exit" reason). If the caller on the other end of this SSE was listening for this event to trigger cleanup, removing it silently changes the protocol. Is this event handled by the Rivet gateway side? If so, the gateway should be updated accordingly.


Minor

  • serverlessStartPayload in config: The auto-queue logic that read config.serverlessStartPayload is removed from startEnvoySync. Is the serverlessStartPayload field still present in EnvoyConfig? If so it is dead config now.
  • Error message wording ("invalid serverless payload" instead of "invalid serverless body"): Good improvement, more consistent with the field name.
  • PromiseWithResolvers<void> vs <undefined>: Correct, void is semantically more accurate here.
  • Indentation fix in stopActor: Good catch.
  • Error message "Runtime already started as serverful": More accurate than "runner".

Summary

The core direction (global singleton + signal handlers) is sound and simplifies the lifecycle model. The main things to resolve before merging: clarify the guard removal for startServerlessActor, confirm the SSE-abort-without-shutdown behavior is intentional and safe, and clean up the now-unused #envoyStopped/#isEnvoyStopped fields.

@MasterPtato MasterPtato force-pushed the 04-05-chore_misc_fixes_add_pb_snapshot_test branch from de70131 to 4639183 Compare April 6, 2026 22:18
@MasterPtato MasterPtato force-pushed the 04-06-fix_envoy_use_global_instance_add_signal_handlers branch from 6c9af76 to 94f54ba Compare April 6, 2026 22:18
@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-4565 April 6, 2026 22:18 Destroyed
@MasterPtato MasterPtato mentioned this pull request Apr 6, 2026
11 tasks
@MasterPtato MasterPtato force-pushed the 04-05-chore_misc_fixes_add_pb_snapshot_test branch from 4639183 to fdd0c18 Compare April 7, 2026 01:30
@MasterPtato MasterPtato force-pushed the 04-06-fix_envoy_use_global_instance_add_signal_handlers branch from 94f54ba to ef85f3e Compare April 7, 2026 01:30
@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-4565 April 7, 2026 01:30 Destroyed
@MasterPtato MasterPtato mentioned this pull request Apr 7, 2026
11 tasks
@MasterPtato MasterPtato force-pushed the 04-06-fix_envoy_use_global_instance_add_signal_handlers branch from ef85f3e to 5bcccc7 Compare April 8, 2026 20:11
@MasterPtato MasterPtato force-pushed the 04-05-chore_misc_fixes_add_pb_snapshot_test branch from fdd0c18 to 17a60a7 Compare April 8, 2026 20:11
@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-4565 April 8, 2026 20:11 Destroyed
@MasterPtato MasterPtato force-pushed the 04-05-chore_misc_fixes_add_pb_snapshot_test branch from 17a60a7 to 85acf51 Compare April 8, 2026 20:14
@MasterPtato MasterPtato force-pushed the 04-06-fix_envoy_use_global_instance_add_signal_handlers branch from 5bcccc7 to 8d964a5 Compare April 8, 2026 20:14
@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-4565 April 8, 2026 20:14 Destroyed
Copy link
Copy Markdown
Contributor Author

MasterPtato commented Apr 8, 2026

Merge activity

  • Apr 8, 8:52 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Apr 8, 8:57 PM UTC: Graphite rebased this pull request as part of a merge.
  • Apr 8, 8:58 PM UTC: @MasterPtato merged this pull request with Graphite.

@MasterPtato MasterPtato changed the base branch from 04-05-chore_misc_fixes_add_pb_snapshot_test to graphite-base/4565 April 8, 2026 20:53
@MasterPtato MasterPtato changed the base branch from graphite-base/4565 to main April 8, 2026 20:55
@MasterPtato MasterPtato force-pushed the 04-06-fix_envoy_use_global_instance_add_signal_handlers branch from 8d964a5 to 5fdf3ad Compare April 8, 2026 20:56
@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-4565 April 8, 2026 20:56 Destroyed
@MasterPtato MasterPtato merged commit 9ed1677 into main Apr 8, 2026
11 of 20 checks passed
@MasterPtato MasterPtato deleted the 04-06-fix_envoy_use_global_instance_add_signal_handlers branch April 8, 2026 20:58
@MasterPtato MasterPtato mentioned this pull request Apr 9, 2026
11 tasks
@NathanFlurry NathanFlurry mentioned this pull request Apr 9, 2026
11 tasks
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.

1 participant