Class GrpcRetry

java.lang.Object
ai.pipestream.module.pipelineprobe.pipelinecrawl.GrpcRetry

public final class GrpcRetry extends Object
Bounded retry wrapper around a blocking gRPC stub call. Used by every control-plane call out of the pipeline-crawl orchestrator so that a stale Stork sub-channel, a momentarily-unavailable target, or a transient RESOURCE_EXHAUSTED doesn't wedge the entire orchestration.

Per-attempt deadline must live inside the supplier. The caller is expected to call stub.withDeadlineAfter(...) inside the supplier so that each retry gets a fresh deadline budget. If the deadline were applied outside, every retry would inherit the same already-spent deadline and fail immediately.

Retryable status codes (per docs/architecture/14-backpressure-and-admission.md):

  • UNAVAILABLE — Stork couldn't find a healthy instance, or the channel is in TRANSIENT_FAILURE and hasn't re-resolved yet.
  • DEADLINE_EXCEEDED — previous attempt timed out; the next call forces channel re-resolution.
  • RESOURCE_EXHAUSTED — the gap-window backstop: target just-flipped-yellow but Consul/Stork doesn't know yet.

All other status codes (INVALID_ARGUMENT, ALREADY_EXISTS, NOT_FOUND, INTERNAL, etc.) are re-thrown immediately — they're not transport failures and retrying just wastes time.

Caller must run on a virtual thread; this class uses Thread.sleep(long) between retries, which on a VT is a cheap park but on a platform thread is a wasted thread.

  • Method Details

    • call

      public static <T> T call(String opName, Supplier<T> stubCall, GrpcRetry.RetryPolicy policy)
      Invoke stubCall with bounded retry per policy. The supplier MUST apply its own per-attempt deadline via stub.withDeadlineAfter(...).
      Type Parameters:
      T - the response type returned by the stub call
      Parameters:
      opName - short human-readable name of the operation, used in retry log messages so operators can see what's flapping
      stubCall - the blocking-stub call, applied fresh on each attempt
      policy - retry budget and backoff schedule
      Returns:
      the successful response
      Throws:
      io.grpc.StatusRuntimeException - the last failure if all attempts were exhausted, or the first non-retryable failure if one occurred