Skip to content

Conversation

@alxckn
Copy link
Member

@alxckn alxckn commented Jan 8, 2026

This PR

This pull request refactors the initialization logic in the MultiProvider class to ensure proper resource management for the thread pool used during provider initialization. The main change is moving the creation and shutdown of the ExecutorService into a try-finally block, which guarantees that the thread pool is always shut down, even if an exception occurs.

We observed issues with some of our apps that fail to shutdown properly because of a hanging non-daemon thread, the changes proposed in this PR fix the issue (tested on our previously failing app).

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @alxckn, 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 enhances the robustness of the MultiProvider's initialization process by implementing a guaranteed shutdown mechanism for its internal thread pool. By enclosing the thread pool's lifecycle within a try-finally block, it prevents resource leaks and addresses a critical issue where applications would fail to terminate cleanly due to persistent non-daemon threads.

Highlights

  • Resource Management: The initialization logic within the MultiProvider class has been refactored to ensure proper resource management for the thread pool used during provider initialization.
  • Thread Pool Shutdown: The ExecutorService is now created and shut down within a try-finally block, guaranteeing its termination even if exceptions occur during the initialization process.
  • Application Stability: This change addresses issues where applications failed to shut down correctly due to hanging non-daemon threads, thereby improving overall application stability and shutdown behavior.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

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.

@alxckn alxckn changed the title Properly shutdown multiprovider initialization thread pool fix(multiprovider): Properly shutdown multiprovider initialization thread pool Jan 8, 2026
@alxckn alxckn force-pushed the fix_unclosed_thread_pool_multiprovider branch from 0524360 to fa592fd Compare January 8, 2026 13:29
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 correctly refactors the provider initialization logic to prevent resource leaks from the thread pool by using a try-finally block. This ensures the ExecutorService is always shut down, even in the case of an exception. The change is a solid improvement for application stability. I have one suggestion to improve the error handling logic within the new try block.

alxckn added 3 commits January 8, 2026 15:19
Signed-off-by: Alexandre Chakroun <[email protected]>
Signed-off-by: Alexandre Chakroun <[email protected]>
@alxckn alxckn force-pushed the fix_unclosed_thread_pool_multiprovider branch from 5ecda1f to 98aee38 Compare January 8, 2026 14:19
@alxckn alxckn marked this pull request as ready for review January 8, 2026 14:26
@alxckn alxckn requested a review from a team as a code owner January 8, 2026 14:27
for (FeatureProvider provider : providers.values()) {
tasks.add(() -> {
provider.initialize(evaluationContext);
return true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we always return true and never use this value, could we get rid of this value entirely? Maybe with a Future<Void>?

// Wait for all provider initializations to complete.
// If any provider.initialize() throws, result.get() will throw ExecutionException.
for (Future<Boolean> result : results) {
result.get();
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we should check for result.isCancelled(), and also add a sensible timeout result.get(timeout, TimeUnit.MILLISECONDS);.

@liran2000
Copy link
Member

This was moved, treated and depecated, so can be closed?

handled

@chrfwow chrfwow requested a review from a team January 8, 2026 15:22
@chrfwow
Copy link
Contributor

chrfwow commented Jan 9, 2026

@alxckn The multi provider was moved to the java-sdk repository: https://github.com/open-feature/java-sdk/tree/main/src/main/java/dev/openfeature/sdk/multiprovider
Please migrate to this version. As pointed out by @liran2000, the issues you worked on were fixed there

@alxckn
Copy link
Member Author

alxckn commented Jan 9, 2026

@chrfwow @liran2000 thanks for reviewing sorry I hadn't noticed the migration, and happy to see it's been internalized and already fixed :) We'll migrate to fix our issue

@alxckn alxckn closed this Jan 9, 2026
@toddbaert
Copy link
Member

@alxckn it's migrated but not released! We have a few new things / fixes in Java though, so I'll try to get a release out soon (if not today): open-feature/java-sdk#1770

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