Skip to content

Add a client-side rate limit for remote feature-flag / remote-config fetches #25665

Description

@jkmassel

Follow-up to #25643. Non-blocking — capturing the right-altitude version here rather than a one-off patch.

Background

#25643 (UIScene adoption) made WordPressAppDelegate refresh the remote stores in both willFinishLaunching and the foreground transition that now fires right after the first scene connect, so updateFeatureFlags() / updateRemoteConfig() run twice on every cold launch. (Pre-scene, the legacy applicationWillEnterForeground did not fire on a cold launch, so they ran exactly once.)

A per-call-site debounce in handleWillEnterForeground would fix that one instance. But the deeper gap is that the stores themselves have no client-side fetch throttle, so any caller — or any future caller — that asks twice in quick succession hits the network twice.

Current behavior

  • RemoteFeatureFlagStore.update(using:then:) enqueues a fetch and calls operationQueue.cancelAllOperations() first — so a second call cancels the first in-flight request and refetches. No "we just fetched, skip" guard.
  • RemoteConfigStore.update(then:) calls remote.getRemoteConfig directly on every call — no cancellation, no throttle.

Callers are uncoordinated: WordPressAppDelegate (launch + foreground), AccountHelper.updateFeatureFlags() (on account change), and AppUpdateCoordinator (its own RemoteConfigStore). The cold-launch double from #25643 is just the most visible instance.

Proposed

Add a persisted "last fetched" timestamp + a minimum refresh interval to each store, so update() is a no-op (returns the cache) within the interval. Prior art already lives in the codebase: AppUpdateCoordinator.shouldFetchAppStoreInfo gates the App Store lookup with a last-fetched-date + day threshold — apply the same shape to the feature-flag / remote-config stores with a short interval (minutes).

This subsumes the #25643 cold-launch double — no one-off debounce needed in the AppDelegate — and naturally dedupes any future caller.

Caveat: allow an explicit bypass

Feature flags are fetched per-user (the endpoint authenticates to customize flags server-side; see the doc comment on RemoteFeatureFlagStore.update), which is why AccountHelper refetches on account change. A blunt time-only limit would suppress that needed refresh, so the rate limit must support a forced refresh (bypass on auth/account change), or be invalidated when the authenticated user changes.

Files

  • WordPress/Classes/Stores/RemoteFeatureFlagStore.swiftupdate(using:then:)
  • WordPress/Classes/Stores/RemoteConfigStore.swiftupdate(then:)
  • Callers: WordPress/Classes/System/WordPressAppDelegate.swift (updateFeatureFlags / updateRemoteConfig), WordPress/Classes/Utility/AccountHelper.swift

Surfaced while reviewing #25643; sibling cleanup tracked in #25664.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions