Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async APIs #269

Open
bsideup opened this issue Jan 2, 2019 · 11 comments
Open

Async APIs #269

bsideup opened this issue Jan 2, 2019 · 11 comments

Comments

@bsideup
Copy link

bsideup commented Jan 2, 2019

Hi!

Would you consider supporting Async APIs?

There are some IO blocking operations (e.g. loading of plugins, or even plugin's startup), and currently, in my async non-blocking app, I have to run them in a special thread pool (although the implementations of the plugin repository and plugins themselves are async)

CompletionStage<Void> could be used in place of potentially-IO methods with void type, and CompletionStage<T> where it returns something.

Consider this issue as a feature request & design discussion for now :)

@decebals
Copy link
Member

decebals commented Jan 2, 2019

Thanks for idea!

Another interesting idea is to load plugins in parallel (if a plugin is not a dependency for another plugin we can load them in parallel) to decrease the startup time of application. But I consider these kind of features somehow enterprise.

I am curios to see how we can implement this feature in a clean and non intrusive way. Any draft, snippet code, idea that will move forward this feature or a concrete PR is welcome.

@decebals
Copy link
Member

decebals commented Jan 2, 2019

And to not forget, to use CompetionStage we need to migrate PF4J from Java 7 to Java 8. I think that this migration will not be a problem because Java 8 is already old.

@bsideup
Copy link
Author

bsideup commented Jan 2, 2019

@decebals I'll sketch something. The bigger challenge is how to keep it backward compatible. Otherwise, it has to be targeted for 3.x, I guess

@decebals
Copy link
Member

decebals commented Jan 2, 2019

@bsideup

The bigger challenge is how to keep it backward compatible. Otherwise, it has to be targeted for 3.x, I guess

3.x is perfect. For 3.x we will increase the minimal Java version to 8.

@decebals
Copy link
Member

decebals commented Jan 2, 2019

I am thinking if it's not possible to add new default async methods in PluginManager for example, methods that transform the existed sync peer methods in async methods using a decorator (as pattern).
If async methods are declared as default methods we don't break the existent API.

@decebals decebals mentioned this issue Feb 26, 2019
3 tasks
@decebals decebals added this to the PF4J 3 milestone Mar 26, 2019
@decebals
Copy link
Member

@bsideup
We started work on PF4J 3. The modifications are available on pf4j_3 branch.
With your help, this issue can be available in PF4J 3. It is already added for this milestone.

@decebals
Copy link
Member

This feature will be removed from PF4J 3 milestone, because the interest for this feature is low.
It can delay the release of PF4J 3 that is almost ready.

@decebals decebals removed this from the PF4J 3 milestone Apr 15, 2019
@decebals
Copy link
Member

I added a POC (Proof Of Concept) on the async branch.
I updated demo (Boot class) to use the new Async API. Everything is functional.
I am not an expert of async/reactive/... so I don't contest that are not mistakes or that it cannot be improved it :)
Any advice, PR is very welcome.

@decebals
Copy link
Member

decebals commented Apr 19, 2019

I added below two code snippets (from demo/Boot.java) that show you the API used to load&start plugins using SYNC and ASYNC variant.
In the new async API I added two new methods (until now) that end with Async:

  • loadPluginsAsync
  • startPluginsAsync

Load and start plugins sync

// create the plugin manager
final PluginManager pluginManager = new DefaultPluginManager();

// load the plugins
pluginManager.loadPlugins();

// start (active/resolved) the plugins
pluginManager.startPlugins();

// retrieves the extensions for Greeting extension point
List<Greeting> greetings = pluginManager.getExtensions(Greeting.class);

Load and start plugins async

// create the plugin manager
final AsyncPluginManager pluginManager = new DefaultAsyncPluginManager();

// load the plugins
CompletionStage<Void> stage = pluginManager.loadPluginsAsync();
stage.thenRun(() -> System.out.println("Plugins loaded")); // optional

// start (active/resolved) the plugins
stage.thenCompose(v -> pluginManager.startPluginsAsync());
stage.thenRun(() -> System.out.println("Plugins started")); // optional

// block and wait for the future to complete (not the best approach in real applications)
stage.toCompletableFuture().get();

// retrieves the extensions for Greeting extension point
List<Greeting> greetings = pluginManager.getExtensions(Greeting.class);

I am not sure yet if the variant with new AsyncPluginManager interface and DefaultAsyncPluginManager class is the best design option. I don't know if the variant with add the new async methods directly in PluginManager is not better.

@decebals
Copy link
Member

decebals commented Apr 24, 2019

To the solution proposed by me can be added support for timeout via CompletableFeature.orTimeout (Java 9+) or a similar method using ScheduledThreadPoolExecutor (Java 8).

@decebals
Copy link
Member

In the end, what you say about the POC (Proof Of Concept) on the async branch? Is it valuable to be included in the PF4J roadmap?
Do you think that something (feature, ...) is missing in POC?

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

No branches or pull requests

2 participants