Skip to content

fix: wire client_timeout and keep_alive_timeout through to Actix#1348

Open
sansyrox wants to merge 2 commits intomainfrom
fix/wire-server-timeouts
Open

fix: wire client_timeout and keep_alive_timeout through to Actix#1348
sansyrox wants to merge 2 commits intomainfrom
fix/wire-server-timeouts

Conversation

@sansyrox
Copy link
Copy Markdown
Member

@sansyrox sansyrox commented Mar 27, 2026

Summary

  • The Python API accepts client_timeout and keep_alive_timeout parameters and threads them through run_processesspawn_process, but spawn_process only called server.start(socket, workers) — silently dropping both timeout values.
  • The Rust Server::start hardcoded KeepAlive::Os and client_request_timeout(Duration::from_secs(0)), meaning the documented timeout configuration had zero effect.
  • This PR adds both parameters to the Rust Server::start signature and passes them to Actix's HttpServer builder.

Test plan

  • Existing integration tests pass (no behavior change for default values of 30s/20s)
  • Manual test: start server with client_timeout=2, send a request to a handler that sleeps 10s, verify the server cuts it off
  • Manual test: verify keep_alive_timeout causes idle connections to be closed after the configured duration

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added configurable client and keep-alive timeout settings so server connection timing can be adjusted.
  • Documentation

    • Clarified timeout semantics: client timeout applies to receiving request headers (not handler execution) and keep-alive controls idle connection lifetime; updated examples, guidance, and recommended ranges.

The Python API accepts client_timeout and keep_alive_timeout parameters
and threads them all the way to spawn_process, but they were never
passed to Server.start(). The Rust side hardcoded KeepAlive::Os and
client_request_timeout of 0 seconds, silently ignoring user config.

Pass both values through to Server.start() and use them when building
the Actix HttpServer.

Made-with: Cursor
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 27, 2026

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

Project Deployment Actions Updated (UTC)
robyn Ready Ready Preview, Comment Mar 28, 2026 8:10pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 27, 2026

📝 Walkthrough

Walkthrough

The PR exposes server timeout parameters end-to-end: client_timeout and keep_alive_timeout are threaded from Python process pool into the Rust Server::start and used to configure Actix client_request_timeout and keep_alive instead of hardcoded defaults.

Changes

Cohort / File(s) Summary
Process pool / Python entry
robyn/processpool.py
spawn_process / run_processes docstrings updated; spawn_process now forwards client_timeout and keep_alive_timeout into server.start(...).
Rust server config
src/server.rs
Server::start signature extended to accept client_timeout: u64 and keep_alive_timeout: u64; Actix server builder now uses client_request_timeout(Duration::from_secs(client_timeout)) and keep_alive(KeepAlive::Timeout(Duration::from_secs(keep_alive_timeout))).
Documentation (EN)
docs_src/src/pages/documentation/en/api_reference/timeout_configuration.mdx
Clarified client_timeout is for receiving complete request headers (not handler execution); clarified keep_alive_timeout idle behavior; adjusted examples and recommended ranges (suggest 60–120s for slow clients).
Documentation (ZH)
docs_src/src/pages/documentation/zh/api_reference/timeout_configuration.mdx
Same clarifications and example/range adjustments as English docs; explicit note that handler execution time is not limited by client_timeout.
Public API docs / package
robyn/__init__.py, robyn/robyn.pyi
Robyn.start docstring and Server.start stub docs updated to document client_timeout and keep_alive_timeout, mapping to Actix settings and env var overrides; no signature/runtime changes in Python surface API.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I tunneled through configs, soft and light,
I threaded timeouts from day to night,
Headers wait, then swiftly part,
Keep-alive hums, a steady heart,
Hooray — adjustable seconds take flight!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description provides a clear summary of the problem, solution, and test plan; however, it lacks the descriptive title and summary structure specified in the repository template, and the checklist items are incomplete. Restructure the description to match the template format with distinct 'Description' and 'Summary' sections, and update the checklist to indicate completion status of required tasks like testing and documentation.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: wiring client_timeout and keep_alive_timeout parameters through to Actix, which is the core objective of the PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/wire-server-timeouts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/server.rs`:
- Around line 280-282: The current use of client_request_timeout only affects
request header read time and does not stop long-running handlers; update the
server to enforce handler execution timeouts by adding a middleware or wrapping
handler execution with a timeout (e.g., add a tower::timeout::TimeoutLayer or
apply tokio::time::timeout around request handling) instead of relying on
client_request_timeout; locate where the server is configured (the block using
KeepAlive::Timeout, .workers, .client_request_timeout) and wrap the service or
router with a timeout layer (or modify the request-handling entrypoint to use
tokio::time::timeout) so that handler functions are aborted when they exceed the
desired duration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b8934a6-de98-489b-9fc9-93150212c9df

📥 Commits

Reviewing files that changed from the base of the PR and between a54ff96 and 15ee1d5.

📒 Files selected for processing (2)
  • robyn/processpool.py
  • src/server.rs

Comment thread src/server.rs
Comment on lines +280 to +282
.keep_alive(KeepAlive::Timeout(std::time::Duration::from_secs(keep_alive_timeout)))
.workers(workers)
.client_request_timeout(std::time::Duration::from_secs(0))
.client_request_timeout(std::time::Duration::from_secs(client_timeout))
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Mar 27, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In actix-web HttpServer, what exactly does client_request_timeout(Duration) control? Does it terminate a request when the handler itself runs longer than the timeout (e.g., handler sleeps 10 seconds)? Please cite official actix-web docs.

💡 Result:

In actix-web's HttpServer, client_request_timeout(Duration) controls the timeout for reading the client request head (headers). If the client does not transmit the entire set of headers within this time, the request is terminated with a 408 (Request Timeout) error. The default is 5000 milliseconds (5 seconds). To disable, set to Duration::ZERO. It does NOT terminate a request when the handler itself runs longer than the timeout (e.g., a handler that sleeps 10 seconds). This timeout only applies to initial header reading, not handler execution time.

Citations:


client_request_timeout does not enforce handler execution timeout (Line 282).

The manual test assumes that client_request_timeout will terminate requests when the handler runs longer than the timeout (e.g., handler sleeps 10 seconds). However, client_request_timeout only controls the timeout for reading client request headers, not handler execution time. A handler that sleeps 10 seconds will not be terminated by this setting. To enforce handler execution timeouts, a different mechanism is required (e.g., middleware-based timeout or tokio::time::timeout).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server.rs` around lines 280 - 282, The current use of
client_request_timeout only affects request header read time and does not stop
long-running handlers; update the server to enforce handler execution timeouts
by adding a middleware or wrapping handler execution with a timeout (e.g., add a
tower::timeout::TimeoutLayer or apply tokio::time::timeout around request
handling) instead of relying on client_request_timeout; locate where the server
is configured (the block using KeepAlive::Timeout, .workers,
.client_request_timeout) and wrap the service or router with a timeout layer (or
modify the request-handling entrypoint to use tokio::time::timeout) so that
handler functions are aborted when they exceed the desired duration.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Resolve — informational comment about Actix semantics, no code change needed.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Rate Limit Exceeded

@sansyrox have exceeded the limit for the number of chat messages per hour. Please wait 1 minutes and 49 seconds before sending another message.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Mar 27, 2026

Merging this PR will not alter performance

✅ 189 untouched benchmarks


Comparing fix/wire-server-timeouts (1826471) with main (3e04c65)

Open in CodSpeed

…dler execution

The `client_timeout` parameter maps to actix-web's `client_request_timeout`,
which only controls how long the server waits for the client to transmit the
complete request headers. It does NOT limit handler execution time or overall
request duration. Updated docstrings, type stubs, Rust doc comments, and both
English and Chinese documentation to make this clear and prevent user confusion.

Made-with: Cursor
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
robyn/processpool.py (1)

16-33: Add a fail-fast guard for invalid timeout values.

Since these values now materially affect startup, validate them upfront (>= 0) to avoid opaque failures later in worker startup paths.

Suggested patch
 def run_processes(
@@
 ) -> List[Process]:
+    if client_timeout < 0 or keep_alive_timeout < 0:
+        raise ValueError(
+            "client_timeout and keep_alive_timeout must be non-negative integers"
+        )
+
     """
     Spawn server processes.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@robyn/processpool.py` around lines 16 - 33, Add a fail-fast check at the
start of run_processes to validate the timeout parameters: verify client_timeout
and keep_alive_timeout are integers >= 0 and raise a clear ValueError (or
TypeError for non-int types) that includes the parameter name and the invalid
value; this prevents later opaque failures during worker startup and makes
debugging immediate when run_processes is called with bad timeout values.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@robyn/processpool.py`:
- Around line 16-33: Add a fail-fast check at the start of run_processes to
validate the timeout parameters: verify client_timeout and keep_alive_timeout
are integers >= 0 and raise a clear ValueError (or TypeError for non-int types)
that includes the parameter name and the invalid value; this prevents later
opaque failures during worker startup and makes debugging immediate when
run_processes is called with bad timeout values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cbe8e251-f485-434f-b346-b85f233b005e

📥 Commits

Reviewing files that changed from the base of the PR and between 15ee1d5 and 1826471.

📒 Files selected for processing (6)
  • docs_src/src/pages/documentation/en/api_reference/timeout_configuration.mdx
  • docs_src/src/pages/documentation/zh/api_reference/timeout_configuration.mdx
  • robyn/__init__.py
  • robyn/processpool.py
  • robyn/robyn.pyi
  • src/server.rs
✅ Files skipped from review due to trivial changes (3)
  • robyn/robyn.pyi
  • docs_src/src/pages/documentation/en/api_reference/timeout_configuration.mdx
  • robyn/init.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/server.rs

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