Skip to content

refactor(remote-config): add API sources failover with health check endpoint support#3812

Open
tonidero wants to merge 2 commits into
mainfrom
api-source-health-checker
Open

refactor(remote-config): add API sources failover with health check endpoint support#3812
tonidero wants to merge 2 commits into
mainfrom
api-source-health-checker

Conversation

@tonidero

@tonidero tonidero commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Description

Completes the health-check-gated API source failover feature. Everything remains behind the usesRemoteConfigAPISources dangerous setting, so released behavior is unchanged.

Failure classification per request attempt on the current source:

Outcome Action
2xx/3xx Success.
4xx Return result; no failover, no health check (request error, not a source problem).
5xx or connection failure GET <source>/v1/health/connectivity (lazy, never proactive). Health 2xx → source healthy, no failover, surface the original error/result. Health non-2xx or unreachable → mark source unhealthy, transparently retry the in-flight request on the next source.

Note

Medium Risk
Changes core HTTP request routing and retry logic for API traffic behind a dangerous setting; incorrect health-check or failover decisions could misroute requests or mask errors, though default production behavior is unchanged when the flag is off.

Overview
Adds health-check-gated failover across remote-config API hosts when usesRemoteConfigAPISources is on. HTTPClient no longer only picks a source URL up front; it loops through sources (capped at 5 attempts), and on 5xx or connection failure asks APISourceFailover whether to retry on the next host.

APISourceFailover picks the current source (same eligibility as before: default base URL, endpoint opts in, not a fallback-host attempt) and on failure probes GET <source>/v1/health/connectivity via SourceHealthChecker (cached ~10s, deduped concurrent probes). Health 2xx → treat the source as up and surface the original error; unhealthy → reportUnhealthy and transparently retry the same in-flight request on the next source. 4xx never triggers failover or health checks.

DefaultRemoteConfigSourceProvider now re-arms the API list every 10 minutes after the first failover advance so the SDK periodically retries the primary; blob failover is unchanged. SourceFailover.reportUnhealthy returns whether it actually advanced.

PurchasesFactory wires APISourceFailover + SourceHealthChecker into HTTPClient instead of passing the raw source provider. Broad unit and backend integration tests cover the new behavior.

Reviewed by Cursor Bugbot for commit 64e7f06. Bugbot is set up for automated code reviews on this repo. Configure here.

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@tonidero tonidero changed the title feat(remote-config): health-check-gated API source failover components refactor(remote-config): health-check-gated API source failover components Jul 21, 2026
@tonidero
tonidero force-pushed the api-source-health-checker branch from 442910a to 630c17f Compare July 21, 2026 14:42
@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.19497% with 14 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@225ea79). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...tlin/com/revenuecat/purchases/common/HTTPClient.kt 86.88% 2 Missing and 6 partials ⚠️
...purchases/common/networking/SourceHealthChecker.kt 89.36% 2 Missing and 3 partials ⚠️
...t/purchases/common/networking/APISourceFailover.kt 96.29% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3812   +/-   ##
=======================================
  Coverage        ?   80.59%           
=======================================
  Files           ?      410           
  Lines           ?    17014           
  Branches        ?     2493           
=======================================
  Hits            ?    13712           
  Misses          ?     2337           
  Partials        ?      965           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tonidero
tonidero force-pushed the api-source-health-checker branch 2 times, most recently from d18c71c to 0f59e70 Compare July 21, 2026 16:01
@RevenueCat-Danger-Bot

RevenueCat-Danger-Bot commented Jul 21, 2026

Copy link
Copy Markdown
1 Message
📖 This PR changes 427 lines of production Kotlin/Java (limit 300); skipped via skip-pr-lines-changed-check label.

Generated by 🚫 Danger

@tonidero tonidero changed the title refactor(remote-config): health-check-gated API source failover components refactor(remote-config): add API sources failover with health check endpoint support Jul 21, 2026
@tonidero
tonidero force-pushed the api-source-health-checker branch from 0f59e70 to d35d1c3 Compare July 21, 2026 16:43
Completes the API source failover feature behind the
usesRemoteConfigAPISources dangerous setting (still internal and
defaulting to false, so released behavior is unchanged):

- SourceHealthChecker: probes <source>/v1/health/connectivity; only a
  2xx is healthy. Blocking, so it must be called from a background
  thread. Concurrent checks per source share one request and results
  are cached for 10s.
- DefaultRemoteConfigSourceProvider: the API failover list restarts
  from the top 10 minutes after it first advances, so the SDK
  periodically retries the primary source (and re-arms an exhausted
  list) instead of sticking on a backup forever.
- APISourceFailover: the decision layer. Connection-level failures and
  5xx responses can fail over, but only after the current source's
  health check fails; a 2xx health response means the source is healthy
  and the original error surfaces instead. 4xx responses never fail
  over. Malformed source URLs are reported unhealthy and skipped.
- HTTPClient: performRequest resolves a source per attempt and walks
  the source list on failed attempts, transparently retrying the
  in-flight request on the next source. ETag refresh retries and the
  static per-endpoint fallback URLs keep their existing behavior, with
  static fallback acting as the last resort once sources are exhausted
  or decline to fail over.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tonidero
tonidero force-pushed the api-source-health-checker branch from d35d1c3 to 51c160a Compare July 21, 2026 17:50
@tonidero
tonidero marked this pull request as ready for review July 23, 2026 07:26
@tonidero
tonidero requested a review from a team as a code owner July 23, 2026 07:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants