Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Right way to start a worker thread with Quarkus?

Tags:

I am implementing a Quarkus server. On server start, a (never ending) background process should be started.

I know I can observe the start event with an @ApplicationScopedbean which implements: void onStart(@Observes StartupEvent ev).

But what is the best way to start a background process? Are there restrictions? In J2EE one should not create Threads, but use ManagedExecutorService or an EJB with a @Asynchronous annotated method.

Is there something similar in Quarkus? I only found the scheduler annotations (which are nice, but I want to start a process only once at the beginning).

So can I just create threads? Or just put my infinite code in void onStart(@Observes StartupEvent ev) ?

Thank you

like image 292
Usul Avatar asked Mar 19 '20 15:03

Usul


2 Answers

As in EJB you should not do such things with a background process. Such processes that are "out of control" of the framework cause most of time very annoying problems.

The answer is: It depends on what you want to do in that job.

If you want to execute tasks on a regular base you could use timers.

If you want to use it as an asynchronous worker, you can use a message queue.

Both is most easily done with the vert.x integration into Quarkus.

Use @ConsumeEvent to create a queue, use

@Inject
EventBus bus;

bus.send("Example message");

to send messages.

Use @Scheduled to work on regular jobs, like in this example.

If you need to permanently listen to some socket or file it is getting more difficult. Maybe the websockets will be helpful in this case.

like image 125
martinw Avatar answered Oct 02 '22 20:10

martinw


The easiest way to start a worker thread is using Vertx#executeBlocking, like this:

@Inject
Vertx vertx;

void foo() {
    vertx.<String>executeBlocking(promise -> {
        // This code will be executed in a worker thread
        System.out.println("Thread: " + Thread.currentThread());
        promise.complete("Done");
    }, asyncResult -> {
        System.out.println(asyncResult.result()); // Done
    });
}

If it will be a long running thread maybe it's a good idea not to use the default worker thread pool and create a new one:

...
@PostConstruct
void init() {
    this.executor = vertx.createSharedWorkerExecutor("my-worker", 10);
}
    
void foo() {
    executor.<String>executeBlocking(promise -> {
        ...
    }
}

Other way of doing this is using a Verticle.

like image 37
Vinicius Avatar answered Oct 02 '22 22:10

Vinicius