You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Summary of the change: tunnel_to_ws_task.rs now defers the gateway pubsub ack for ToEnvoyTunnelMessage-kind messages until after the message has been handed to the actor's WebSocket (via the new ordered_handoff helper), so a failed WS send surfaces as an unacked failure instead of silently acknowledging data the actor never received. On the actor-host side, envoy-client's handle_request_chunk (both in tunnel.rs and actor/http.rs) now sends an explicit error/abort response instead of silently dropping a request chunk that arrives without a matching request start, so the gateway doesn't hang waiting for a response that will never come. Good fix for the underlying race, and the new ordered_handoff unit tests cleanly isolate the core ordering guarantee (reply only after handoff succeeds, no reply if handoff fails).
A few things worth a look:
1. ACK_MSG_DURATION's meaning silently changes for the common case (engine/packages/pegboard-envoy/src/tunnel_to_ws_task.rs)
For ToEnvoyTunnelMessage (i.e. actual HTTP/WS tunnel traffic, presumably the bulk of gateway messages), ack_start is now captured before parsing, but the reply/ack doesn't happen until after the full match-block processing, serialization, and conn.ws_handle.send(...) complete. That's the same span already tracked by PROCESS_MSG_DURATION (which already included the WS send pre-PR), plus parse and reply overhead. So for tunnel messages, pegboard_envoy_ack_msg_duration (documented as "Time to deserialize and reply to an incoming ToEnvoyConn msg") now overlaps almost entirely with pegboard_envoy_process_msg_duration, whereas before the two were sequential and disjoint. Any dashboard/alert tuned to ACK_MSG_DURATION as a fast "did we ack the pubsub message" signal will see it balloon and start tracking actor WS throughput instead. Worth a one-line update to the metric help text (or splitting into a distinct metric for the deferred-ack path) so this isn't a silent surprise, and worth double-checking any existing alert thresholds built on the old semantics.
2. New error path in handle_request_chunk awaits a WS send inline in the shared per-connection dispatch loop (engine/sdks/rust/envoy-client/src/tunnel.rs) handle_request_chunk is driven from envoy_loop's single sequential message loop, shared by every actor hosted under that envoy/runner process. The new send_error_response(...).await call there follows the same pattern already used by handle_request_start's pre-existing "unknown actor" branch, so this isn't a regression, just flagging that there are now two await points in this loop that block on an outbound WS send for error paths instead of one. If that send stalls (e.g. remote flow control), the whole loop pauses for every actor on the connection, same as already happens on the actor-not-found path today.
3. Test coverage is solid for the core primitive but doesn't cover the branch selection in handle_message
The ordered_handoff tests nicely isolate the ordering guarantee itself, and the new envoy-client test confirms a stray chunk gets rejected instead of silently dropped. Nothing currently exercises that only the ToEnvoyTunnelMessage arm gets the deferred ack while ToEnvoyCommands/ToEnvoyConnPing still ack immediately in handle_message. That's understandably harder to set up (needs a real/fake Conn + UPS message), so this is a suggestion rather than a blocker.
Nothing else stood out. The reused HttpStreamAbortReasonKind::HandlerError variant and generalized send_error_response (now taking error_code/message) avoid touching the wire schema, consistent with the "never modify a published *.bare protocol version" rule. I also checked pegboard-gateway2's response-wait handler: it already treats a ToRivetResponseAbort received before any ToRivetResponseStart as a proper request failure, so sending an abort without ever sending a start (the new behavior in the two "not found" branches) is handled correctly on the receiving end.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.