Skip to content

feat(appstore): use bounded stale cache when refresh fails - #63141

Draft
joshtrichards wants to merge 5 commits into
masterfrom
jtr/feat-AppStore-Fetcher-cache-fallback
Draft

feat(appstore): use bounded stale cache when refresh fails#63141
joshtrichards wants to merge 5 commits into
masterfrom
jtr/feat-AppStore-Fetcher-cache-fallback

Conversation

@joshtrichards

@joshtrichards joshtrichards commented Aug 11, 2026

Copy link
Copy Markdown
Member
  • Resolves: #

Summary

This preserves access to (slightly stale) App Store metadata during temporary retrieval failures while preventing indefinitely stale or incompatible data from being used. This might also diminish need to use #55420 in some environments,

Before this change, a failed refresh returned an empty result even when a valid cached response was available. Now, we fall back to valid, same-version App Store cache data when refreshing the App Store fails, provided the cached data is no older than seven days:

Scenario Before After
Fresh, same-version cache Return cached data Return cached data
Stale cache, refresh succeeds Return fresh data Return fresh data
Stale cache, temporary refresh failure Return [] Return same-version cached data, up to seven days old
Recent failure cooldown Return [] Return same-version cached data, up to seven days old
Valid refresh with data: [] Return [] and do not refresh the cache Store and return the valid empty result
Cache older than seven days and refresh fails Return [] Return []
Cache from another Nextcloud version and refresh fails Return [] Return []
Missing or unreadable cache and refresh fails Return [] Return []

This improves resilience during temporary App Store or network failures without allowing indefinitely stale or incompatible metadata to be used.

Changes:

  • Retain valid cached data for the current Nextcloud version while refreshing.
  • Return stale cached data when refreshes fail or are suppressed by the recent-failure cooldown.
  • Limit stale fallback data to seven days.
  • Continue accepting valid empty responses as fresh data (to not overlook legitimate filtering changes).
  • Reject missing, malformed, incompatible-version, and overly stale cache data.
  • Add shared fetcher tests covering:
    • refresh failures with usable stale data;
    • the seven-day stale-data boundary;
    • the recent-failure cooldown;
    • valid empty refresh responses.
  • Add child-fetcher regression coverage confirming that stale data still passes through:
    • AppFetcher allowlist filtering;
    • AppDiscoverFetcher expiry filtering.

User impact

Temporary App Store or network failures no longer cause App Store browsing and metadata consumers to immediately receive an empty result when usable cached metadata is available.

For example, if the App Store endpoint is temporarily unavailable while an instance has a six-day-old cache for its current Nextcloud version, users can continue browsing the cached App Store metadata. If the cache is more than seven days old, or belongs to another Nextcloud version, the fetcher still returns an empty result rather than presenting potentially misleading data.

Testing

  • PHPUnit coverage added for the base fetcher fallback behavior.
  • Regression coverage added for AppFetcher and AppDiscoverFetcher.

TODO

  • Backport? (Kinda a bug fix / kinda an enhancement... so...)

Checklist

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

Fall back to stale but otherwise valid, same-version App Store cache data when a refresh fails, provided it is no older than seven days. Continue accepting valid empty responses as fresh data while rejecting missing, incompatible, or overly stale cache entries.

Improves the user experience by preserving access to App Store metadata during temporary retrieval failures, allowing users to continue browsing the App Store.

Signed-off-by: Josh <josh.t.richards@gmail.com>
Signed-off-by: Josh <josh.t.richards@gmail.com>
Verify that same-version cached data is used after refresh failures while within the seven-day stale limit, rejected after the limit, and returned during the recent-failure cooldown. Also verify that valid empty refresh responses replace stale data.

Signed-off-by: Josh <josh.t.richards@gmail.com>
Verify that stale app data still respects the App Store allowlist.

Signed-off-by: Josh <josh.t.richards@gmail.com>
Verify that  stale discover data still removes expired entries after the base fetcher falls back from a failed refresh.

Assisted-by: Copilot:gpt-5.6-luna

Signed-off-by: Josh <josh.t.richards@gmail.com>
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