Use case:
During Graceful Shutdown, we rely on scheduled tasks being executed until final shutdown. This works with springs v6.0.x and stopped working in v6.1
With this change all scheduled tasks are canceled and continueExistingPeriodicTasksAfterShutdownPolicy
of the ThreadPoolTaskScheduler
has no effect here.
Here is a spring boot sample application:
@SpringBootApplication
@EnableScheduling
public class DemoApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
System.out.println("Sleeping forever, you can press Ctrl+C to shutdown application");
while (true) {
Thread.sleep(1000);
}
}
@Bean
ThreadPoolTaskSchedulerCustomizer threadPoolTaskSchedulerPhaseCustomizer() {
return p -> {
p.setPhase(0);
p.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
p.setWaitForTasksToCompleteOnShutdown(true);
p.setAcceptTasksAfterContextClose(true);
p.setExecuteExistingDelayedTasksAfterShutdownPolicy(true);
p.setAwaitTerminationSeconds(180);
p.setPoolSize(4);
p.setThreadNamePrefix("custom-scheduler-");
};
}
@Scheduled(fixedRate = 1000, scheduler = ScheduledAnnotationBeanPostProcessor.DEFAULT_TASK_SCHEDULER_BEAN_NAME)
public void test() {
var pid = System.getProperty("PID");
System.out.println("Kill me with 'kill -int " + pid + "' - " + Thread.currentThread().getName() + " - " + System.currentTimeMillis());
}
@Bean
SmartLifecycle waitOnShutdown() {
return new SmartLifecycle() {
private boolean running;
@Override
public void start() {
this.running = true;
}
@Override
public void stop() {
var counter = 0;
System.out.println("Waiting for 10 seconds before stopping");
do {
try {
System.out.println("Waiting for 1 second");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (counter++ < 10);
this.running = true;
}
@Override
public boolean isRunning() {
return this.running;
}
};
}
}
After sending kill -int xyz
to the output of the scheduled task stops.
Our current workaround is to use a custom ScheduledAnnotationBeanPostProcessor
ignoring the ContextClosedEvent
Comment From: jhoeller
It looks like the fix for #24629 is too harsh in assuming that all declaratively scheduled tasks should be cancelled unconditionally on context close. I'll see how we can revise this while still adhering to the target scenario in #24629 as well.
Comment From: jhoeller
The revision will be available in the upcoming 6.1.9 snapshot, reducing the early cancellation to non-managed objects while letting regular singleton beans participate in the regular factory destruction arrangement and the scheduler setup. Please give it an early try if you have the chance today, in advance of the actual 6.1.9 release tomorrow...
Comment From: ansgarschulte
Thx for the fast fix and turnaround. I can confirm that it is working with my test application and setting continueExistingPeriodicTasksAfterShutdownPolicy
to false (default value).
Comment From: jhoeller
Good to hear, thanks for the immediate feedback!