timeoutInterceptor function

Interceptor timeoutInterceptor(
  1. Duration timeout
)

Builds an Interceptor that applies timeout to every call.

The interceptor composes with any deadline already carried by the parent AbortSignal: if the parent's deadline is tighter than now + timeout, the parent wins and no wrapping happens. Otherwise a TimeoutSignal is installed on a copy of the request.

Composition order per RFC 0002: timeout sits outside retry, so the deadline covers all retry attempts, not each individual attempt.

Implementation

Interceptor timeoutInterceptor(Duration timeout) {
  if (timeout <= Duration.zero) {
    throw ArgumentError.value(
      timeout,
      'timeout',
      'must be a positive duration',
    );
  }

  return <I extends Object, O extends Object>(AnyFn<I, O> next) {
    return (Request<I, O> req) {
      final parentDeadline = req.signal.deadline;
      final candidate = DateTime.now().add(timeout);
      if (parentDeadline != null && !candidate.isBefore(parentDeadline)) {
        return next(req);
      }
      final signal = TimeoutSignal(timeout, parent: req.signal);
      return next(_withSignal(req, signal));
    };
  };
}