Reputation: 139
I am working on project where context and session are managed by ThreadLocal safely with ThreadPoolExecutor ( information is passed from Thread to another inside ThreadPoolExecutor).
We have:
It works fine and tested in high level production project.
Quarkus context propagation works fine. But migrating the current (production) project to quarkus seem to be hard and risky.
So, how, for example, @Provide a CustomThreadPool, and quarkus can use it as principal ThreadPool instead of default one.
Upvotes: 0
Views: 4461
Reputation: 21
Quarkus version: 1.9.1.Final
Java: 11
Well, you could tune Quarkus main service executor by configuration properties. Have a look all quarkus.thread-pool.*
properties and then use it as a regular service executor.
In order to inject this thread pool into your service, be sure that you support context propagation by adding the following extension ./mvnw quarkus:add-extension -Dextensions="quarkus-smallrye-context-propagation"
as you can see in this link
Inject the main service executor into your service is as simple as:
@Inject ManagedExecutor exec;
Create a separate service executor it's another approach (however you should ask yourself, What I get with a separate executor?, What I am looking for?), maybe make sense, I guess that depends on the case. In 'this case', you could create your own ManagedExcutor and use it, for example:
import io.quarkus.runtime.Startup;
import org.eclipse.microprofile.context.ManagedExecutor;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;
import javax.ws.rs.Produces;
public class Producers {
private final static int POOL_SIZE = 4; // TODO move on this hardcode properties to a config file
private final static int POOL_QUEUE_SIZE = 10;
@Startup // Instanciated at start-time
@ApplicationScoped // Only one instance for all your app (Singleton)
@Produces
@Named("customServiceExecutor") // tag your instance, because remember that you will have also another ServiceExecutor (the default one)
ManagedExecutor managedCustomExecutor() {
System.out.println("customServiceExecutor created (once)!.");
return ManagedExecutor.builder()
.maxAsync(POOL_SIZE)
.maxQueued(POOL_QUEUE_SIZE)
.build();
}
}
And then let's use it!:
import io.smallrye.context.api.NamedInstance;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.context.ManagedExecutor;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/hello/")
public class HelloResource {
@ConfigProperty(name = "org.pjgg.greeting")
private String greeting;
@Inject
@NamedInstance("customServiceExecutor")
ManagedExecutor delorean;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
System.out.println(java.lang.Thread.activeCount());
var promise = delorean.supplyAsync(()-> "You will see this in the future !!!");
promise.thenAccept(System.out::println);
System.out.println(java.lang.Thread.activeCount());
return greeting;
}
}
Upvotes: 1