Skip to content

Behaviour change in ScheduledAnnotationBeanPostProcessor: canceling scheduled tasks on ContextClosedEvent v6.0 -> v6.1 #33009

Closed
@ansgarschulte

Description

@ansgarschulte

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

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: regressionA bug that is also a regression

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions