Evaluate flags from the replicator cache when the replicator is not ready - #114
Closed
ryanechternacht wants to merge 1 commit into
Closed
ryanechternacht wants to merge 1 commit into
ryanechternacht wants to merge 1 commit into
Conversation
…eady In replicator mode, checkFlag, checkFlagWithEntitlement, and checkFlags skipped the datastream whenever the replicator's health endpoint reported ready: false, and went to the API instead. The replicator keeps its Redis cache when it loses its connection to Schematic, so those checks now evaluate from the cache regardless of readiness, matching the Go SDK. A flag missing from the cache still falls back to the API. Direct WebSocket mode is unchanged and still requires an active connection. The replicator answers 503 with a JSON body while not ready, and the health check only read the body on 2xx. An SDK that started while the replicator was not ready never learned cache_version and built cache keys under the wrong version. The health check now reads the body regardless of status. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2 of 3 tasks
bpapillon
approved these changes
Sep 29, 2026
Member
Author
|
Closing in favor of fixing this in the Replicator. The SDK is right to gate flag checks on Replicator readiness; the Replicator should keep reporting |
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.
Problem
In replicator mode the SDK polls the replicator's health endpoint and treats
readyas "connected". When a customer's Schematic account is closed or Schematic is unreachable, the replicator stays up with its Redis cache intact but reportsready: false.Today, when that happens:
checkFlag/checkFlagWithEntitlementskip the datastream (tryDatastreamCheckFlagreturns null whenisConnected()is false) and go to the API path: the local flag result cache, thenfeatures().checkFlag. With Schematic unreachable or the account closed, that call fails and the flag default is returned.checkFlagshas the sameisConnected()gate, so it goes to the result cache plus the bulkfeatures().checkFlagscall, and returns defaults for every key when that fails.The Go SDK (reference) does not gate flag checks on readiness.
useDataStream()only checks that a datastream client exists, and in replicator mode entity resolution evaluates with whatever the cache holds.A second issue made this worse. The replicator answers 503 with its JSON body while not ready, and
checkReplicatorHealthonly read the body on 2xx. An SDK that started while the replicator was not ready never learnedcache_version, so it built cache keys under the local rules engine version instead of the replicator's. Go reads the body regardless of status.Change
Schematic: newcanEvaluateViaDatastream()used by bothtryDatastreamCheckFlagand thecheckFlagsdatastream path. In replicator mode it returns true whenever a datastream client exists. In direct WebSocket mode it still requiresisConnected(), so WebSocket behavior is unchanged. A flag missing from the cache, or any evaluation error, still falls back to the API as before.DataStreamClient.checkReplicatorHealth: reads and parses the JSON body for any status, updates the cache version from it (keeping the last known version when none is reported), and still treats non-2xx orready: falseas not ready.Test
New
ReplicatorNotReadyTest:checkFlag,checkFlagWithEntitlement, andcheckFlagsreturn the cached evaluation and never touch the API client.{"ready": false, "cache_version": "v42"}: the client stays not connected but adoptsv42for cache keys.All three fail on
mainand pass with this change../gradlew compileJava spotlessCheck testpasses on JDK 11 (250 tests).🤖 Generated with Claude Code