Skip to content

Commit

Permalink
Use a timer when awaiting Quartz shutdown
Browse files Browse the repository at this point in the history
The Quartz scheduler shutdown seems like it
can block indefinitely if there is an exception
in a yet to be completed job.
To guard against this, we ensure that we only
wait a configurable amount of time for the scheduler
to shut down.

This is a breaking change because previously we waited
indefinitely.

Relates to quarkusio#28114
  • Loading branch information
geoand committed Sep 23, 2022
1 parent d18b476 commit a4d38da
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.quartz.runtime;

import java.time.Duration;
import java.util.Map;
import java.util.Optional;

Expand Down Expand Up @@ -57,6 +58,13 @@ public class QuartzBuildTimeConfig {
@ConfigItem(defaultValue = "QRTZ_")
public String tablePrefix;

/**
* The maximum amount of time Quarkus will wait for currently running jobs to finish.
* If the value is {@code 0}, then Quarkus will not wait at all for these jobs.
*/
@ConfigItem(defaultValue = "PT10S")
public Duration shutdownWaitTime;

/**
* The SQL string that selects a row in the "LOCKS" table and places a lock on the row.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
import java.util.Objects;
import java.util.OptionalLong;
import java.util.Properties;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import javax.annotation.PreDestroy;
Expand Down Expand Up @@ -89,6 +92,7 @@ public class QuartzScheduler implements Scheduler {
private final org.quartz.Scheduler scheduler;
private final boolean enabled;
private final boolean startHalted;
private final Duration shutdownWaitTime;
private final Map<String, QuartzTrigger> scheduledTasks = new HashMap<>();

public QuartzScheduler(SchedulerContext context, QuartzSupport quartzSupport, SchedulerRuntimeConfig schedulerRuntimeConfig,
Expand All @@ -97,6 +101,7 @@ public QuartzScheduler(SchedulerContext context, QuartzSupport quartzSupport, Sc
Vertx vertx) {
enabled = schedulerRuntimeConfig.enabled;
final Duration defaultOverdueGracePeriod = schedulerRuntimeConfig.overdueGracePeriod;
shutdownWaitTime = quartzSupport.getBuildTimeConfig().shutdownWaitTime;
final QuartzRuntimeConfig runtimeConfig = quartzSupport.getRuntimeConfig();

boolean forceStart;
Expand Down Expand Up @@ -478,9 +483,24 @@ void start(@Observes @Priority(Interceptor.Priority.PLATFORM_BEFORE) StartupEven
void destroy(@Observes @BeforeDestroyed(ApplicationScoped.class) Object event) {
if (scheduler != null) {
try {
// Note that this method does not return until all currently executing jobs have completed
scheduler.shutdown(true);
} catch (SchedulerException e) {
if (shutdownWaitTime.isZero()) {
scheduler.shutdown(false);
} else {
CompletableFuture.supplyAsync(new Supplier<>() {
@Override
public Void get() {
// Note that this method does not return until all currently executing jobs have completed
try {
scheduler.shutdown(true);
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
return null;
}
}).get(shutdownWaitTime.toMillis(), TimeUnit.MILLISECONDS);
}

} catch (Exception e) {
LOGGER.warnf("Unable to gracefully shutdown the scheduler", e);
}
}
Expand Down

0 comments on commit a4d38da

Please sign in to comment.