Skip to content

fix: Do not emit duplicate provider events - #37

Draft
kinyoklion wants to merge 1 commit into
devin/1788360613-ruby-zero-start-waitfrom
devin/1788360667-ruby-event-dedup
Draft

fix: Do not emit duplicate provider events#37
kinyoklion wants to merge 1 commit into
devin/1788360613-ruby-zero-start-waitfrom
devin/1788360667-ruby-event-dedup

Conversation

@kinyoklion

Copy link
Copy Markdown
Member

Provider events are no longer emitted for a status the application has already been told about.

  • The provider subscribed to data source status in its constructor, so the transition which completed initialization was emitted as a PROVIDER_READY event on top of the one the OpenFeature SDK emits for initialization itself. Subscription now happens after initialization succeeds.
  • Several data source states map to the same provider status, so a new error while already interrupted produced a second PROVIDER_STALE. An event is now emitted only when the provider status actually changes.
  • shutdown unsubscribes the listeners it added.

Based on #36, which also changes init; review that one first.

Found during the weekly OpenFeature provider audit.

Implementation details

Requirements

  • I have added test coverage for new or changed functionality
  • I have followed the repository's pull request submission guidelines
  • I have validated my changes against all supported platform versions

Related issues

None.

Describe the solution you've provided

The provider builds its status and flag change listeners in the constructor but registers them at the end of a successful init, and removes them in shutdown. A failed initialization does not register them, since the OpenFeature SDK reports that outcome itself.

DataSourceStatusListener remembers the last event it emitted, guarded by a mutex because the LaunchDarkly SDK notifies listeners from its own thread, and skips an event which repeats it. A status which changes and later returns still emits again.

This matches the provider event requirements of the OpenFeature provider behavior spec, and the behavior of the Python provider, which registers its emitting listener after initialization for the same reason.

Describe alternatives you've considered

Comparing the whole data source status rather than the mapped provider status: the OpenFeature event carries the provider status, so two states which map to the same status are not a change an application can act on.

Keeping the constructor subscription and filtering the first READY only: that would still emit duplicates for repeated states, and the ordering between the provider's event and the SDK's own initialization event would remain unspecified.

Additional context

Testing: bundle exec rspec (84 examples) and bundle exec rubocop on Ruby 3.4.5. The new tests cover no subscription before init, subscription after a successful init, no subscription after a failed init, a repeated status emitting once, and a status which changes back emitting again.

The README's Eventing row describes when events are emitted.

Link to Devin session: https://app.devin.ai/sessions/fe1eb757fe694ef79f3d09f6307d4b47
Open in Devin Desktop: https://app.devin.ai/desktop/session/fe1eb757fe694ef79f3d09f6307d4b47?variant=devin
Requested by: @kinyoklion

@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot added the devin-pr PRs created by Devin label Sep 2, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

@cursor review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

devin-pr PRs created by Devin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant