Skip to content

[feature] Opt-in retries for remote cache HTTP requests #2680

Description

@maastrich

Is your feature request related to a problem? Please describe.

We run a self-hosted HTTP remote cache (Bazel cache protocol, behind CloudFront) for a fairly large monorepo. Under CI load a small fraction of blob requests fail with transient 503s (CDN capacity ramp-up, S3 SlowDown, that kind of thing). We measured around 0.1-0.2% of requests during bursts.

moon currently gives up on the first error. For uploads that's mostly fine (the manifest is skipped and the next run rebuilds), but for downloads a single failed blob out of hundreds means the task ends up with a partial output set and fails hard with task_runner::missing_outputs. So a 0.1% transient error rate on the cache turns into red CI several times a day, even though a single retry would almost certainly have succeeded.

Example from our logs:

[WARN] moon_cache_storage::storage_backend  Failed to retrieve blobs, will attempt to retrieve remaining from other storage backends  storage="http-remote-cache" hash="43d4d1..." expected_count=265 actual_count=176 errors=["Failed to make HTTP request (503 Service Unavailable)."]
Error: task_runner::missing_outputs

Describe the solution you'd like

An opt-in retry setting on the remote cache client, off by default so current behavior doesn't change:

remote:
  api: http
  cache:
    retries: 2

A short exponential backoff (honoring Retry-After when present) on 429/5xx responses would cover the common transient cases. I'd be happy if it only applied to the HTTP client at first.

Describe alternatives you've considered

  • Retrying at the infrastructure level: CloudFront origin-group failover can't be used here because behaviors with PUT in AllowedMethods can't target origin groups, and reads/writes share paths.
  • Making the failure softer instead of retrying: when a blob can't be fetched after retries, falling back to actually running the task instead of failing with missing_outputs would also solve it. That might be worth doing regardless of retries, but it felt like a separate discussion.
  • Wrapping moon with CI-level job retries, which works but re-runs entire jobs for a single lost 28-byte blob.

Additional context

Tested with moon 2.3.2. verifyIntegrity is enabled on our side; the failures above are plain HTTP errors, not integrity mismatches. If a PR is welcome for this I can give it a try.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions