Skip to content

Pre-warm image cache for workflow step states#3447

Merged
vegaro merged 5 commits into
mainfrom
cesar/wfl-workflow-image-predownloader
May 11, 2026
Merged

Pre-warm image cache for workflow step states#3447
vegaro merged 5 commits into
mainfrom
cesar/wfl-workflow-image-predownloader

Conversation

@vegaro

@vegaro vegaro commented May 7, 2026

Copy link
Copy Markdown
Member

Motivation

When the two-surface workflow slide animation (#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: 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.


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.

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

@codecov

codecov Bot commented May 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.33333% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.58%. Comparing base (c6fded7) to head (ef23ab0).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
...otlin/com/revenuecat/purchases/PurchasesFactory.kt 62.50% 6 Missing ⚠️
...cat/purchases/common/offerings/OfferingsManager.kt 83.33% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3447      +/-   ##
==========================================
+ Coverage   79.48%   79.58%   +0.10%     
==========================================
  Files         363      364       +1     
  Lines       14562    14596      +34     
  Branches     1979     1982       +3     
==========================================
+ Hits        11574    11616      +42     
+ Misses       2190     2181       -9     
- Partials      798      799       +1     

☔ View full report in Codecov by Sentry.
📢 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.

@vegaro vegaro changed the base branch from main to cesar/extract-paywall-predownloader May 7, 2026 12:41
@vegaro vegaro force-pushed the cesar/wfl-workflow-image-predownloader branch from aadd569 to c4697fc Compare May 7, 2026 12:45
Base automatically changed from cesar/extract-paywall-predownloader to main May 7, 2026 13:06
@vegaro vegaro force-pushed the cesar/wfl-workflow-image-predownloader branch 3 times, most recently from 6f71aee to 27d101f Compare May 7, 2026 13:16
@vegaro vegaro changed the base branch from main to cesar/paywall-localized-image-predownloader May 7, 2026 13:53
@vegaro vegaro force-pushed the cesar/wfl-workflow-image-predownloader branch 2 times, most recently from f4ea9bf to 17b3f23 Compare May 7, 2026 14:23
@vegaro vegaro marked this pull request as ready for review May 7, 2026 14:27
@vegaro vegaro requested review from a team as code owners May 7, 2026 14:27
@vegaro vegaro requested a review from facumenzella May 7, 2026 14:28
@vegaro vegaro force-pushed the cesar/wfl-workflow-image-predownloader branch from 667080a to 22d623c Compare May 7, 2026 15:47

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ 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 22d623ce3ae04e0e5b94416124f5e13e509acdbb. Configure here.

@vegaro vegaro changed the base branch from cesar/paywall-localized-image-predownloader to main May 7, 2026 16:07
@vegaro vegaro force-pushed the cesar/wfl-workflow-image-predownloader branch 2 times, most recently from 1514e4e to aded8a9 Compare May 7, 2026 16:09
@vegaro vegaro force-pushed the cesar/wfl-workflow-image-predownloader branch from aded8a9 to 53c48a4 Compare May 7, 2026 16:13

offeringsManager.getOfferings(
appUserId,
appInBackground = false,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth adding a test for appInBackground = true

import java.util.Date
import kotlin.time.Duration

internal typealias WorkflowPreWarmer = (appUserID: String, offeringIdentifier: String, appInBackground: Boolean) -> Unit

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we put this somewhere else? Let's slowly sunset Offerings

Pre-download is pure CPU work (tree traversal, URI building) that kicks off
async Coil/font-loader requests internally. No need to block onSuccess on it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment on lines +44 to +48
val result = workflowDetailResolver.resolve(response)
scope.launch {
runCatching { workflowAssetPreDownloader.preDownloadWorkflowAssets(result.workflow) }
.onFailure { errorLog(it) { "Failed to pre-download workflow assets" } }
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🍠

@facumenzella facumenzella left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice one

@vegaro vegaro enabled auto-merge May 11, 2026 05:19
@vegaro vegaro added this pull request to the merge queue May 11, 2026
Merged via the queue into main with commit 1bfed5e May 11, 2026
36 checks passed
@vegaro vegaro deleted the cesar/wfl-workflow-image-predownloader branch May 11, 2026 05:59
github-merge-queue Bot pushed a commit that referenced this pull request May 13, 2026
**This is an automatic release.**

## RevenueCat SDK
### 📦 Dependency Updates
* [RENOVATE] Update dependency gradle to v8.14.5 (#3459) via RevenueCat
Git Bot (@RCGitBot)

## RevenueCatUI SDK
### ✨ New Features
* Pre-warm image cache for workflow step states (#3447) via Cesar de la
Vega (@vegaro)
### Paywallv2
#### ✨ New Features
* Add `close_workflow` button action (#3453) via Cesar de la Vega
(@vegaro)
#### 🐞 Bugfixes
* Fix preload VideoComponent fallback override images (#3449) via Cesar
de la Vega (@vegaro)

### 🔄 Other Changes
* Select blob source by priority and weighted random (#3458) via Toni
Rico (@tonidero)
* [AUTOMATIC] Update golden test files for backend integration tests
(#3473) via RevenueCat Git Bot (@RCGitBot)
* Clean up unreferenced topic files after successful remote-config
refresh (#3439) via Toni Rico (@tonidero)
* Cache remote config response in memory with TTL and persist to disk
(#3457) via Toni Rico (@tonidero)
* build(deps): bump fastlane from 2.233.1 to 2.234.0 (#3463) via
dependabot[bot] (@dependabot[bot])
* Update codelabs links (#3460) via Jaewoong Eum (@skydoves)
* Add RemoteConfigManager and TopicFetcher (#3437) via Toni Rico
(@tonidero)
* Add exit offers support to workflows (#3452) via Cesar de la Vega
(@vegaro)
* Update baseline profiles (#3461) via RevenueCat Git Bot (@RCGitBot)
* Add network scaffolding for remote config endpoint (#3435) via Toni
Rico (@tonidero)
* test: cover singleStepFallbackId == initialStepId edge case (#3445)
via Facundo Menzella (@facumenzella)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: this is a release/versioning update (SNAPSHOT -> final) plus
docs deployment path changes, with no functional code changes beyond
version constants.
> 
> **Overview**
> Finalizes the `10.6.0` release by switching all version references
from `10.6.0-SNAPSHOT` to `10.6.0` (root `.version`,
`gradle.properties`, `Config.frameworkVersion`, and sample/test app
`libs.versions.toml` files).
> 
> Updates documentation publishing to point at the `10.6.0` docs path
(CircleCI S3 sync target and `docs/index.html` redirect), and prepends
the `10.6.0` section to `CHANGELOG.md`/`CHANGELOG.latest.md`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
4da1697. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
matteinn pushed a commit to matteinn/purchases-android that referenced this pull request Jun 5, 2026
Extracted from
RevenueCat#3447

Little refactor extracting PaywallComponentsImagePreDownloader

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes paywall image predownload behavior and wiring, which could
increase/alter network/cache usage for paywall assets (notably header
images) and affect startup/background work.
> 
> **Overview**
> Extracts Paywall V2 image predownload logic from
`OfferingImagePreDownloader` into a new
`PaywallComponentsImagePreDownloader`, and updates `PurchasesFactory` to
create/reuse a single `CoilImageDownloader` and pass the new
predownloader through.
> 
> Updates the image selection for Paywall V2 to include `header` stack
assets (in addition to stack/sticky footer/background), and adjusts
tests to cover the new header image/icon downloads.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2bb8a6e. 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants