From f40048a68561620cf7b1b6e9235df7f697902d59 Mon Sep 17 00:00:00 2001 From: Kamo Spertsyan Date: Thu, 30 Jul 2026 19:21:55 +0300 Subject: [PATCH 1/3] feat: expose InvalidateRemoteConfigsCache, bump sandwich to 7.12.0 Bridges the new native cache invalidation API (android-sdk 9.7.0 / qonversion-ios-sdk 6.14.0 via sandwich 7.12.0). The method performs no network request and has no callback - it marks the remote configs cache stale so the next RemoteConfig / RemoteConfigList call fetches a fresh targeting evaluation. An in-flight RemoteConfig load is re-issued once; an in-flight RemoteConfigList completes with the evaluation it started with. Not needed after Identify - the SDK invalidates automatically. Call after initialization. Co-Authored-By: Claude Fable 5 --- Editor/QonversionDependencies.xml | 4 ++-- .../unitywrapper/QonversionWrapper.java | 4 ++++ Runtime/Android/QonversionWrapperAndroid.cs | 5 +++++ Runtime/Scripts/IQonversion.cs | 20 +++++++++++++++++++ .../Scripts/Internal/QonversionInternal.cs | 6 ++++++ .../wrappers/qonversion/IQonversionWrapper.cs | 1 + .../qonversion/QonversionWrapperNoop.cs | 4 ++++ Runtime/iOS/Plugins/QonversionBridge.m | 4 ++++ Runtime/iOS/QonversionWrapperIOS.cs | 10 ++++++++++ 9 files changed, 56 insertions(+), 2 deletions(-) diff --git a/Editor/QonversionDependencies.xml b/Editor/QonversionDependencies.xml index 10858ea..5add313 100644 --- a/Editor/QonversionDependencies.xml +++ b/Editor/QonversionDependencies.xml @@ -1,11 +1,11 @@ - + - + diff --git a/Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java b/Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java index 4a621d1..185bd38 100644 --- a/Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java +++ b/Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java @@ -82,6 +82,10 @@ public static synchronized void syncHistoricalData() { qonversionSandwich.syncHistoricalData(); } + public static synchronized void invalidateRemoteConfigsCache() { + qonversionSandwich.invalidateRemoteConfigsCache(); + } + public static synchronized void syncPurchases() { qonversionSandwich.syncPurchases(); } diff --git a/Runtime/Android/QonversionWrapperAndroid.cs b/Runtime/Android/QonversionWrapperAndroid.cs index 8407b4a..155d0a8 100644 --- a/Runtime/Android/QonversionWrapperAndroid.cs +++ b/Runtime/Android/QonversionWrapperAndroid.cs @@ -27,6 +27,11 @@ public void SyncHistoricalData() CallQonversion("syncHistoricalData"); } + public void InvalidateRemoteConfigsCache() + { + CallQonversion("invalidateRemoteConfigsCache"); + } + public void SyncStoreKit2Purchases() { } diff --git a/Runtime/Scripts/IQonversion.cs b/Runtime/Scripts/IQonversion.cs index 6495dce..f334fab 100644 --- a/Runtime/Scripts/IQonversion.cs +++ b/Runtime/Scripts/IQonversion.cs @@ -127,6 +127,26 @@ public interface IQonversion /// Remote Configs public void RemoteConfigList(string[] contextKeys, bool includeEmptyContextKey, Qonversion.OnRemoteConfigListReceived callback); + /// + /// Invalidates the cache of remote configs so the next RemoteConfig or + /// RemoteConfigList call fetches a fresh targeting evaluation from the + /// server instead of returning the cached copy. + /// + /// This method performs no network request itself — it only marks the + /// cached values as stale. An in-flight RemoteConfig load is re-issued + /// once so its waiting callbacks receive a fresh evaluation; an + /// in-flight RemoteConfigList completes with the evaluation it started + /// with. + /// + /// Call it when the targeting inputs changed and you need the change + /// reflected immediately, for example after setting a batch of user + /// properties your remote config targeting depends on. You do NOT need + /// to call it after Identify — the SDK invalidates the cache on + /// identity changes automatically. Call it after initialization. + /// + /// Remote Configs + public void InvalidateRemoteConfigsCache(); + /// /// This function should be used for the test purposes only. Do not forget to delete the usage of this function before the release. /// Use this function to attach the user to the experiment. diff --git a/Runtime/Scripts/Internal/QonversionInternal.cs b/Runtime/Scripts/Internal/QonversionInternal.cs index 599793e..a07fe3f 100644 --- a/Runtime/Scripts/Internal/QonversionInternal.cs +++ b/Runtime/Scripts/Internal/QonversionInternal.cs @@ -213,6 +213,12 @@ public void RemoteConfigList(string[] contextKeys, bool includeEmptyContextKey, instance.RemoteConfigList(contextKeysJson, includeEmptyContextKey, OnRemoteConfigListForContextKeysMethodName); } + public void InvalidateRemoteConfigsCache() + { + var instance = GetNativeWrapper(); + instance.InvalidateRemoteConfigsCache(); + } + public void AttachUserToExperiment(string experimentId, string groupId, Qonversion.OnAttachUserResponseReceived callback) { AttachUserCallback = callback; diff --git a/Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs b/Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs index aefe445..cf6d9ea 100644 --- a/Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs +++ b/Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs @@ -26,6 +26,7 @@ internal interface IQonversionWrapper void RemoteConfig([CanBeNull] string contextKey, string callbackName); void RemoteConfigList(string callbackName); void RemoteConfigList(string contextKeysJson, bool includeEmptyContextKey, string callbackName); + void InvalidateRemoteConfigsCache(); void AttachUserToExperiment(string experimentId, string groupId, string callbackName); void DetachUserFromExperiment(string experimentId, string callbackName); void AttachUserToRemoteConfiguration(string remoteConfigurationId, string callbackName); diff --git a/Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs b/Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs index 797d794..4c8b523 100644 --- a/Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs +++ b/Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs @@ -83,6 +83,10 @@ public void RemoteConfigList(string contextKeysJson, bool includeEmptyContextKey { } + public void InvalidateRemoteConfigsCache() + { + } + public void AttachUserToExperiment(string experimentId, string groupId, string callbackName) { } diff --git a/Runtime/iOS/Plugins/QonversionBridge.m b/Runtime/iOS/Plugins/QonversionBridge.m index d9fe8fe..75c74c4 100644 --- a/Runtime/iOS/Plugins/QonversionBridge.m +++ b/Runtime/iOS/Plugins/QonversionBridge.m @@ -58,6 +58,10 @@ void _syncHistoricalData() { [qonversionSandwich syncHistoricalData]; } +void _invalidateRemoteConfigsCache() { + [qonversionSandwich invalidateRemoteConfigsCache]; +} + void _syncStoreKit2Purchases() { [qonversionSandwich syncStoreKit2Purchases]; } diff --git a/Runtime/iOS/QonversionWrapperIOS.cs b/Runtime/iOS/QonversionWrapperIOS.cs index d3dbb42..4b853f6 100644 --- a/Runtime/iOS/QonversionWrapperIOS.cs +++ b/Runtime/iOS/QonversionWrapperIOS.cs @@ -27,6 +27,9 @@ internal class QonversionWrapperIOS : IQonversionWrapper [DllImport("__Internal")] private static extern void _syncHistoricalData(); + [DllImport("__Internal")] + private static extern void _invalidateRemoteConfigsCache(); + [DllImport("__Internal")] private static extern void _syncStoreKit2Purchases(); @@ -156,6 +159,13 @@ public void SyncHistoricalData() #endif } + public void InvalidateRemoteConfigsCache() + { +#if UNITY_IOS + _invalidateRemoteConfigsCache(); +#endif + } + public void SyncStoreKit2Purchases() { #if UNITY_IOS From e9504eb0ad346a8336cd86dc54f018daa323dc73 Mon Sep 17 00:00:00 2001 From: Kamo Spertsyan Date: Thu, 30 Jul 2026 19:38:41 +0300 Subject: [PATCH 2/3] review: doc conventions - see-cref links, summary/remarks split, retry note - Cross-references now use (the file's convention) instead of plain text; the elaboration paragraphs moved from to so the completion tooltip stays short. - State the retry degradation explicitly and the pre-initialization behavior (GetSharedInstance throws before Initialize). - Explicit interface type instead of var in QonversionInternal (29:4 precedent in the file). Co-Authored-By: Claude Fable 5 --- Runtime/Scripts/IQonversion.cs | 21 ++++++++++++------- .../Scripts/Internal/QonversionInternal.cs | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/Runtime/Scripts/IQonversion.cs b/Runtime/Scripts/IQonversion.cs index f334fab..e8b01b5 100644 --- a/Runtime/Scripts/IQonversion.cs +++ b/Runtime/Scripts/IQonversion.cs @@ -128,22 +128,27 @@ public interface IQonversion public void RemoteConfigList(string[] contextKeys, bool includeEmptyContextKey, Qonversion.OnRemoteConfigListReceived callback); /// - /// Invalidates the cache of remote configs so the next RemoteConfig or - /// RemoteConfigList call fetches a fresh targeting evaluation from the - /// server instead of returning the cached copy. - /// + /// Invalidates the cache of remote configs so the next or + /// call fetches + /// a fresh targeting evaluation from the server instead of returning the cached copy. + /// + /// /// This method performs no network request itself — it only marks the /// cached values as stale. An in-flight RemoteConfig load is re-issued /// once so its waiting callbacks receive a fresh evaluation; an /// in-flight RemoteConfigList completes with the evaluation it started - /// with. + /// with. If the re-issued load fails, the previously received evaluation + /// is delivered instead of an error — the call never degrades below the + /// pre-invalidation result. /// /// Call it when the targeting inputs changed and you need the change /// reflected immediately, for example after setting a batch of user /// properties your remote config targeting depends on. You do NOT need - /// to call it after Identify — the SDK invalidates the cache on - /// identity changes automatically. Call it after initialization. - /// + /// to call it after — the SDK invalidates the + /// cache on identity changes automatically. Call it after + /// : calling before initialization + /// throws. + /// /// Remote Configs public void InvalidateRemoteConfigsCache(); diff --git a/Runtime/Scripts/Internal/QonversionInternal.cs b/Runtime/Scripts/Internal/QonversionInternal.cs index a07fe3f..dc2a24c 100644 --- a/Runtime/Scripts/Internal/QonversionInternal.cs +++ b/Runtime/Scripts/Internal/QonversionInternal.cs @@ -215,7 +215,7 @@ public void RemoteConfigList(string[] contextKeys, bool includeEmptyContextKey, public void InvalidateRemoteConfigsCache() { - var instance = GetNativeWrapper(); + IQonversionWrapper instance = GetNativeWrapper(); instance.InvalidateRemoteConfigsCache(); } From c6cc5d6ef9168dd42299c70299e09c405fb19e4a Mon Sep 17 00:00:00 2001 From: Kamo Spertsyan Date: Thu, 30 Jul 2026 19:46:39 +0300 Subject: [PATCH 3/3] review: disambiguate the remaining overloaded crefs RemoteConfig and Identify both have two overloads; RemoteConfigList in the same block already carried a signature. IDE hover now resolves to the intended method on all three. Co-Authored-By: Claude Fable 5 --- Runtime/Scripts/IQonversion.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Runtime/Scripts/IQonversion.cs b/Runtime/Scripts/IQonversion.cs index e8b01b5..7a9e625 100644 --- a/Runtime/Scripts/IQonversion.cs +++ b/Runtime/Scripts/IQonversion.cs @@ -128,7 +128,7 @@ public interface IQonversion public void RemoteConfigList(string[] contextKeys, bool includeEmptyContextKey, Qonversion.OnRemoteConfigListReceived callback); /// - /// Invalidates the cache of remote configs so the next or + /// Invalidates the cache of remote configs so the next or /// call fetches /// a fresh targeting evaluation from the server instead of returning the cached copy. /// @@ -144,7 +144,7 @@ public interface IQonversion /// Call it when the targeting inputs changed and you need the change /// reflected immediately, for example after setting a batch of user /// properties your remote config targeting depends on. You do NOT need - /// to call it after — the SDK invalidates the + /// to call it after — the SDK invalidates the /// cache on identity changes automatically. Call it after /// : calling before initialization /// throws.