Skip to content

chore!: pass the loaded flags to onFeatureFlags and reloadFeatureFlags - #664

Merged
turnipdabeets merged 10 commits into
chore/v6-adopt-posthog-android-4from
chore/v6-flags-loaded-result
Oct 28, 2026
Merged

turnipdabeets merged 10 commits into
chore/v6-adopt-posthog-android-4from
chore/v6-flags-loaded-result

Conversation

@turnipdabeets

@turnipdabeets turnipdabeets commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

💡 Motivation and Context

This assumed we’ve pulled in Android 4.0

PostHogConfig.onFeatureFlags was a void Function() and reloadFeatureFlags() returned Future<void>, so Flutter apps couldn't tell what loaded or whether loading failed. posthog-ios 4.0 passes this to its listener and reload callback (PostHog/posthog-ios#897, #913), posthog-android 4.0 gets the same (PostHog/posthog-android#877), and posthog-js already passes it to onFeatureFlags.

Closes #231

Both now carry a new PostHogFeatureFlagsLoaded:

Field Meaning
flags keys of the enabled flags
variants enabled flag → true or the variant string; disabled flags left out
errorsLoading true when the latest load failed; the values are then the last known ones

Per platform:

Platform onFeatureFlags reloadFeatureFlags()
iOS/macOS from posthog-ios onFeatureFlags from posthog-ios reloadFeatureFlags(_:)
Android from posthog-android PostHogFeatureFlagsCallback from posthog-android reloadFeatureFlags
Web from posthog-js onFeatureFlags posthog-js 1.438.2+: awaits featureFlags.reloadFeatureFlagsAsync(), which settles after this reload's own request (not one already in flight); errorsLoading unless it loaded. Older posthog-js: the next onFeatureFlags call, with a timeout covering every retry posthog-js may make ((feature_flag_request_max_retries + 2) × feature_flag_request_timeout_ms + 500 ms per retry, 9.5 s with defaults)
Windows/Linux from the Dart core awaits the Dart core's reload

fromMap stays internal (channel_serialization.dart), in line with #646.

Breaking: onFeatureFlags = () { … } becomes (loaded) { … } or (_) { … }. Callers of reloadFeatureFlags() are unaffected; custom platform interface implementations must return the new type.

Depends on #663 (posthog-android 4.0). The Android code is written against the PostHogFeatureFlagsLoaded posthog-android 4.0 adds, which is still in review, so this stays a draft until that API is final.

💚 How did you test it?

  • flutter analyze, flutter test (1258 pass), dart format, scripts/check-api-dart.sh (snapshot updated).
  • New tests: the method channel passes native flags to the callback and drops disabled ones; malformed native args give empty flags; on desktop, reloadFeatureFlags() returns the loaded flags, and after a failed request returns the last known flags with errorsLoading: true, as does onFeatureFlags. The desktop test fails when errorsLoading is hardcoded to false.
  • flutter build ios --simulator against a local posthog-ios 4.0 checkout (temporary .package(path:), reverted), and flutter build web.
  • Web (Chrome): reloadFeatureFlags awaits reloadFeatureFlagsAsync() when present and reports errorsLoading when posthog-js skips the request; the first test fails without that path.
  • Not yet built: Android, until posthog-android 4.0 exists locally.

📝 Checklist

  • All commits are signed (see Commit signing)
  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed.
  • No breaking change or entry added to the changelog.

If releasing new changes

  • Ran pnpm changeset to generate a changeset file

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Claude Code (Claude Opus 5.5) made this as part of the feature flag parity work across the iOS, Android and Flutter majors. The field names mirror posthog-ios's PostHogFeatureFlagsLoaded. For web reloadFeatureFlags(), waiting only for the next posthog-js onFeatureFlags call could return a response from a request already in flight, and never fires when posthog-js skips the request, so newer posthog-js uses reloadFeatureFlagsAsync() and older versions keep that path behind a timeout.

🤖 Generated with Claude Code

@turnipdabeets turnipdabeets self-assigned this Oct 23, 2026

@posthog posthog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PostHog Review · Standard · reviewed 93f0034: 1 Should fix.

This is the only automatic review while this pull request is a draft. Comment @posthog review to review new changes sooner. Otherwise, a review of the new changes runs when you mark it ready for review.

See this review and its findings in PostHog Review. Comment @posthog review --deep for a Deep review. A Deep review takes longer and looks deeper than a Standard review.

Comment thread posthog_flutter/lib/src/posthog_flutter_web_handler.dart Outdated
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

posthog-flutter Compliance Report

Date: 2026-10-27 22:18:27 UTC
Duration: 96884ms

✅ All Tests Passed!

45/45 tests passed


Capture Tests

✅ 29/29 tests passed

View Details
Test Status Duration
Format Validation.Event Has Required Fields ✅ 144ms
Format Validation.Event Has Uuid ✅ 119ms
Format Validation.Event Has Lib Properties ✅ 117ms
Format Validation.Distinct Id Is String ✅ 117ms
Format Validation.Token Is Present ✅ 116ms
Format Validation.Custom Properties Preserved ✅ 119ms
Format Validation.Event Has Timestamp ✅ 119ms
Retry Behavior.Retries On 503 ✅ 5332ms
Retry Behavior.Does Not Retry On 400 ✅ 2119ms
Retry Behavior.Does Not Retry On 401 ✅ 2118ms
Retry Behavior.Respects Retry After Header ✅ 8127ms
Retry Behavior.Implements Backoff ✅ 15446ms
Retry Behavior.Retries On 500 ✅ 5229ms
Retry Behavior.Retries On 502 ✅ 5229ms
Retry Behavior.Retries On 504 ✅ 5226ms
Retry Behavior.Max Retries Respected ✅ 15434ms
Deduplication.Generates Unique Uuids ✅ 126ms
Deduplication.Preserves Uuid On Retry ✅ 5225ms
Deduplication.Preserves Uuid And Timestamp On Retry ✅ 10337ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ✅ 5232ms
Deduplication.No Duplicate Events In Batch ✅ 125ms
Deduplication.Different Events Have Different Uuids ✅ 118ms
Compression.Sends Gzip When Enabled ✅ 118ms
Batch Format.Uses Proper Batch Structure ✅ 115ms
Batch Format.Flush With No Events Sends Nothing ✅ 109ms
Batch Format.Multiple Events Batched Together ✅ 125ms
Error Handling.Does Not Retry On 403 ✅ 2117ms
Error Handling.Does Not Retry On 413 ✅ 2118ms
Error Handling.Retries On 408 ✅ 5224ms

Feature_Flags Tests

✅ 16/16 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id ✅ 14ms
Request Payload.Flags Request Uses V2 Query Param ✅ 10ms
Request Payload.Flags Request Hits Flags Path Not Decide ✅ 10ms
Request Payload.Flags Request Omits Authorization Header ✅ 10ms
Request Payload.Token In Flags Body Matches Init ✅ 10ms
Request Payload.Groups Round Trip ✅ 11ms
Request Payload.Groups Default To Empty Object ✅ 10ms
Request Payload.Person Properties Distinct Id Auto Populated When Caller Omits It ✅ 10ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False ✅ 10ms
Request Payload.Disable Geoip Omitted Defaults To False ✅ 10ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key ✅ 10ms
Request Lifecycle.No Flags Request On Init Alone ✅ 5ms
Request Lifecycle.No Flags Request On Normal Capture ✅ 113ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests ✅ 17ms
Request Lifecycle.Mock Response Value Is Returned To Caller ✅ 10ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event ✅ 117ms

@turnipdabeets
turnipdabeets marked this pull request as ready for review October 23, 2026 17:11
@turnipdabeets
turnipdabeets requested a review from a team as a code owner October 23, 2026 17:11

@posthog posthog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PostHog Review · Standard · reviewed 80ac673: 1 Should fix.

Comment thread posthog_flutter/lib/src/posthog_flutter_web_handler.dart Outdated
onFeatureFlags and reloadFeatureFlags now carry a PostHogFeatureFlagsLoaded with the enabled flags, their values and whether loading failed, matching posthog-ios 4.0 and posthog-android 4.0. On web, reloadFeatureFlags completes right away with the flags loaded so far, because posthog-js doesn't report when a reload finishes.
Wait for the next posthog-js onFeatureFlags call instead of returning the flags already loaded, so a failed reload reports errorsLoading. Complete right away when flags are disabled, and after twice the flags request timeout when posthog-js skips the request without calling back.
The next onFeatureFlags callback can carry a response from a request already in flight, so reloadFeatureFlags() could complete with flags from before the reload. posthog-js 1.438.2+ settles reloadFeatureFlagsAsync() after this reload's own request; use it when present and keep the callback path for older posthog-js.
@turnipdabeets
turnipdabeets force-pushed the chore/v6-flags-loaded-result branch from de3a190 to 0a7ab2a Compare October 26, 2026 18:38

@dustinbyrne dustinbyrne left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The native/desktop result plumbing and major migration look consistent, but the legacy web fallback can report a successful retry as failed with default settings. Consider accounting for the full retry lifecycle before completing the fallback. Two optional documentation qualifications are inline. Native 4.0 dependency/build prerequisites remain separate.

AI-assisted review.

Comment thread posthog_flutter/lib/src/posthog_flutter_web_handler.dart
Comment thread posthog_flutter/lib/src/posthog_config.dart
Comment thread posthog_flutter/lib/src/feature_flags_loaded.dart
@dustinbyrne
dustinbyrne requested a review from a team October 27, 2026 17:00
… failure

posthog-js retries a timed-out /flags request once by default, 500 ms later, inside the same reload. The older-JS deadline of twice the request timeout reported cached flags with errorsLoading set before a successful retry landed.

@dustinbyrne dustinbyrne left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All three previous findings are addressed. The successful-retry reproduction now returns fresh flags without reporting a failure. One optional public-documentation update is inline. Native 4.0 dependency availability and successful native builds remain release prerequisites.

AI-assisted review.

Comment thread posthog_flutter/lib/src/posthog.dart Outdated
…budget

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@turnipdabeets
turnipdabeets merged commit 2939aa9 into chore/v6-adopt-posthog-android-4 Oct 28, 2026
21 of 26 checks passed
@turnipdabeets
turnipdabeets deleted the chore/v6-flags-loaded-result branch October 28, 2026 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants