Skip to content

feat: configurable Envoy route timeout for long-running actor requests - #714

Open
Maya Wang (mayawang) wants to merge 1 commit into
mainfrom
feat/configurable-route-timeout
Open

feat: configurable Envoy route timeout for long-running actor requests#714
Maya Wang (mayawang) wants to merge 1 commit into
mainfrom
feat/configurable-route-timeout

Conversation

@mayawang

@mayawang Maya Wang (mayawang) commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Split out of #487, which bundled three unrelated changes.

Summary

Envoy's end-to-end timeout on the workload route is hardcoded at 10s in
buildRoutes. An actor that legitimately holds a request open longer gets cut
off: a harness relaying an LLM completion keeps the request open for the whole
generation, and the client sees a 504 mid-turn.

Adds --route-timeout on atenet-router. The default is 10s, so behavior is
unchanged
unless an operator passes the flag.

Changes

cmd/atenet/internal/router/ — adds XdsServer.routeTimeout with a
SetRouteTimeout setter and a defaultRouteTimeout const, wired from
routerConfig.RouteTimeout / --route-timeout. Same shape as the adjacent
SetExtProcMessageTimeout and SetExtProcMaxRequests, and a flag on the
existing config struct rather than an env read, matching the convention the
parked-request work established.

A non-positive value leaves the default in place, since Envoy reads a zero route
timeout as no timeout at all.

The knob bounds the actor's own handling time only. The resume that may precede
a request is covered by request parking and the ext_proc message timeout, both
of which already derive from --parked-request-budget.

manifests/ate-install/atenet-router.yaml documents it as a commented-out entry.

Verification

  • go build ./..., go vet ./..., go test ./... — all pass.

  • xds_test.go reads the timeout back out of buildRoutes, where Envoy
    actually picks it up: default, setter override, and
    non-positive-keeps-default. The helper pins that route to
    OriginalDstClusterName — a change that moved actor traffic onto some other
    route would otherwise leave the test passing while the timeout governed a
    route nothing uses.

  • On a live GKE cluster, read back out of Envoy's own /config_dump. With
    the new image and no flag, the workload route reports timeout: 10s, so the
    default is genuinely unchanged. With --route-timeout=5m it reports
    timeout: 300s. Same binary, same manifest, only the flag differs.

    Caveat on that measurement: it was taken before ingress: route actor ingress through the atunnel mTLS server landed, so the route it read was the old
    dynamic_forward_proxy path to pod-IP:80. After rebasing, the timeout
    attaches to the actor_original_dst route that replaced it — which is now
    pinned by the test above rather than left to inspection.

  • Regression, resume with parking on the path: a conversation actor that had
    been suspended for 4 days was resumed by an ordinary request through the
    router — HTTP 200 in 3.74s, exactly one parked request,
    parking_wait_duration_seconds{outcome="served"} = 3.459s, no shed and no
    budget_exhausted.

Relationship to #465

This is a stopgap for the connected-socket suspend/restore problem tracked in
#465 (suspend-safe actor networking). Once actor network traffic survives
checkpoint/restore natively, much of the need to raise this ceiling should go
away; this just makes the current behavior tunable in the meantime.

Fixes #<issue_number_goes_here>

It's a good idea to open an issue first for discussion.

  • Tests pass
  • Appropriate changes to documentation are included in the PR

Envoy's end-to-end timeout on the workload route is hardcoded at 10s. An actor
that legitimately holds a request open longer than that gets cut off: a harness
relaying an LLM completion keeps the request open for the whole generation, and
the client sees a 504 mid-turn.

Add --route-timeout on atenet-router. The default is 10s, so behavior is
unchanged, and a non-positive value leaves the default in place.

The knob bounds the actor's own handling time only. The resume that may precede
a request is covered by request parking and the ext_proc message timeout, both
of which already derive from --parked-request-budget.

Wired as a flag on the existing router config struct rather than an env read,
matching how the parked-request and ext_proc knobs are done, and documented as
a commented-out entry in the atenet-router manifest.

The test reads the timeout back out of buildRoutes, where Envoy actually picks
it up, and pins that route to OriginalDstClusterName: a change that moved actor
traffic onto some other route would otherwise leave the test passing while the
timeout governed a route nothing uses.

@ronlv10 Ron Lev (ronlv10) left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for creating this PR! We encountered the same issue when trying to use substrate.

cmd.Flags().StringVar(&cfg.Auth.AteapiServerName, "ateapi-server-name", "", "SNI / hostname expected on the ateapi server cert. Optional.")
cmd.Flags().BoolVar(&cfg.Auth.AteapiUseTokenAuth, "ateapi-use-token-auth", false, "Authenticate to ateapi with the Bearer token from --ateapi-token-file instead of the client certificate from --ateapi-client-cert.")
cmd.Flags().StringVar(&cfg.Auth.AteapiTokenFile, "ateapi-token-file", "", "Projected SA token file used as Bearer credential. Required with --ateapi-use-token-auth, ignored otherwise.")
cmd.Flags().DurationVar(&cfg.RouteTimeout, "route-timeout", defaultRouteTimeout, "Envoy's end-to-end timeout on the workload route, bounding one request from the ingress listener to the actor's response. Raise it for actors whose turns legitimately run long — a harness relaying an LLM completion holds the request open for the whole generation. This does not cover the resume that may precede the request; see --parked-request-budget")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you considered making it configurable per actor-template (or per request)? I think that making it global for the whole router might be too broad, as this timeout could vary between actor types.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for this we would need an api, right? this can follow as a follow up issue. Any objection Ron Lev (@ronlv10) ?

}
})

// A zero value is what an operator who never passes --route-timeout would

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this true ?
the config is cmd.Flags().DurationVar(&cfg.RouteTimeout, "route-timeout", defaultRouteTimeout, no ?

@LiorLieberman

Copy link
Copy Markdown
Collaborator

a harness relaying an LLM completion keeps the request open for the whole
generation, and the client sees a 504 mid-turn.

Maya Wang (@mayawang) can you clarify what do you mean here?>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we considered using idle_timeout vs timeout here?

idle_timeout sets the maximum time that a stream can exist without any network activity (which feels more relevant for our usecase?). The timer resets every time a byte is sent or received.

@yanavlasov

Copy link
Copy Markdown

Have we considered using idle_timeout vs timeout here?

idle_timeout sets the maximum time that a stream can exist without any network activity (which feels more relevant for our usecase?). The timer resets every time a byte is sent or received.

You need both. idle_timeout is how long ateom can remain suspended without breaking network connections. request_timeout is how long request can be in-flight, potentially across multiple suspend/resume cycles.

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.

4 participants