Skip to content

fix: merge SetProviderAndWait fixes into next#475

Open
dd-oleksii wants to merge 5 commits intoopen-feature:nextfrom
dd-oleksii:oleksii/jj-kpprsnmruuwn
Open

fix: merge SetProviderAndWait fixes into next#475
dd-oleksii wants to merge 5 commits intoopen-feature:nextfrom
dd-oleksii:oleksii/jj-kpprsnmruuwn

Conversation

@dd-oleksii
Copy link

This PR

Merge of #474 along with latest changes from main into next. cc @erka

Related Issues

#474
#460

Notes

Follow-up Tasks

How to test

gabegorelick and others added 3 commits January 31, 2026 20:23
Signed-off-by: Gabe Gorelick <gabe@hightouch.io>
…#469)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: Gabe Gorelick <gabe@hightouch.io>
@dd-oleksii dd-oleksii requested review from a team as code owners February 16, 2026 22:22
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @dd-oleksii, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request integrates critical fixes and improvements related to provider registration and lifecycle management, specifically addressing the SetProviderAndWait functionality. The changes streamline the process of setting and initializing feature providers, enhance error handling, and improve the robustness of event handling during provider shutdowns. This ensures a more predictable and stable experience when managing feature flag providers within the SDK.

Highlights

  • Provider Lifecycle Management Refinement: Refactored the internal mechanisms for setting and managing feature providers, separating initialization and shutdown logic into distinct helper functions (initNew and shutdownOld). This improves clarity and maintainability of provider lifecycle management.
  • Enhanced SetProviderAndWait Functionality: The SetProviderAndWait and SetNamedProviderAndWait functions now correctly wait for provider initialization to complete by utilizing a channel, ensuring synchronous behavior as intended. Error handling for nil providers has also been added.
  • Improved Event Executor Robustness: Internal provider registration functions in event_executor.go no longer return errors, simplifying their call sites. The shutdown semaphore for event handlers was changed to a buffered channel, preventing potential deadlocks during provider shutdown and logging a warning instead of returning an error on timeout.
  • Dependency Updates: Updated golang.org/x/sync and golang.org/x/text modules to their latest versions, ensuring the project benefits from the most recent bug fixes and performance improvements.
  • Test Reliability Improvements: Adjusted event emission timing in event_executor_test.go to ensure events are invoked after handlers are registered, leading to more reliable and accurate test results.
Changelog
  • event_executor.go
    • Removed unused imports for fmt and time.
    • Modified registerDefaultProvider, registerNamedEventingProvider, and startListeningAndShutdownOld functions to no longer return errors.
    • Updated startListeningAndShutdownOld to use a non-blocking send to the shutdown semaphore and log a warning instead of returning an error on timeout.
  • event_executor_test.go
    • Removed error checks from calls to registerDefaultProvider and registerNamedEventingProvider.
    • Relocated eventingImpl.Invoke calls in TestEventHandler_HandlersRunImmediately to occur after event handler registration, ensuring proper test execution.
  • go.mod
    • Updated golang.org/x/sync dependency from v0.18.0 to v0.19.0.
    • Updated golang.org/x/text dependency from v0.31.0 to v0.33.0.
  • go.sum
    • Updated checksums for golang.org/x/sync and golang.org/x/text modules to reflect new versions.
  • openfeature_api.go
    • Refactored SetProvider and SetProviderAndWait to use a new setProviderWithContext helper function.
    • Introduced initNew and shutdownOld helper functions to encapsulate provider initialization and shutdown logic.
    • Added nil provider checks to SetProvider and SetNamedProvider functions.
    • Modified SetProviderAndWait and SetNamedProviderAndWait to explicitly wait for provider initialization completion via a channel.
    • Removed the async parameter from internal setProviderWithContext and setNamedProviderWithContext functions.
    • Reordered GetProviderMetadata and GetNamedProviderMetadata methods within the file.
  • reference.go
    • Changed the shutdownSemaphore channel in newProviderRef to be buffered with a capacity of 1.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the provider setting logic, particularly around SetProviderAndWait. The changes introduce a clearer separation of concerns for provider initialization and shutdown, using channels to manage asynchronous operations. This improves the robustness of setting providers. My review found a minor inconsistency in error handling for SetProviderAndWait compared to SetNamedProviderAndWait, for which I've suggested a fix to improve consistency and error reporting.

OpenFeature specification defines SetProviderAndWait as a waiting
version of SetProvider, or as a shortcut for waiting on provider ready
event. However, currently SetProvider and SetProviderAndWait exhibit
non-trivial behavior differences besides waiting.

SetProvider runs initialization asynchronously and potentially
concurrently with shutdown of the old provider. The API is not blocked
and the application author may initialize other providers
concurrently, run evaluations, etc.

🐛: in this mode, the error from initializer is ignored when updating
the provider state, so fatal/error states may be not set properly.

SetProviderAndWait runs initialization synchronously while holding
exclusive api.mu lock. This almost completely locks OpenFeature SDK:
the application author cannot initialize other providers (for
different domains), configure context or hooks, evaluate feature
flags, or shutdown SDK. If a provider initialization blocks
forever'ish, the SDK remains unusable and is unrecoverable.

Another difference is that old provider is shutdown only after new
provider has successfully initialized.

🐛: if the new provider fails to initialize, the old provider is
already unset in API but will never be shutdown, and the new provider
is not registered with api.eventExecutor (so if it comes back online
after some time, nobody listens to its events, and the state will go
out of sync if old provider continues emitting events).

🐛: in both modes, given that shutdown is run concurrently with
updating subscriptions in eventExecutor, it is possible for the old
provider to override the state of the new provider:
1. init finishes, emits provider ready event (directly from
   goroutine), updates state
2. old provider emits some event during shutdown (e.g., PROVIDER_ERROR
   or PROVIDER_STALE), eventExecutor receives the event and updates
   the state to error/stale
3. new provider is registered with eventExecutor but the state is
   already wrong.

This PR introduces a couple of changes:

Make initialization flow consistent across both modes: always
initialize async but make "AndWait" methods wait for initialization
outside of critical section. Make init respect returned error.

Always call shutdown on old provider (if it is no longer used).

Always register new provider with event executor. Do this before we
start init/shutdown, so the old provider cannot influence state of the
new provider. Make event executor registration non-erroring by making
shutdown channel buffered (there were no good way to recover from
registration error).

Signed-off-by: Oleksii Shmalko <oleksii.shmalko@datadoghq.com>
@dd-oleksii dd-oleksii force-pushed the oleksii/jj-kpprsnmruuwn branch 2 times, most recently from 87af314 to 5a69fbb Compare February 17, 2026 12:31
Signed-off-by: Oleksii Shmalko <oleksii.shmalko@datadoghq.com>
@dd-oleksii dd-oleksii force-pushed the oleksii/jj-kpprsnmruuwn branch from 5a69fbb to bf2f8f9 Compare February 17, 2026 12:33
@beeme1mr beeme1mr requested a review from erka February 17, 2026 15:19
@codecov
Copy link

codecov bot commented Feb 17, 2026

Codecov Report

❌ Patch coverage is 84.74576% with 9 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (next@05198d3). Learn more about missing BASE report.

Files with missing lines Patch % Lines
openfeature_api.go 87.23% 3 Missing and 3 partials ⚠️
event_executor.go 72.72% 3 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             next     #475   +/-   ##
=======================================
  Coverage        ?   86.15%           
=======================================
  Files           ?       21           
  Lines           ?     1936           
  Branches        ?        0           
=======================================
  Hits            ?     1668           
  Misses          ?      231           
  Partials        ?       37           
Flag Coverage Δ
e2e 86.15% <84.74%> (?)
unit 86.15% <84.74%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Member

@erka erka left a comment

Choose a reason for hiding this comment

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

Thank you @dd-oleksii but maybe it makes sense to focus on the original PR and the main branch for now. An extra PR might not add much value in fixing the issue and could increase the scope, especially with potential merge conflicts from other changes anyway.

@erka erka added the v2 label Feb 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants