feat(remote-config): add RemoteConfigManager#7067
Conversation
4 builds increased size
RevenueCat 1.0 (1)
|
| Item | Install Size Change |
|---|---|
| DYLD.String Table | ⬆️ 50.3 kB |
| DYLD.Exports | ⬆️ 4.1 kB |
| Code Signature | ⬆️ 3.8 kB |
| 📝 RCWebPurchaseRedemption.init | ⬆️ 2.9 kB |
| RCWebPurchaseRedemption.Objc Metadata | ⬇️ -2.9 kB |
BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.local-source
⚖️ Compare build
📦 Install build
⏱️ Analyze build performance
Total install size change: ⬆️ 19.5 kB (0.15%)
Total download size change: ⬆️ 6.1 kB (0.14%)
Largest size changes
| Item | Install Size Change |
|---|---|
| 📝 RevenueCat.RemoteConfigStrings.value witness | ⬆️ 7.9 kB |
| 📝 RevenueCat.RCContainer.ElementParser.checksumString(in) | ⬆️ 1.5 kB |
| 🗑 RevenueCat.RCContainer.Parser.checksumString(in) | ⬇️ -1.5 kB |
| DYLD.String Table | ⬆️ 1.3 kB |
| 📝 RevenueCat.RCContainer.ElementParser.base64URLString(in) | ⬆️ 1.2 kB |
BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.cocoapods
⚖️ Compare build
📦 Install build
⏱️ Analyze build performance
Total install size change: ⬆️ 40.3 kB (0.14%)
Total download size change: ⬆️ 13.4 kB (0.2%)
Largest size changes
| Item | Install Size Change |
|---|---|
| DYLD.String Table | ⬆️ 11.4 kB |
| 📝 RevenueCat.RemoteConfigStrings.value witness | ⬆️ 7.9 kB |
| 📝 RevenueCat.RCContainer.ElementParser.checksumString(in) | ⬆️ 1.5 kB |
| 🗑 RevenueCat.RCContainer.Parser.checksumString(in) | ⬇️ -1.5 kB |
| 📝 RevenueCat.RCContainer.ElementParser.base64URLString(in) | ⬆️ 1.2 kB |
BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.spm
⚖️ Compare build
📦 Install build
⏱️ Analyze build performance
Total install size change: ⬆️ 19.7 kB (0.17%)
Total download size change: ⬆️ 5.1 kB (0.11%)
Largest size changes
| Item | Install Size Change |
|---|---|
| 📝 RevenueCat.RemoteConfigStrings.value witness | ⬆️ 7.9 kB |
| 📝 RevenueCat.RCContainer.ElementParser.checksumString(in) | ⬆️ 1.5 kB |
| 🗑 RevenueCat.RCContainer.Parser.checksumString(in) | ⬇️ -1.5 kB |
| 📝 RevenueCat.RCContainer.ElementParser.base64URLString(in) | ⬆️ 1.2 kB |
| 🗑 RevenueCat.RCContainer.Parser.base64URLString(in) | ⬇️ -1.2 kB |
🛸 Powered by Emerge Tools
Comment trigger: Size diff threshold of 100.00kB exceeded
3df4088 to
1f95120
Compare
|
@RCGitBot please test |
|
@RCGitBot please test run-test-ios-15-and-14 |
|
🚀 Triggered run-test-ios-15-and-14 → Pipeline #39787 |
989bde7 to
96e80a7
Compare
69f7b0f to
41ad3fe
Compare
tonidero
left a comment
There was a problem hiding this comment.
Some small differences with Android, but in general, I do think it all makes sense! And as we discussed, we can iterate in follow-ups If needed.
96e80a7 to
d313b32
Compare
d676892 to
55b2419
Compare
caff100 to
25ac068
Compare
572b0f3 to
12f8722
Compare
❌ CI Job Failed —
|
12f8722 to
e37560b
Compare
e37560b to
f7ef32f
Compare
25ac068 to
97e93b7
Compare
f7ef32f to
e8b227e
Compare
| case let .success(.container(container, _)): | ||
| self.persist(container: container, previous: persisted) | ||
| case .success(.noContent): | ||
| break |
There was a problem hiding this comment.
204 refresh skips lastRefreshAt
Medium Severity
A successful noContent (204) refresh leaves disk cache unchanged and never updates lastRefreshAt, even though the server confirmed the config is current. Only container responses set lastRefreshAt in persist, so successful syncs that return no body look stale to any logic keyed off last refresh time.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit e8b227e. Configure here.
…-manager-config-cache Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # RevenueCat.xcodeproj/project.pbxproj # Sources/Logging/Strings/RemoteConfigStrings.swift
❌ CI Job Failed —
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
There are 3 total unresolved issues (including 1 from previous review).
❌ 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 59f7d0a. Configure here.
| case let .success(.container(container, _)): | ||
| self.persist(container: container, previous: persisted) | ||
| case .success(.noContent): | ||
| break |
There was a problem hiding this comment.
Success cases mismatch fetch result
High Severity
The refresh completion handler pattern-matches Result success as .container and .noContent, but RemoteConfigFetchResult is still a struct with an optional container produced by GetRemoteConfigOperation. This commit does not align those shapes, so wiring the manager to the real API will not handle 204 vs container responses correctly without further changes.
Reviewed by Cursor Bugbot for commit 59f7d0a. Configure here.
| ) -> [String: [String]] { | ||
| return previous | ||
| .merging(response.topics.topicBlobRefs) { _, changed in changed } | ||
| .filter { topic, _ in response.activeTopics.contains(topic) } |
There was a problem hiding this comment.
Topics lacks topicBlobRefs member
High Severity
mergedTopicBlobRefs reads response.topics.topicBlobRefs, but RemoteConfiguration.Topics only exposes entries and this commit does not add topicBlobRefs. The merge and persistence path therefore depend on an API that is not present alongside the manager.
Reviewed by Cursor Bugbot for commit 59f7d0a. Configure here.






Part of a stack of PRs, builds on #7076 and should be aligned with the Android equivalent in RevenueCat/purchases-android#3612.
Description
RemoteConfigManager, which is responsible for refreshing the latest config using theRemoteConfigAPI.PersistedRemoteConfigurationDownloading / storing the topics payloads itself will be done in a follow up PR.
Note
Medium Risk
Introduces a new remote-config refresh and disk persistence path that will affect SDK configuration once wired, but failures preserve cached state and the manager is not yet integrated into the main SDK flow.
Overview
Adds
RemoteConfigManagerto orchestrate remote config refresh: it readsPersistedRemoteConfigurationfrom disk, builds aRemoteConfigRequest(domain, manifest, prefetched blobs), calls the API once at a time, and on success decodes the container config and writes updated manifest, active topics, prefetch blobs, and merged topic blob refs (pruning inactive topics).RemoteConfigAPIis abstracted behindRemoteConfigAPITypefor testability. Parse and network failures log via newRemoteConfigStringscases and leave the existing cache unchanged; 204/no content also skips writes.Unit tests cover first vs subsequent requests, in-flight deduplication, persistence/merge behavior, and error paths. SDK lifecycle wiring and blob download are explicitly deferred.
Reviewed by Cursor Bugbot for commit 59f7d0a. Bugbot is set up for automated code reviews on this repo. Configure here.