Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support timeouts in handlers #591

Merged
merged 2 commits into from
Apr 22, 2023
Merged

Support timeouts in handlers #591

merged 2 commits into from
Apr 22, 2023

Conversation

timostamm
Copy link
Member

@timostamm timostamm commented Apr 21, 2023

This PR adds support for timeouts on the server side for all three protocols. This feature from gRPC is also known as deadlines, and it can be used to limit the time a server may take to process a response.

For example, when a client provides the timeoutMs call option, a header Connect-Timeout-Ms is added to the request. The server parses this timeout, and if it takes longer than the given timeout to process the request, it should give up, and respond with the error code deadline_exceeded.

On a connect-es server, the parsed timeout is available as an AbortSignal on the context:

import type { HandlerContext } from "@bufbuild/connect";

const say = async (req: SayRequest, ctx: HandlerContext) => {

  ctx.signal.aborted; // true if timed out
  ctx.signal.reason; // an error with code deadline_exceed if timed out

  // raises an error with code deadline_exceed if timed out
  ctx.signal.throwIfAborted();

  // the AbortSignal can be passed to other functions
  await longRunning(ctx.signal);

  return new SayResponse({sentence: `You said: ${req.sentence}`});
};

It is up to the implementation to honor the AbortSignal.

This also adds two related options to ConnectRouter:

  /**
   * The maximum value for timeouts that clients may specify.
   * If a clients requests a timeout that is greater than maxTimeoutMs,
   * the server responds with the error code InvalidArgument.
   */
  maxTimeoutMs: number;

  /**
   * To shut down servers gracefully, this option takes an AbortSignal.
   * If this signal is aborted, all `deadline` AbortSignals in handler contexts
   * will be aborted as well. This gives implementations a chance to wrap up
   * work before the server process is killed.
   */
  shutdownSignal?: AbortSignal;

Edit: The HandlerContext property was originally added as deadline?: AbortSignal in this PR, but #531 updated it to be signal: AbortSignal. The example above was updated.

Edit: #632 added a timeoutMs(): number | undefined method to the HandlerContext. It can be used to propagate the timeout to upstream RPCs.

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.

2 participants