fix: reset flag-called tracking when definitions reload - #267
Conversation
|
maybe a better approach would be to check the results and the cached flags and only clear the values that have changed, wdyt? or is it ok to emit again? i recall those events being "expensive" but later this was improved during ingestion |
posthog-ruby Compliance ReportDate: 2026-09-07 19:49:17 UTC ✅ All Tests Passed!46/46 tests passed Capture Tests✅ 29/29 tests passed View Details
Feature_Flags Tests✅ 17/17 tests passed View Details
|
Prompt To Fix All With AI### Issue 1
lib/posthog/feature_flags.rb:1288
**Refresh Can Duplicate Events**
During a background refresh, the new definitions become visible before this callback clears the deduplication tracker. A concurrent evaluation can use those new definitions and record its `$feature_flag_called` event, but the callback then erases that record. A later read emits the event again even though no additional reload occurred. The tracker reset must be ordered with definition publication, such as by associating entries with a definition generation.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "fix: reset flag-called tracking when def..." | Re-trigger Greptile |
we're already doing this. ingestion does deduplicate these as well. |
dustinbyrne
left a comment
There was a problem hiding this comment.
The existing dedupe key already includes distinct ID, flag key, response and normalized groups. Resetting the tracker when definitions are applied matches its lifecycle contract; 304 and failed refreshes preserve tracking.
💡 Motivation and Context
Related to #189.
After local flag definitions reload, the client still remembers earlier
$feature_flag_calledevents and suppresses the next access. Clear the existing tracker when definitions are applied or when a quota response discards loaded definitions. Manual reloads, background polling, and external-cache refreshes use the same callback.Definition publication and tracker reset now share the existing deduplication mutex, closing the race where a refresh erased an event recorded against newly published definitions. Network requests, cache-provider callbacks, and logging stay outside that lock. Repeated reads between reloads remain deduplicated. HTTP 304 responses, failed requests, and responses without definitions leave tracking unchanged. Evaluations already in flight may still complete using definitions they read before a refresh.
💚 How did you test it?
bundle exec rspec: 696 examples, 0 failures. The 19-example reload suite also passed ten seeded runs (190 examples).bundle exec rubocop(85 files),bundle exec rake public_api:check, and the core gem build. All passed. The gem build retains its existing missing-author warning.4f4b1de269fc651c7a79a1ba0f09d4ed0c90bf96. Local autoreview of the concurrency follow-up, published asd0b0315e801c64c409e38c3555619950e8f6eb74, also passed with no actionable findings.Validation used Ruby 4.0.6 and Bundler 4.0.13 with frozen dependencies. The CI Ruby 3.2/3.3/3.4 matrix was not run locally. Tests use WebMock rather than a live PostHog service.
📝 Checklist
If releasing new changes
pnpm changesetto generate a changeset fileThe changeset selects patch releases for both
posthog-rubyandposthog-rails. Rails delegates feature-flag access to the core client and pins the exact core SDK version, so it needs a release to receive this fix. The changeset was edited directly; the generator was not run.🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Pi agents implemented and independently reviewed this user-directed fix. Tools used were Git, Bundler/RSpec, RuboCop, Rake, RubyGems, GitHub CLI, and the isolated Pi autoreview helper. Session references: implementation
3efed453-bba9-4ebc-853b-b7247693a8d8, publication510ebebc-a750-45a5-88ce-92821ccd3256(local sessions, no public link).The fix keeps the existing bounded tracker and mutex rather than adding generation tracking or changing the public client API. Human review is required before merging.