Class ApiRetryHelper

java.lang.Object
edu.ucsb.cs.scaffold.services.ApiRetryHelper

public class ApiRetryHelper extends Object
Wraps calls to an external REST API (GitHub, PrairieLearn) with three defenses:
  • Pacing: consecutive calls are kept at least paceMs apart, to stay under rate limits in the first place. The pacer only sleeps the remaining gap since the previous call, so an occasional interactive call is not delayed at all — only tight loops (like a repo sync) are slowed.
  • Backoff-retries on 5xx: transient server errors (e.g. GitHub's 502 "Unicorn" page) are retried up to retryMax times, sleeping retryInitialSleepSeconds and doubling each time (8, 16, 32...). Only then does the call fail — with a one-line ApiRetryHelper.ApiUnavailableException instead of the provider's HTML error page.
  • Rate-limit reaction: a 429, or a 403 whose body mentions "rate limit", counts as a retryable event and additionally doubles the pace permanently (for the life of the service instance), with a log suggestion to raise the pace's configuration variable.

All other client errors (404 for a missing path, 401/403 for a bad token) are rethrown untouched — callers depend on their semantics.

  • Constructor Details

    • ApiRetryHelper

      public ApiRetryHelper(String apiName, String paceVariableName, long retryInitialSleepSeconds, int retryMax, long paceInitialMs)
  • Method Details

    • execute

      public <T> T execute(String description, Supplier<T> call)
      Runs call, pacing it relative to the previous call and retrying per the class contract. description identifies the request in log messages, e.g. "GET .../contents/questions".