Skip to content

feat(server): add timeout handler plugin - #1858

Merged
dinwwwh merged 3 commits into
middleapi:mainfrom
dinwwwh:claude/timeout-handler-plugin-6a89b4
Aug 14, 2026
Merged

feat(server): add timeout handler plugin#1858
dinwwwh merged 3 commits into
middleapi:mainfrom
dinwwwh:claude/timeout-handler-plugin-6a89b4

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Aug 14, 2026

Copy link
Copy Markdown
Member

Adds TimeoutHandlerPlugin to @orpc/server/plugins, the server-side counterpart of TimeoutLinkPlugin. When handling exceeds the configured timeout, the plugin aborts the request signal with an AbortError. It never preempts the procedure: abort-aware procedures stop early and logging records the timeout as a cancellation, while a procedure that ignores the signal still delivers its real result or error, so nothing is masked.

Features

  • timeout limits producing the response; the separate streamingTimeout (usually higher) limits the full duration of streaming bodies, both async iterator objects and readable streams.
  • Both options accept a static number or a per-request function of the interceptor options; returning null/undefined disables the timeout for that request.
  • No timer leaks: timers are cleared when the response is produced and when a streaming body finishes or is cancelled; requests with both timeouts disabled bypass the plugin entirely.

Testing

  • 15 handler tests under fake timers, each asserting zero leftover timers: abort + response via signal-honoring procedures, no preemption, unmasked late errors, dynamic values, per-request disabling, and streaming termination and cleanup for both body kinds.
  • Registered in the all-plugins compatibility suite; pnpm type:check, eslint, and pnpm docs:validate pass.

Docs

  • /docs/plugins/timeout now covers both the link and handler plugins, streaming timeouts, and dynamic per-request values.

@vercel

vercel Bot commented Aug 14, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
orpc Ready Ready Preview Aug 14, 2026 9:39am

@pkg-pr-new

pkg-pr-new Bot commented Aug 14, 2026

Copy link
Copy Markdown
More templates

@orpc/ai-sdk

npm i https://pkg.pr.new/@orpc/ai-sdk@1858

@orpc/arktype

npm i https://pkg.pr.new/@orpc/arktype@1858

@orpc/bun

npm i https://pkg.pr.new/@orpc/bun@1858

@orpc/client

npm i https://pkg.pr.new/@orpc/client@1858

@orpc/cloudflare

npm i https://pkg.pr.new/@orpc/cloudflare@1858

@orpc/contract

npm i https://pkg.pr.new/@orpc/contract@1858

@orpc/experimental-effect

npm i https://pkg.pr.new/@orpc/experimental-effect@1858

@orpc/evlog

npm i https://pkg.pr.new/@orpc/evlog@1858

@orpc/hibernation

npm i https://pkg.pr.new/@orpc/hibernation@1858

@orpc/json-schema

npm i https://pkg.pr.new/@orpc/json-schema@1858

@orpc/nest

npm i https://pkg.pr.new/@orpc/nest@1858

@orpc/next

npm i https://pkg.pr.new/@orpc/next@1858

@orpc/node

npm i https://pkg.pr.new/@orpc/node@1858

@orpc/openapi

npm i https://pkg.pr.new/@orpc/openapi@1858

@orpc/opentelemetry

npm i https://pkg.pr.new/@orpc/opentelemetry@1858

@orpc/pinia-colada

npm i https://pkg.pr.new/@orpc/pinia-colada@1858

@orpc/pino

npm i https://pkg.pr.new/@orpc/pino@1858

@orpc/publisher

npm i https://pkg.pr.new/@orpc/publisher@1858

@orpc/ratelimit

npm i https://pkg.pr.new/@orpc/ratelimit@1858

@orpc/server

npm i https://pkg.pr.new/@orpc/server@1858

@orpc/shared

npm i https://pkg.pr.new/@orpc/shared@1858

@orpc/swr

npm i https://pkg.pr.new/@orpc/swr@1858

@orpc/tanstack-query

npm i https://pkg.pr.new/@orpc/tanstack-query@1858

@orpc/trpc

npm i https://pkg.pr.new/@orpc/trpc@1858

@orpc/valibot

npm i https://pkg.pr.new/@orpc/valibot@1858

@orpc/zod

npm i https://pkg.pr.new/@orpc/zod@1858

commit: 0af2efd

@codecov

codecov Bot commented Aug 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 30 untouched benchmarks


Comparing dinwwwh:claude/timeout-handler-plugin-6a89b4 (0af2efd) with main (4403853)

Open in CodSpeed

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ Minor suggestions only — the plugin is solid and well-tested; one ergonomic nit inline.

Reviewed changes

  • TimeoutHandlerPlugin implementation — new packages/server/src/plugins/timeout.ts that aborts the merged request signal with an AbortError after timeout (response production) or streamingTimeout (full streaming body), never preempting the procedure. Exported from @orpc/server/plugins.
  • Handler tests — 15 fake-timer tests with an afterEach asserting zero leftover timers, covering abort propagation, no-preemption, unmasked errors, dynamic per-request values, streaming cleanup for both async-iterator and ReadableStream bodies.
  • Registration — added to the tests/plugins/all-plugins.test.ts compatibility suite.
  • Docsapps/content/docs/plugins/timeout.mdx split into Client/Server sections with streaming and dynamic-timeout coverage.

I traced the abort path end to end: the interceptor forwards request.signal = anyAbortSignal([request.signal, controller.signal]), and the standard handler relays request.signal into the procedure signal, so aborting the plugin's controller does reach signal-honoring procedures. The timeout timer is cleared in finally once next() resolves, and streamingTimeout is cleared via the wrapped body's onFinish (both on completion and cancellation). The tests are meaningful — each assertion would fail if the corresponding behavior regressed (e.g. a buggy timer that fires would trip the getTimerCount() === 0 guard).

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Comment thread packages/server/src/plugins/timeout.ts

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ The new 14339e0e "fix" commit is clean (generated-file version bump only); not approving because the prior review's timeout-required nit thread is still open on timeout.ts.

Reviewed changes (delta since previous review, commit 14339e0e "fix")

  • Wrangler types regenerationpackages/cloudflare/worker-configuration.d.ts and playgrounds/cloudflare/worker-configuration.d.ts only change the generated workerd@1.20260730.1 → workerd@1.20260804.1 header line; the hash line and all actual content are byte-identical, so this is pure generated-file cosmetics with no behavioral surface.
  • The TimeoutHandlerPlugin source (packages/server/src/plugins/timeout.ts), its tests, and the docs are unchanged from the previously reviewed version.

One non-blocking observation: this commit bundles an unrelated wrangler types regeneration (generated files) into a feature PR. It's harmless, but dropping it would keep the PR focused on the timeout plugin.

Pullfrog  | Fix it ➔View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@dinwwwh
dinwwwh merged commit 38df61f into middleapi:main Aug 14, 2026
12 checks passed
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