private static long exponentialBackOff(long effectiveDelayMs, long backoffLimitMs) {
    try {
      Thread.sleep(effectiveDelayMs);
    }
    catch (InterruptedException ex) {
      Thread.currentThread().interrupt();
      throw new RuntimeException("Unexpected thread interrupt", ex);
    }

    long nextRawDelay = (long)Math.min(effectiveDelayMs * EXP_BACKOFF_FACTOR, backoffLimitMs);
    long jitter = (long)(RANDOM.nextDouble() * nextRawDelay * EXP_BACKOFF_JITTER);
    long jitterSign = RANDOM.nextBoolean() ? 1 : -1;
    return nextRawDelay + jitter * jitterSign;
  }
private static long exponentialBackOff(long effectiveDelayMs, long backoffLimitMs)