Prewarm workflow assets after offerings refresh#6732
Conversation
After offerings are fetched, fetch the workflow for the current offering and pre-download images, videos, and fonts across all workflow screens, so paywall presentation doesn't block on cold network requests. Gated behind -EnableWorkflowsEndpoint and respects isAppBackgrounded for appropriate network priority. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Warm workflow assets as a side-effect of fetching the workflow rather than issuing a redundant second getWorkflow call from warmUpCaches. This removes the extra background network request after every offerings refresh and keeps the caching co-located with the only fetch site. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| ) | ||
| } | ||
| if #available(iOS 15.0, macOS 12.0, watchOS 8.0, tvOS 15.0, *), | ||
| let cache = self.paywallCache { |
There was a problem hiding this comment.
I was wondering about renaming paywallCache to something more meaningful
There was a problem hiding this comment.
yeah at this point it's not paywallCache anymore, for the future!
Images, videos, and fonts are independent — no need to wait for each group to finish before starting the next. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Follows the same pattern as warmUpPaywallImagesCache, warmUpPaywallVideosCache, and warmUpPaywallFontsCache. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit fdd0930. Configure here.
…ove PaywallComponentsData allocation - Replace hasLoadedWorkflow bool with warmedWorkflowIDs: Set<String> keyed on workflow.id so each distinct workflow is warmed exactly once - Add guard let self in all task group closures to match existing patterns - Extract imageURLs(from:localizations:) as a shared free function and add allImageURLs/allLowResVideoUrls directly on WorkflowScreen, removing the intermediate PaywallComponentsData allocation in warmUpWorkflowCaches Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
📸 Snapshot TestBase build not foundNo build was found for the base commit 79d837d. This is required to generate a snapshot diff for your pull request. It's possible that you created a branch off the base commit before all of the CI steps have finished processing, e.g. the one that uploads a build to our system. If that's the case, no problem! Just wait and this will eventually resolve. 🛸 Powered by Emerge Tools |
|
|
||
| } | ||
|
|
||
| private func imageURLs( |
| ) | ||
| } | ||
| if #available(iOS 15.0, macOS 12.0, watchOS 8.0, tvOS 15.0, *), | ||
| let cache = self.paywallCache { |
There was a problem hiding this comment.
yeah at this point it's not paywallCache anymore, for the future!
### Motivation When the two-surface workflow slide animation (RevenueCat#3418) starts a transition, the incoming step's images may not yet be in Coil's cache, causing a visible pop-in mid-slide. Pre-warming images for every workflow step before the paywall is shown lets transitions start with warm caches. We already prewarm offerings, so we should do the same for workflows. ### Description Mirrors the iOS approach in [purchases-ios#6732](RevenueCat/purchases-ios#6732): after offerings are successfully fetched and cached, the SDK proactively fetches the workflow for the current offering and pre-downloads all of its screen images and fonts, the same pattern already used for offering paywall images via `OfferingImagePreDownloader`. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Adds automatic workflow fetch + asset pre-download during offerings retrieval, increasing background work and network/cache activity which could impact performance or timing-sensitive flows if misbehaving. > > **Overview** > Pre-warms workflow step assets to avoid mid-transition pop-in by **fetching the current offering’s workflow after offerings are loaded** and pre-downloading its screen images and fonts. > > This introduces `WorkflowAssetPreDownloader` (deduped by workflow id) and wires it into `WorkflowManager.getWorkflow` (pre-download failures are logged and do not block returning the workflow). `OfferingsManager` now accepts an optional `workflowPreWarmer` callback, which `PurchasesFactory` provides to trigger workflow pre-warming for the current offering; tests were updated/added to cover these behaviors, plus a `NoOpLogHandler` for silencing logs in tests. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit ef23ab0. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

Summary
PaywallCacheWarmingwithwarmUpWorkflowCaches(workflow:), which pre-downloads images, videos, and fonts across all workflow screens (in a single parallel task group)Purchases.workflow(forOfferingIdentifier:)— no extra network call; assets are warmed the first time a workflow is fetched-EnableWorkflowsEndpointlaunch argumentNotes
Intentionally prewarming all screens (not just those reachable from
initialStepId). If workflows grow to have many screens with complex branching, a bounded graph walk viaWorkflowStep.stepTriggerActionswould be a better approach — this is documented in a comment in the implementation.Labels
`pr:feat` `pr:RevenueCatUI` `feat:PaywallsV2`
Test plan
🤖 Generated with Claude Code
Note
Medium Risk
Adds automatic prewarming of workflow images/videos (and fonts on non-tvOS) as a side effect of fetching a workflow, which can increase background work, bandwidth, and caching behavior. Logic is guarded per-workflow ID but still touches asset download and file caching paths concurrently.
Overview
Fetching a workflow via
Purchases.workflow(forOfferingIdentifier:)now kicks off background prewarming of that workflow’s screen assets (images, low-res videos, and downloadable fonts on non-tvOS) using the existingPaywallCacheWarminginfrastructure.PaywallCacheWarminggainswarmUpWorkflowCaches(workflow:), dedupes by workflow ID, logs a newStrings.paywalls.warming_up_workflowmessage, and prefetches assets for all screens in parallel viaFileRepository/font installation. Cache-warming helpers were extended to compute image/video URLs forWorkflowScreen, and unit test mocks were updated accordingly.Reviewed by Cursor Bugbot for commit 6e984bb. Bugbot is set up for automated code reviews on this repo. Configure here.