gRPC Client Deadline and Timeout Control

Propagate per-call deadlines through gRPC clients with timeout headers, cancellation signals, and DEADLINE_EXCEEDED error classification.

TypescriptNodeData Fetching

Code

snippet
import * as grpc from '@grpc/grpc-js';
import { echo } from './generated/echo_grpc_pb';

const client = new echo(
  'api.example.com:443',
  grpc.credentials.createSsl(),
);

function callWithDeadline(payload: string, timeoutMs: number) {
  return new Promise<string>((resolve, reject) => {
    // 每次调用独立截止时间,随调用元数据传播到下游
    const callOptions = { deadline: Date.now() + timeoutMs };

    client.echo(
      { payload } as never,
      new grpc.Metadata(),
      callOptions,
      (err: grpc.ServiceError | null, response?: { payload: string }) => {
        if (err) {
          if (err.code === grpc.status.DEADLINE_EXCEEDED) {
            reject(Object.assign(new Error('deadline exceeded'), { retryable: false }));
            return;
          }
          if (err.code === grpc.status.UNAVAILABLE) {
            reject(Object.assign(new Error('unavailable'), { retryable: true }));
            return;
          }
          reject(new Error('rpc failed: ' + err.details));
          return;
        }
        resolve(response?.payload ?? '');
      },
    );
  });
}

try {
  const echoed = await callWithDeadline('ping', 2_000);
  console.log('echo ok:', echoed.length);
} catch (err) {
  const { message, retryable } = err as Error & { retryable?: boolean };
  console.log('failed:', message, 'retryable:', retryable ?? false);
}