Add support for task scheduling shutdown related properties
See gh-15951
This commit is contained in:
parent
d2cbf08f09
commit
fa49dfcaaf
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -23,6 +23,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.task.TaskSchedulingProperties.Shutdown;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.task.TaskSchedulerBuilder;
|
||||
import org.springframework.boot.task.TaskSchedulerCustomizer;
|
||||
|
|
@ -58,6 +59,9 @@ public class TaskSchedulingAutoConfiguration {
|
|||
ObjectProvider<TaskSchedulerCustomizer> taskSchedulerCustomizers) {
|
||||
TaskSchedulerBuilder builder = new TaskSchedulerBuilder();
|
||||
builder = builder.poolSize(properties.getPool().getSize());
|
||||
Shutdown shutdown = properties.getShutdown();
|
||||
builder = builder.awaitTermination(shutdown.isAwaitTermination());
|
||||
builder = builder.awaitTerminationPeriod(shutdown.getAwaitTerminationPeriod());
|
||||
builder = builder.threadNamePrefix(properties.getThreadNamePrefix());
|
||||
builder = builder.customizers(taskSchedulerCustomizers);
|
||||
return builder;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.task;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
|
|
@ -29,6 +31,8 @@ public class TaskSchedulingProperties {
|
|||
|
||||
private final Pool pool = new Pool();
|
||||
|
||||
private final Shutdown shutdown = new Shutdown();
|
||||
|
||||
/**
|
||||
* Prefix to use for the names of newly created threads.
|
||||
*/
|
||||
|
|
@ -38,6 +42,10 @@ public class TaskSchedulingProperties {
|
|||
return this.pool;
|
||||
}
|
||||
|
||||
public Shutdown getShutdown() {
|
||||
return this.shutdown;
|
||||
}
|
||||
|
||||
public String getThreadNamePrefix() {
|
||||
return this.threadNamePrefix;
|
||||
}
|
||||
|
|
@ -63,4 +71,34 @@ public class TaskSchedulingProperties {
|
|||
|
||||
}
|
||||
|
||||
public static class Shutdown {
|
||||
|
||||
/**
|
||||
* Whether the executor should wait for scheduled tasks to complete on shutdown.
|
||||
*/
|
||||
private boolean awaitTermination;
|
||||
|
||||
/**
|
||||
* Maximum time the executor should wait for remaining tasks to complete.
|
||||
*/
|
||||
private Duration awaitTerminationPeriod;
|
||||
|
||||
public boolean isAwaitTermination() {
|
||||
return this.awaitTermination;
|
||||
}
|
||||
|
||||
public void setAwaitTermination(boolean awaitTermination) {
|
||||
this.awaitTermination = awaitTermination;
|
||||
}
|
||||
|
||||
public Duration getAwaitTerminationPeriod() {
|
||||
return this.awaitTerminationPeriod;
|
||||
}
|
||||
|
||||
public void setAwaitTerminationPeriod(Duration awaitTerminationPeriod) {
|
||||
this.awaitTerminationPeriod = awaitTerminationPeriod;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -59,11 +59,18 @@ public class TaskSchedulingAutoConfigurationTests {
|
|||
public void enableSchedulingWithNoTaskExecutorAutoConfiguresOne() {
|
||||
this.contextRunner
|
||||
.withPropertyValues(
|
||||
"spring.task.scheduling.shutdown.await-termination=true",
|
||||
"spring.task.scheduling.shutdown.await-termination-period=30s",
|
||||
"spring.task.scheduling.thread-name-prefix=scheduling-test-")
|
||||
.withUserConfiguration(SchedulingConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(TaskExecutor.class);
|
||||
TaskExecutor taskExecutor = context.getBean(TaskExecutor.class);
|
||||
TestBean bean = context.getBean(TestBean.class);
|
||||
Thread.sleep(15);
|
||||
assertThat(taskExecutor).hasFieldOrPropertyWithValue(
|
||||
"waitForTasksToCompleteOnShutdown", true);
|
||||
assertThat(taskExecutor)
|
||||
.hasFieldOrPropertyWithValue("awaitTerminationSeconds", 30);
|
||||
assertThat(bean.threadNames)
|
||||
.allMatch((name) -> name.contains("scheduling-test-"));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.boot.task;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
|
|
@ -42,19 +43,28 @@ public class TaskSchedulerBuilder {
|
|||
|
||||
private final Integer poolSize;
|
||||
|
||||
private final Boolean awaitTermination;
|
||||
|
||||
private final Duration awaitTerminationPeriod;
|
||||
|
||||
private final String threadNamePrefix;
|
||||
|
||||
private final Set<TaskSchedulerCustomizer> customizers;
|
||||
|
||||
public TaskSchedulerBuilder() {
|
||||
this.poolSize = null;
|
||||
this.awaitTermination = null;
|
||||
this.awaitTerminationPeriod = null;
|
||||
this.threadNamePrefix = null;
|
||||
this.customizers = null;
|
||||
}
|
||||
|
||||
public TaskSchedulerBuilder(Integer poolSize, String threadNamePrefix,
|
||||
public TaskSchedulerBuilder(Integer poolSize, Boolean awaitTermination,
|
||||
Duration awaitTerminationPeriod, String threadNamePrefix,
|
||||
Set<TaskSchedulerCustomizer> taskSchedulerCustomizers) {
|
||||
this.poolSize = poolSize;
|
||||
this.awaitTermination = awaitTermination;
|
||||
this.awaitTerminationPeriod = awaitTerminationPeriod;
|
||||
this.threadNamePrefix = threadNamePrefix;
|
||||
this.customizers = taskSchedulerCustomizers;
|
||||
}
|
||||
|
|
@ -65,8 +75,35 @@ public class TaskSchedulerBuilder {
|
|||
* @return a new builder instance
|
||||
*/
|
||||
public TaskSchedulerBuilder poolSize(int poolSize) {
|
||||
return new TaskSchedulerBuilder(poolSize, this.threadNamePrefix,
|
||||
this.customizers);
|
||||
return new TaskSchedulerBuilder(poolSize, this.awaitTermination,
|
||||
this.awaitTerminationPeriod, this.threadNamePrefix, this.customizers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the executor should wait for scheduled tasks to complete on shutdown,
|
||||
* not interrupting running tasks and executing all tasks in the queue.
|
||||
* @param awaitTermination whether the executor needs to wait for the tasks to
|
||||
* complete on shutdown
|
||||
* @return a new builder instance
|
||||
* @see #awaitTerminationPeriod(Duration)
|
||||
*/
|
||||
public TaskSchedulerBuilder awaitTermination(boolean awaitTermination) {
|
||||
return new TaskSchedulerBuilder(this.poolSize, awaitTermination,
|
||||
this.awaitTerminationPeriod, this.threadNamePrefix, this.customizers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum time the executor is supposed to block on shutdown. When set, the
|
||||
* executor blocks on shutdown in order to wait for remaining tasks to complete their
|
||||
* execution before the rest of the container continues to shut down. This is
|
||||
* particularly useful if your remaining tasks are likely to need access to other
|
||||
* resources that are also managed by the container.
|
||||
* @param awaitTerminationPeriod the await termination period to set
|
||||
* @return a new builder instance
|
||||
*/
|
||||
public TaskSchedulerBuilder awaitTerminationPeriod(Duration awaitTerminationPeriod) {
|
||||
return new TaskSchedulerBuilder(this.poolSize, this.awaitTermination,
|
||||
awaitTerminationPeriod, this.threadNamePrefix, this.customizers);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -75,8 +112,8 @@ public class TaskSchedulerBuilder {
|
|||
* @return a new builder instance
|
||||
*/
|
||||
public TaskSchedulerBuilder threadNamePrefix(String threadNamePrefix) {
|
||||
return new TaskSchedulerBuilder(this.poolSize, threadNamePrefix,
|
||||
this.customizers);
|
||||
return new TaskSchedulerBuilder(this.poolSize, this.awaitTermination,
|
||||
this.awaitTerminationPeriod, threadNamePrefix, this.customizers);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -105,7 +142,8 @@ public class TaskSchedulerBuilder {
|
|||
public TaskSchedulerBuilder customizers(
|
||||
Iterable<TaskSchedulerCustomizer> customizers) {
|
||||
Assert.notNull(customizers, "Customizers must not be null");
|
||||
return new TaskSchedulerBuilder(this.poolSize, this.threadNamePrefix,
|
||||
return new TaskSchedulerBuilder(this.poolSize, this.awaitTermination,
|
||||
this.awaitTerminationPeriod, this.threadNamePrefix,
|
||||
append(null, customizers));
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +172,8 @@ public class TaskSchedulerBuilder {
|
|||
public TaskSchedulerBuilder additionalCustomizers(
|
||||
Iterable<TaskSchedulerCustomizer> customizers) {
|
||||
Assert.notNull(customizers, "Customizers must not be null");
|
||||
return new TaskSchedulerBuilder(this.poolSize, this.threadNamePrefix,
|
||||
return new TaskSchedulerBuilder(this.poolSize, this.awaitTermination,
|
||||
this.awaitTerminationPeriod, this.threadNamePrefix,
|
||||
append(this.customizers, customizers));
|
||||
}
|
||||
|
||||
|
|
@ -158,6 +197,10 @@ public class TaskSchedulerBuilder {
|
|||
public <T extends ThreadPoolTaskScheduler> T configure(T taskScheduler) {
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(this.poolSize).to(taskScheduler::setPoolSize);
|
||||
map.from(this.awaitTermination)
|
||||
.to(taskScheduler::setWaitForTasksToCompleteOnShutdown);
|
||||
map.from(this.awaitTerminationPeriod).asInt(Duration::getSeconds)
|
||||
.to(taskScheduler::setAwaitTerminationSeconds);
|
||||
map.from(this.threadNamePrefix).to(taskScheduler::setThreadNamePrefix);
|
||||
if (!CollectionUtils.isEmpty(this.customizers)) {
|
||||
this.customizers.forEach((customizer) -> customizer.customize(taskScheduler));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.boot.task;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
|
|
@ -45,6 +46,20 @@ public class TaskSchedulerBuilderTests {
|
|||
assertThat(scheduler.getPoolSize()).isEqualTo(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void awaitTerminationShouldApply() {
|
||||
ThreadPoolTaskScheduler executor = this.builder.awaitTermination(true).build();
|
||||
assertThat(executor)
|
||||
.hasFieldOrPropertyWithValue("waitForTasksToCompleteOnShutdown", true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void awaitTerminationPeriodShouldApply() {
|
||||
ThreadPoolTaskScheduler executor = this.builder
|
||||
.awaitTerminationPeriod(Duration.ofMinutes(1)).build();
|
||||
assertThat(executor).hasFieldOrPropertyWithValue("awaitTerminationSeconds", 60);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void threadNamePrefixShouldApply() {
|
||||
ThreadPoolTaskScheduler scheduler = this.builder.threadNamePrefix("test-")
|
||||
|
|
|
|||
Loading…
Reference in New Issue