Skip to content

chore!: pass the load result to the feature flags callback - #877

Merged
turnipdabeets merged 8 commits into
chore/v4-remove-deprecatedfrom
chore/v4-flags-loaded-result
Oct 28, 2026
Merged

turnipdabeets merged 8 commits into
chore/v4-remove-deprecatedfrom
chore/v4-flags-loaded-result

Conversation

@turnipdabeets

@turnipdabeets turnipdabeets commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Note

Stacked on the 4.0 integration PR #871. Merges into chore/v4-remove-deprecated, not main.

💡 Motivation and Context

Addresses #563: the callback now receives the loaded flags and whether loading failed.

Brings the Android flags callback to parity with posthog-ios 4.0 (PostHogFeatureFlagsLoaded) and Flutter 6.

PostHogConfig.onFeatureFlags and reloadFeatureFlags() now take a new PostHogFeatureFlagsCallback. Its loaded() receives a PostHogFeatureFlagsLoaded with:

  • flags: the keys of the enabled flags
  • variants: their values (true or the variant string)
  • errorsLoading: whether the latest load failed (the values are then the last known ones)

Every path that invoked the old callback now passes an accurate result, including failed requests, a disabled SDK, and bootstrap.

config.onFeatureFlags = PostHogFeatureFlagsCallback { loaded ->
    if (!loaded.errorsLoading && loaded.variants["new-checkout"] == "test") {
        // ...
    }
}

Why a new type instead of changing PostHogOnFeatureFlags: core's public types are also part of posthog-server's API. Changing PostHogOnFeatureFlags.loaded() would force a server major for a callback the server can only fill with empty data (it evaluates flags per call). So:

  • PostHogOnFeatureFlags moves from core into posthog-server, same package and shape, so server users' source and binaries keep working. Android no longer sees it.
  • The server already calls its own callback directly, so it no longer passes one to the core config (core's stateless client never called it).
  • posthog-server gets a minor bump, since it now depends on core 7.0.
  • The server can drop or replace it in its own major.

The other core types the server exposes (FeatureFlagResult, PostHogBeforeSend, PostHogEncryption, PostHogIntegration) are unchanged.

For reviewers: a blank distinctId reports errorsLoading = true, since no request is made.

💚 How did you test it?

  • ./gradlew spotlessCheck apiCheck :posthog:test :posthog-server:test :posthog-android:testDebugUnitTest pass, and the Android sample compiles.
  • PostHogRemoteConfigTest and PostHogBootstrapTest assert the result passed on success, failure, and bootstrap.
  • The server's tests are unchanged apart from asCoreConfig no longer setting the core callback.
  • posthog-server.api only gains PostHogOnFeatureFlags (moved in, unchanged).

📝 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) implemented the change after a cross-SDK flags API review (iOS, Android, Flutter, React Native). A first version changed PostHogOnFeatureFlags in place and bumped the server to a major; it was reworked to move the old type into posthog-server so the server stays untouched until its own major.

🤖 Generated with Claude Code

@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 90beca5: 2 Should fix.

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/src/main/java/com/posthog/internal/PostHogRemoteConfig.kt Outdated
Comment thread posthog/src/main/java/com/posthog/PostHog.kt Outdated
@turnipdabeets
turnipdabeets force-pushed the chore/v4-remove-deprecated branch from 2f486a0 to a41d9b9 Compare October 26, 2026 16:29
@turnipdabeets
turnipdabeets force-pushed the chore/v4-flags-loaded-result branch from 6d389ab to 4469ad4 Compare October 26, 2026 16:29
@turnipdabeets
turnipdabeets force-pushed the chore/v4-remove-deprecated branch from a41d9b9 to caf64bd Compare October 26, 2026 18:47
@turnipdabeets
turnipdabeets force-pushed the chore/v4-flags-loaded-result branch 2 times, most recently from e9eb0db to 46fca5a Compare October 27, 2026 15:48

@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 46fca5a: 1 Should fix.

Comment thread posthog/src/main/java/com/posthog/internal/PostHogRemoteConfig.kt
turnipdabeets and others added 5 commits October 27, 2026 12:59
PostHogConfig.onFeatureFlags and reloadFeatureFlags() now take a PostHogFeatureFlagsCallback, whose loaded() receives a PostHogFeatureFlagsLoaded with the enabled flags, their values, and errorsLoading, matching posthog-ios 4.0. Every path that invoked the callback passes an accurate result, including failures, a disabled SDK, and bootstrap.

PostHogOnFeatureFlags moves to posthog-server under the same name, so the server's API is unchanged and it can drop the type in its own major.
posthog-server calls its own PostHogOnFeatureFlags directly, and the core stateless client never calls config.onFeatureFlags. Bump posthog-server to minor since it now depends on core 7.0, and document that a bootstrapped onFeatureFlags runs on the setup() thread.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@turnipdabeets
turnipdabeets force-pushed the chore/v4-flags-loaded-result branch from 3f4acd8 to 5dcba77 Compare October 27, 2026 17:20

@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.

AI-assisted review. The readable-cache and bootstrap fixes are verified. One Direct Boot cache-availability regression remains; details and executed base/head evidence are inline.

Comment thread posthog/src/main/java/com/posthog/internal/PostHogRemoteConfig.kt
@dustinbyrne
dustinbyrne requested a review from a team October 27, 2026 21:31
A failed load now hydrates the flag cache before the callback. Under Direct
Boot that read returned empty values and latched, so persisted flags stayed
hidden after unlock. Only latch once the preferences are readable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@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 8aaa5a4: 1 Must fix, 1 Should fix.

This is review round 3 on this pull request. When findings keep coming back in the same code, the approach is usually the problem. Before the next fix, check whether a different design would remove the whole class of findings.

Comment thread posthog/src/main/java/com/posthog/internal/PostHogRemoteConfig.kt
Comment thread posthog/src/main/java/com/posthog/internal/PostHogRemoteConfig.kt Outdated
turnipdabeets and others added 2 commits October 28, 2026 10:59
Every flag getter retried hydration under Direct Boot and re-read each cached
key, each read failing against locked preferences. Check availability once and
skip the reads until storage is readable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hydration reads the cache off the flags lock, so a reset() landing between the
read and the commit had the previous identity's flags restored. clear() now
bumps a generation and hydration drops a commit from an older one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@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.

AI-assisted review. Verified reset invalidation, Direct Boot recovery, and retained cached values on failed loads. No remaining findings in the reviewed changes.

@turnipdabeets
turnipdabeets merged commit b2361cd into chore/v4-remove-deprecated Oct 28, 2026
11 checks passed
@turnipdabeets
turnipdabeets deleted the chore/v4-flags-loaded-result branch October 28, 2026 20:38
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