feat: add evaluateFlags() API for single-call flag evaluation#130
Closed
feat: add evaluateFlags() API for single-call flag evaluation#130
Conversation
Phase 1 of the Server SDK Feature Flag Evaluations RFC. Mirrors the Node (posthog-js#3476) and Python (posthog-python#539) implementations. * `Client::evaluateFlags()` returns a `FeatureFlagEvaluations` snapshot. Reads on the snapshot do not trigger additional `/flags` requests; access via `isEnabled` / `getFlag` fires a deduped `$feature_flag_called` event the first time each key is touched. `getFlagPayload` is silent. * `capture()` accepts a `flags` snapshot to attach `$feature/<key>` and `$active_feature_flags` properties without a fresh `/flags` round trip. * The single-flag dedup is extracted to `Client::captureFlagCalledIfNeeded()`, shared by the legacy path and the snapshot. * `flag_keys_to_evaluate` and `geoip_disable` are forwarded on the `/flags` request body when callers pass `flagKeys` or `disableGeoip`. * New `feature_flags_log_warnings` option silences filter warnings emitted from `only()` / `onlyAccessed()`. Also fixes a pre-existing bug in `SizeLimitedHash::contains/add` that caused the per-distinct_id `$feature_flag_called` dedup to never match after the first event. The new snapshot path requires real dedup, and existing tests only ever made a single call so the bug was invisible until now. Generated-By: PostHog Code Task-Id: 1f29305a-ee56-456e-a341-8faa4eb8716d
Contributor
Author
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.
Summary
Phase 1 of the Server SDK Feature Flag Evaluations RFC ported to posthog-php. Mirrors the Node (posthog-js#3476) and Python (posthog-python#539) implementations.
Adds a single-call flag evaluation API:
Client::evaluateFlags(distinctId, …)returns aFeatureFlagEvaluationssnapshot. Reads on the snapshot do not trigger additional/flagsrequests.isEnabled($key)/getFlag($key)record access and fire a deduped\$feature_flag_calledevent the first time each key is touched, with the rich metadata (\$feature_flag_id,\$feature_flag_version,\$feature_flag_reason,\$feature_flag_request_id).getFlagPayload($key)is silent — no event, no access tracking.only([...])andonlyAccessed()return filtered clones with their own access set, so child reads don't back-propagate.onlyAccessed()warns and falls back to the full snapshot when no flags have been accessed.capture(['flags' => \$snapshot, …])attaches\$feature/<key>and\$active_feature_flagsfrom the snapshot — no extra/flagsrequest. Takes precedence over the existingsend_feature_flagspath;send_feature_flagsis not deprecated in this PR.The single-flag dedup block in
getFeatureFlagResult()is now extracted toClient::captureFlagCalledIfNeeded()and shared by both code paths against the existing per-distinct_idSizeLimitedHashcache.Pre-flight answers
getFeatureFlagResult()— extracted in this PR toClient::captureFlagCalledIfNeeded(). Cache:Client::\$distinctIdsFeatureFlagsReported(cap 50,000)./flagsresponse handler?Client::flags()already returns the v4 shape (flags[\$key]['metadata']['{id,version,payload}'],flags[\$key]['reason']['description'], top-levelrequestId,evaluatedAt). No new lower-level call needed.Client::loadFlags()polls/api/feature_flag/local_evaluationwith ETag/304 support. There is noflag_definitions_loaded_attimestamp in posthog-php today, so locally-evaluated records leave it null. Adding it is left for a follow-up.Client::capture(array \$message)takes a single associative array; the newflagsparameter slots in as a top-level key.lib/FeatureFlagEvaluations.php(PSR-4 →PostHog\\FeatureFlagEvaluations), with companionslib/EvaluatedFlagRecord.phpandlib/FeatureFlagEvaluationsHost.php.Pre-existing dedup bug fix
SizeLimitedHash::contains/addusedarray_key_existsto compare values to keys, so the per-distinct_id\$feature_flag_calleddedup never actually matched after the first event. Existing tests only ever made a single call per (flag, distinct_id), so the bug was invisible. The new snapshot path requires real dedup; this PR fixes both helpers to operate on a per-key set as intended.Phase 2 — follow-up
Phase 2 (a separate minor) will deprecate the legacy methods now superseded by
evaluateFlags():Client::getFeatureFlag()/PostHog::getFeatureFlag()Client::isFeatureEnabled()/PostHog::isFeatureEnabled()Client::getFeatureFlagResult()/PostHog::getFeatureFlagResult()Client::getAllFlags()/PostHog::getAllFlags()send_feature_flagscapture parameterClient::getFeatureFlagPayload()(already deprecated) and the rich-result-for-one-flag method (getFeatureFlagResult()) are intentionally not removed in either phase — there is no public equivalent on the new API for fetching a single flag's full result.Test plan
vendor/bin/phpunit --filter FeatureFlagEvaluationsTest— 19 new tests, 65 assertions, all passingvendor/bin/phpunit— full suite passes (1 pre-existing unrelated failure in `testLoadFeatureFlagsWrongKey` reproduces on the upstream branch this is based on)Created with PostHog Code