-
Notifications
You must be signed in to change notification settings - Fork 3
feat: add precomputed configuration storage #239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Add the foundational data structures and utilities for the precomputed client feature: - ObfuscationUtils: MD5 hashing for flag key obfuscation - PrecomputedFlag: DTO for precomputed flag assignments - PrecomputedBandit: DTO for precomputed bandit assignments - PrecomputedConfigurationResponse: Wire protocol response parsing - BanditResult: Result container for bandit action lookups - MissingSubjectKeyException: Validation exception Includes comprehensive unit tests for serialization round-trips and MD5 hash consistency.
sameerank
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The empty-vs-null behavior returned by loadConfigFromCache is the main one that was confusing to me. The rest are nits. Looks good overall!
eppo/src/main/java/cloud/eppo/android/PrecomputedConfigurationStore.java
Outdated
Show resolved
Hide resolved
eppo/src/main/java/cloud/eppo/android/dto/PrecomputedConfigurationResponse.java
Show resolved
Hide resolved
| return CompletableFuture.completedFuture(null); | ||
| } | ||
| return cacheLoadFuture = | ||
| CompletableFuture.supplyAsync( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing to fix here, but just noting that there's a race condition due to a sync check and async read. You've handled it by ensuring that exceptions are caught so it's not dangerous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea absolutely thanks for mentioning; I'm being kind of lazy and copying the same pattern as exists in the local-eval configuration store.
eppo/src/main/java/cloud/eppo/android/dto/PrecomputedConfigurationResponse.java
Outdated
Show resolved
Hide resolved
8f4e45c to
e80e6f9
Compare
Add md5HexPrefix() method that only converts the bytes needed for a given prefix length, avoiding unnecessary work when only a prefix is required (e.g., cache file naming uses first 8 chars). Includes unrolled loop for the common 4-byte (8 hex char) case to help compiler optimization, following iOS SDK PR #93 approach.
Extract common file caching functionality from ConfigCacheFile into a new BaseCacheFile base class. This enables reuse for the upcoming precomputed configuration cache without code duplication. - Add BaseCacheFile with common read/write/delete operations - Refactor ConfigCacheFile to extend BaseCacheFile - No functional changes to existing behavior
Add the storage layer for precomputed flag configurations: - PrecomputedCacheFile: Disk cache file extending BaseCacheFile - PrecomputedConfigurationStore: In-memory + disk storage with async save/load operations and proper thread synchronization - Updates in-memory config even if disk write fails for resilience Also adds test data files to Makefile for integration testing. Includes unit tests for cache operations and failure scenarios.
e80e6f9 to
dd5309f
Compare
- Return null consistently in loadConfigFromCache for both file-not-found and read-error cases - Use static EMPTY singleton in PrecomputedConfigurationResponse.empty() - Use Collections.singletonMap() in getEnvironment() for memory efficiency
Motivation
The precomputed client needs to store configuration both in-memory for fast access and on disk for offline/startup scenarios. This PR adds the storage layer that manages this caching.
Changes
Storage:
PrecomputedCacheFile- Disk cache file extendingBaseCacheFilewith precomputed-specific namingPrecomputedConfigurationStore- Thread-safe storage manager with:Build:
Makefileto download precomputed test data files from sdk-test-dataTests:
PrecomputedConfigurationStoreTest- Unit tests for:Decisions
volatilefor configuration field to ensure visibility across threads without locking on readscacheLock) and load future management (cacheLoadLock)PR Stack
This PR is part of the precomputed client feature, split for easier review:
Why this structure: The storage layer depends on both the base cache infrastructure (PR 1) and the DTOs (PR 2). It's isolated from the client implementation, making it easier to review the caching logic independently.
Merge order: PR 1 and PR 2 must be merged first, then this PR's base updated to
main.