feat(example): add precomputed client demo#241
Open
leoromanovsky wants to merge 15 commits intomainfrom
Open
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.
fa04c22 to
7524fa0
Compare
2a2e1bc to
63b0d58
Compare
7524fa0 to
1abb120
Compare
63b0d58 to
95a40f0
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.
1abb120 to
f85971f
Compare
328f129 to
5d88392
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
Add the main precomputed client implementation with: - Server-side precomputed flag assignments with instant lookups - Support for all flag types: string, boolean, integer, numeric, JSON - Bandit action support with attribute decoding - Builder pattern with extensive configuration options - Offline mode with initial configuration support - Background polling with configurable interval and jitter - Assignment and bandit logging with deduplication caches - Graceful error handling mode The client fetches precomputed assignments from the edge endpoint, eliminating client-side flag evaluation overhead. Includes comprehensive instrumented tests covering: - All flag type assignments - Assignment logging and deduplication - Bandit actions - Offline mode - SDK test data integration
42bc3da to
590804e
Compare
- Make polling fields volatile for thread safety - Return user's default value on parse failure instead of hardcoded 0 - Extract magic string to NO_ACTION_CACHE_KEY constant - Fix banditActions serialization to match JS SDK wire format - Add comments for hash length and jitter calculation - Rename misleading test to testNonGracefulModeCanBeConfigured
5d88392 to
d15bde0
Compare
Extract environment prefix from SDK key to automatically construct the correct edge endpoint URL (e.g., https://5qhpgd.fs-edge-assignment.eppo.cloud). This removes the need for users to manually configure the base URL.
Add demonstration of the precomputed client in the example app: - Rename MainActivity -> HomeActivity, SecondActivity -> StandardClientActivity - Add PrecomputedActivity with: - Subject ID input with server/disk initialization options - Dynamic subject attributes table (add/remove key-value pairs) - Flag key input with type selection (string, bool, int, numeric, JSON) - Assignment log display - Proper lifecycle handling for polling (pause/resume/stop) - Add back navigation to all activities - Update layouts and strings This provides a complete interactive demo of the precomputed client for testing and development purposes.
d15bde0 to
dd5c86d
Compare
Address PR review feedback by removing redundant inline comments that simply restated what the test assertions already conveyed.
sameerank
approved these changes
Feb 5, 2026
Comment on lines
+98
to
+104
| Button removeButton = new Button(this); | ||
| removeButton.setText("X"); | ||
| removeButton.setMinWidth(0); | ||
| removeButton.setMinHeight(0); | ||
| removeButton.setMinimumWidth(0); | ||
| removeButton.setMinimumHeight(0); | ||
| removeButton.setPadding(16, 8, 16, 8); |
There was a problem hiding this comment.
Is it common to create UI components programmatically like this in Android? 😮
Also .setMinWidth and .setMinimumWidth are different?
Comment on lines
+230
to
+231
| // JSON assignments return JsonNode - for simplicity, we show as string | ||
| appendToLog("JSON assignment for '" + flagKey + "': (use getJSONAssignment() API)"); |
There was a problem hiding this comment.
Could you do
JsonNode jsonResult = precomputedClient.getJSONAssignment(flagKey, null);
and stringify it with jsonResult.toString()?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Provide an interactive demonstration of the precomputed client in the example app for testing and development purposes.
Changes
Activity Refactoring:
MainActivity→HomeActivity(launcher with client selection)SecondActivity→StandardClientActivity(existing client demo)New
PrecomputedActivity:platformandappVersiononPause()→ pause pollingonResume()→ resume pollingonDestroy()→ stop pollingLayouts:
activity_home.xml- Updated with precomputed client buttonactivity_precomputed.xml- New layout with all controlsResources:
Screen.Recording.2026-02-03.at.5.01.09.PM.mov
Decisions
PR Stack
This PR is part of the precomputed client feature, split for easier review:
Why this structure: Example app changes are purely additive and don't affect the SDK library. Keeping them separate allows the core feature to be merged and released independently if needed.
Merge order: This is the final PR in the stack. Merge PRs 1-4 first.
Full Stack Summary