* Use server time for remote config refreshes
* Assert production remote config request dates
* Clarify remote config refresh timestamps
* Test production refresh time round trip
* perf(remote-config): cache persisted config in memory on RemoteConfigDiskCache
Keep an in-memory copy of the persisted RemoteConfiguration so read() and
topic(_:) don't hit disk on every call. It's reset to the new value on write
and cleared on clear(), and lazily loaded from disk on the next read.
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor(remote-config): distinguish not-loaded from empty with CacheState enum
Use a CacheState enum (notLoaded / loaded) so read() only hits disk once,
including when nothing is persisted, instead of re-reading on every call.
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor(remote-config): name the in-memory cache `snapshot` to match Android
Aligns naming with purchases-android's RemoteConfigDiskCache in-memory snapshot.
Co-authored-by: Cursor <cursoragent@cursor.com>
* test(remote-config): cover snapshot caching of read misses
Verify a decoding failure and a missing file both cache the miss, so the
disk is only read once even if the persisted file changes afterwards.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(remote-config): only update in-memory snapshot when write succeeds
Avoid serving a configuration from memory that failed to persist to disk.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(remote-config): update disk and snapshot atomically in write/clear
Perform the disk mutation and snapshot update under the snapshot lock so
concurrent reads can't observe a torn state (disk changed but snapshot stale),
and keep a consistent lock order (snapshot then cache) across read/write/clear.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>