Skip to content

Commit 8b6a34f

Browse files
authored
Merge pull request #46100 from manovotn/schedulerLongRunningTasks
Scheduler - document scheduling long running tasks
2 parents db011a2 + d5bc184 commit 8b6a34f

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

docs/src/main/asciidoc/scheduler-reference.adoc

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,57 @@ class MyService {
442442

443443
NOTE: A CDI event is fired synchronously and asynchronously when the scheduler or a scheduled job is paused/resumed. The payload is `io.quarkus.scheduler.SchedulerPaused`, `io.quarkus.scheduler.SchedulerResumed`, `io.quarkus.scheduler.ScheduledJobPaused` and `io.quarkus.scheduler.ScheduledJobResumed` respectively.
444444

445+
[[scheduling_long_running_tasks]]
446+
== Scheduling Long-Running Tasks
447+
448+
Executing a long-running task might yield a warning message similar to the following:
449+
450+
[source,java]
451+
----
452+
WARN [io.ver.cor.imp.BlockedThreadChecker] (vertx-blocked-thread-checker) Thread Thread[vert.x-worker-thread-1,5,main] has been blocked for 81879 ms, time limit is 60000 ms: io.vertx.core.VertxException: Thread blocked
453+
----
454+
455+
This is happening because the default worker thread pool is coming from Vert.x which guards against threads being blocked for far too long.
456+
457+
NOTE: The amount of time for which a Vert.x worker thread can be blocked is also https://quarkus.io/guides/all-config#quarkus-vertx_quarkus-vertx-max-worker-execute-time[configurable].
458+
459+
Therefore, a proper way to execute long tasks is to offload them from the scheduled method to a custom executor service.
460+
Here's an example of such setup for a long-running task that we do not expect to execute often:
461+
462+
[source,java]
463+
----
464+
@ApplicationScoped
465+
public class LongRunner implements Runnable {
466+
467+
private ExecutorService executorService;
468+
469+
@PostConstruct
470+
void init() {
471+
executorService = Executors.newThreadPerTaskExecutor(Executors.defaultThreadFactory()); <1>
472+
}
473+
474+
@PreDestroy
475+
void destroy() {
476+
executorService.shutdown(); <2>
477+
}
478+
479+
480+
@Scheduled(cron = "{my.schedule}")
481+
public void update() {
482+
executorService.execute(this); <3>
483+
}
484+
485+
@Override
486+
public void run() { <4>
487+
// perform the actual task here
488+
}
489+
}
490+
----
491+
<1> Create a fitting executor. In this case, a new thread is created per scheduled task and stopped once the task finishes.
492+
<2> `@PreDestroy` callback is used to shut down the executor service.
493+
<3> Scheduled method only delegates the job to the custom executor - this prevent Vert.x thread from being blocked.
494+
<4> The bean implements `Runnable`, a format we can directly pass to the executor service as a parameter.
495+
445496
[[programmatic_scheduling]]
446497
== Programmatic Scheduling
447498

0 commit comments

Comments
 (0)