Skip to content

Conversation

@toddbaert
Copy link
Member

@toddbaert toddbaert commented Oct 29, 2025

Replay of #444 (these contributions are not mine, but @erka 's)

This PR

  • Add WithProvider option for registering named providers with optional hooks
  • Remove ProviderMap type in favor of variadic functional options
  • Change NamedProvider from struct to interface
  • Update NewProvider signature to take strategy first, then options
  • Add Track method support to MultiProvider for tracking events
  • Update tests, documentation and examples to reflect new API

erka added 5 commits October 27, 2025 18:15
Changes:
- Add WithProvider option for registering named providers with optional hooks
- Remove ProviderMap type in favor of variadic functional options
- Change NamedProvider from struct to interface
- Update NewProvider signature to take strategy first, then options
- Add Track method support to MultiProvider for tracking events
- Update tests, documentation and examples to reflect new API

Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
- remove inboundEvents channel in favor of direct pipe channel
- fix race condition in updateProviderStateFromEvent with lock
- optimize Shutdown to only spawn goroutines for StateHandler providers
- ensure outboundEvents channel is closed after all workers complete

Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
@toddbaert toddbaert requested review from a team as code owners October 29, 2025 18:37
@toddbaert toddbaert requested a review from erka October 29, 2025 18:37
@toddbaert toddbaert changed the title Feat/multi provider track feat(multi): add tracking, functional options Oct 29, 2025
@gemini-code-assist
Copy link

Summary of Changes

Hello @toddbaert, 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 introduces substantial improvements to the multi.Provider component within the OpenFeature Go SDK. The primary goal is to enhance the flexibility and functionality of managing multiple feature flag providers. This is achieved through a refactored initialization process using an options pattern, the formalization of named providers via a new interface, and the addition of a Track method to propagate tracking events. Furthermore, the internal event handling and shutdown procedures have been made more robust to ensure reliable operation.

Highlights

  • Refactored Multi-Provider Initialization: The multi.NewProvider function now uses an options pattern with WithProvider to register feature providers, replacing the previous ProviderMap argument. This allows for more flexible configuration, including the ability to attach specific hooks to individual providers during registration.
  • Introduced NamedProvider Interface: A new NamedProvider interface has been defined, which extends of.FeatureProvider by adding a Name() method and an unwrap() method. This formalizes the concept of named providers within the multi-provider architecture and improves type safety.
  • Implemented Track Method for Multi-Provider: The multi.Provider now implements the of.Tracker interface, enabling it to forward tracking events to all its internal feature providers that are in a ReadyState and also implement of.Tracker.
  • Enhanced Event Handling and Shutdown Logic: The internal event forwarding mechanism has been significantly refactored for improved robustness and concurrency. This includes a new forwardProviderEvents pipeline that aggregates events from multiple providers and a more streamlined shutdown process.
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.

@toddbaert
Copy link
Member Author

@erka I'm so sorry, I was reviewing and accidentally pushed your branch with no changes. When that happen GH closes the PR automatically :(

I added all your commits back, but I can't put them back on your branch.

Copy link

@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 introduces a significant and beneficial refactoring of the multi-provider. The API is improved by introducing functional options for provider configuration, which is more idiomatic in Go. The internal implementation is also more robust, with fixes for potential race conditions and better event handling logic. Additionally, it adds support for the Tracker interface. My review includes a few suggestions to improve logging clarity in the shutdown process, fix a potentially flaky test, and correct a syntax error in the README documentation. Overall, this is a great improvement to the package.

@codecov
Copy link

codecov bot commented Oct 29, 2025

Codecov Report

❌ Patch coverage is 87.50000% with 25 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.15%. Comparing base (1a0d39e) to head (31dad0d).

Files with missing lines Patch % Lines
openfeature/multi/multiprovider.go 86.41% 14 Missing and 8 partials ⚠️
openfeature/multi/isolation.go 57.14% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #446      +/-   ##
==========================================
- Coverage   83.23%   83.15%   -0.09%     
==========================================
  Files          27       27              
  Lines        2034     2101      +67     
==========================================
+ Hits         1693     1747      +54     
- Misses        299      305       +6     
- Partials       42       49       +7     
Flag Coverage Δ
e2e 83.15% <87.50%> (-0.09%) ⬇️
unit 83.15% <87.50%> (-0.09%) ⬇️

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.

erka added 3 commits October 30, 2025 12:30
Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
@erka
Copy link
Contributor

erka commented Oct 31, 2025

/gemini review

Copy link

@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 introduces significant and valuable improvements to the multi-provider implementation. The transition to functional options for provider registration (WithProvider) and the change of NamedProvider from a struct to an interface make the API more flexible and idiomatic. The addition of the Track method and context-aware Init and Shutdown functions are also great enhancements. The code is well-structured, and the updates to tests and documentation are thorough.

I have found one critical race condition in the new ShutdownWithContext function that needs to be addressed. I've also noted a minor inconsistency in context usage for logging. Apart from these points, the changes are excellent.

erka and others added 3 commits October 31, 2025 16:43
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
@erka
Copy link
Contributor

erka commented Oct 31, 2025

/gemini review

Copy link

@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 is an excellent pull request that significantly refactors the multi-provider API to be more idiomatic and robust. The move to functional options with WithProvider is a great improvement over the previous ProviderMap approach, making the API cleaner and preserving provider order. The introduction of Track support, along with context-aware initialization and shutdown, adds valuable functionality and improves the provider's lifecycle management. The code quality is high, and the test coverage is thorough, including the new features. I have one suggestion regarding context propagation in logging functions to enhance traceability, but overall, this is a very strong contribution.

Comment on lines +480 to +481
slog.String(MetadataProviderName, e.providerName),
slog.String(MetadataProviderType, e.ProviderName),
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these log attrs supposed to have the same values? As in, should MetadataProviderType have value e.ProviderName?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think there’s a naming issue here - I’ve struggled with it too. providerName is a user-defined name in the WithProvider option in namedEvent, while ProviderName is the defined name in of.Event.

erka and others added 4 commits November 1, 2025 10:58
Co-authored-by: Sahid Velji <sahidvelji@gmail.com>
Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
Co-authored-by: Sahid Velji <sahidvelji@gmail.com>
Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
Co-authored-by: Sahid Velji <sahidvelji@gmail.com>
Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
// Name returns the unique name assigned to the provider.
Name() string
// unwrap returns the underlying [of.FeatureProvider] instance.
unwrap() of.FeatureProvider
Copy link
Contributor

Choose a reason for hiding this comment

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

If this interface is exported, then unwrap should also be exported

Copy link
Contributor

Choose a reason for hiding this comment

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

I don’t want to export it. I’ve reworked it, but it might look a bit messy. wdyt?

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess my question is: would it make more sense to unexport the NamedProvider interface and export instead the namedProvider struct, so that the interface is used internally, while the struct is exposed? What we've got now is also fine, but I prefer to minimize exporting interfaces.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don’t have a strong opinion on this. Let’s see what the other members think.

Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
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.

4 participants