Skip to content

Commit 597c58f

Browse files
quaffsnicoll
authored andcommitted
Add support for SimpleTaskExecutor#reject-tasks-when-limit-reached
See gh-45155 Signed-off-by: Yanming Zhou <[email protected]>
1 parent 10b15e3 commit 597c58f

File tree

5 files changed

+52
-10
lines changed

5 files changed

+52
-10
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutionProperties.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ public static class Simple {
8383
*/
8484
private Integer concurrencyLimit;
8585

86+
/**
87+
* Specify whether to reject tasks when the concurrency limit has been reached.
88+
*/
89+
private boolean rejectTasksWhenLimitReached;
90+
8691
public Integer getConcurrencyLimit() {
8792
return this.concurrencyLimit;
8893
}
@@ -91,6 +96,14 @@ public void setConcurrencyLimit(Integer concurrencyLimit) {
9196
this.concurrencyLimit = concurrencyLimit;
9297
}
9398

99+
public boolean isRejectTasksWhenLimitReached() {
100+
return this.rejectTasksWhenLimitReached;
101+
}
102+
103+
public void setRejectTasksWhenLimitReached(boolean rejectTasksWhenLimitReached) {
104+
this.rejectTasksWhenLimitReached = rejectTasksWhenLimitReached;
105+
}
106+
94107
}
95108

96109
public static class Pool {

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ private SimpleAsyncTaskExecutorBuilder builder() {
136136
builder = builder.taskDecorator(this.taskDecorator.getIfUnique());
137137
TaskExecutionProperties.Simple simple = this.properties.getSimple();
138138
builder = builder.concurrencyLimit(simple.getConcurrencyLimit());
139+
builder = builder.rejectTasksWhenLimitReached(simple.isRejectTasksWhenLimitReached());
139140
TaskExecutionProperties.Shutdown shutdown = this.properties.getShutdown();
140141
if (shutdown.isAwaitTermination()) {
141142
builder = builder.taskTerminationTimeout(shutdown.getAwaitTerminationPeriod());

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfigurationTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,12 @@ void simpleAsyncTaskExecutorBuilderShouldReadProperties() {
8484
this.contextRunner
8585
.withPropertyValues("spring.task.execution.thread-name-prefix=mytest-",
8686
"spring.task.execution.simple.concurrency-limit=1",
87+
"spring.task.execution.simple.reject-tasks-when-limit-reached=true",
8788
"spring.task.execution.shutdown.await-termination=true",
8889
"spring.task.execution.shutdown.await-termination-period=30s")
8990
.run(assertSimpleAsyncTaskExecutor((taskExecutor) -> {
9091
assertThat(taskExecutor.getConcurrencyLimit()).isEqualTo(1);
92+
assertThat(taskExecutor).hasFieldOrPropertyWithValue("rejectTasksWhenLimitReached", true);
9193
assertThat(taskExecutor.getThreadNamePrefix()).isEqualTo("mytest-");
9294
assertThat(taskExecutor).hasFieldOrPropertyWithValue("taskTerminationTimeout", 30000L);
9395
}));

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilder.java

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
* @author Stephane Nicoll
4242
* @author Filip Hrisafov
4343
* @author Moritz Halbritter
44+
* @author Yanming Zhou
4445
* @since 3.2.0
4546
*/
4647
public class SimpleAsyncTaskExecutorBuilder {
@@ -51,22 +52,25 @@ public class SimpleAsyncTaskExecutorBuilder {
5152

5253
private final Integer concurrencyLimit;
5354

55+
private final boolean rejectTasksWhenLimitReached;
56+
5457
private final TaskDecorator taskDecorator;
5558

5659
private final Set<SimpleAsyncTaskExecutorCustomizer> customizers;
5760

5861
private final Duration taskTerminationTimeout;
5962

6063
public SimpleAsyncTaskExecutorBuilder() {
61-
this(null, null, null, null, null, null);
64+
this(null, null, null, false, null, null, null);
6265
}
6366

6467
private SimpleAsyncTaskExecutorBuilder(Boolean virtualThreads, String threadNamePrefix, Integer concurrencyLimit,
65-
TaskDecorator taskDecorator, Set<SimpleAsyncTaskExecutorCustomizer> customizers,
66-
Duration taskTerminationTimeout) {
68+
boolean rejectTasksWhenLimitReached, TaskDecorator taskDecorator,
69+
Set<SimpleAsyncTaskExecutorCustomizer> customizers, Duration taskTerminationTimeout) {
6770
this.virtualThreads = virtualThreads;
6871
this.threadNamePrefix = threadNamePrefix;
6972
this.concurrencyLimit = concurrencyLimit;
73+
this.rejectTasksWhenLimitReached = rejectTasksWhenLimitReached;
7074
this.taskDecorator = taskDecorator;
7175
this.customizers = customizers;
7276
this.taskTerminationTimeout = taskTerminationTimeout;
@@ -79,7 +83,7 @@ private SimpleAsyncTaskExecutorBuilder(Boolean virtualThreads, String threadName
7983
*/
8084
public SimpleAsyncTaskExecutorBuilder threadNamePrefix(String threadNamePrefix) {
8185
return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, threadNamePrefix, this.concurrencyLimit,
82-
this.taskDecorator, this.customizers, this.taskTerminationTimeout);
86+
this.rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, this.taskTerminationTimeout);
8387
}
8488

8589
/**
@@ -89,7 +93,7 @@ public SimpleAsyncTaskExecutorBuilder threadNamePrefix(String threadNamePrefix)
8993
*/
9094
public SimpleAsyncTaskExecutorBuilder virtualThreads(Boolean virtualThreads) {
9195
return new SimpleAsyncTaskExecutorBuilder(virtualThreads, this.threadNamePrefix, this.concurrencyLimit,
92-
this.taskDecorator, this.customizers, this.taskTerminationTimeout);
96+
this.rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, this.taskTerminationTimeout);
9397
}
9498

9599
/**
@@ -99,7 +103,19 @@ public SimpleAsyncTaskExecutorBuilder virtualThreads(Boolean virtualThreads) {
99103
*/
100104
public SimpleAsyncTaskExecutorBuilder concurrencyLimit(Integer concurrencyLimit) {
101105
return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, concurrencyLimit,
102-
this.taskDecorator, this.customizers, this.taskTerminationTimeout);
106+
this.rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, this.taskTerminationTimeout);
107+
}
108+
109+
/**
110+
* Specify whether to reject tasks when the concurrency limit has been reached.
111+
* @param rejectTasksWhenLimitReached whether to reject tasks when the concurrency
112+
* limit has been reached
113+
* @return a new builder instance
114+
* @since 3.5.0
115+
*/
116+
public SimpleAsyncTaskExecutorBuilder rejectTasksWhenLimitReached(boolean rejectTasksWhenLimitReached) {
117+
return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit,
118+
rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, this.taskTerminationTimeout);
103119
}
104120

105121
/**
@@ -109,7 +125,7 @@ public SimpleAsyncTaskExecutorBuilder concurrencyLimit(Integer concurrencyLimit)
109125
*/
110126
public SimpleAsyncTaskExecutorBuilder taskDecorator(TaskDecorator taskDecorator) {
111127
return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit,
112-
taskDecorator, this.customizers, this.taskTerminationTimeout);
128+
this.rejectTasksWhenLimitReached, taskDecorator, this.customizers, this.taskTerminationTimeout);
113129
}
114130

115131
/**
@@ -120,7 +136,7 @@ public SimpleAsyncTaskExecutorBuilder taskDecorator(TaskDecorator taskDecorator)
120136
*/
121137
public SimpleAsyncTaskExecutorBuilder taskTerminationTimeout(Duration taskTerminationTimeout) {
122138
return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit,
123-
this.taskDecorator, this.customizers, taskTerminationTimeout);
139+
this.rejectTasksWhenLimitReached, this.taskDecorator, this.customizers, taskTerminationTimeout);
124140
}
125141

126142
/**
@@ -150,7 +166,8 @@ public SimpleAsyncTaskExecutorBuilder customizers(
150166
Iterable<? extends SimpleAsyncTaskExecutorCustomizer> customizers) {
151167
Assert.notNull(customizers, "'customizers' must not be null");
152168
return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit,
153-
this.taskDecorator, append(null, customizers), this.taskTerminationTimeout);
169+
this.rejectTasksWhenLimitReached, this.taskDecorator, append(null, customizers),
170+
this.taskTerminationTimeout);
154171
}
155172

156173
/**
@@ -178,7 +195,8 @@ public SimpleAsyncTaskExecutorBuilder additionalCustomizers(
178195
Iterable<? extends SimpleAsyncTaskExecutorCustomizer> customizers) {
179196
Assert.notNull(customizers, "'customizers' must not be null");
180197
return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit,
181-
this.taskDecorator, append(this.customizers, customizers), this.taskTerminationTimeout);
198+
this.rejectTasksWhenLimitReached, this.taskDecorator, append(this.customizers, customizers),
199+
this.taskTerminationTimeout);
182200
}
183201

184202
/**
@@ -218,6 +236,7 @@ public <T extends SimpleAsyncTaskExecutor> T configure(T taskExecutor) {
218236
map.from(this.virtualThreads).to(taskExecutor::setVirtualThreads);
219237
map.from(this.threadNamePrefix).whenHasText().to(taskExecutor::setThreadNamePrefix);
220238
map.from(this.concurrencyLimit).to(taskExecutor::setConcurrencyLimit);
239+
map.from(this.rejectTasksWhenLimitReached).to(taskExecutor::setRejectTasksWhenLimitReached);
221240
map.from(this.taskDecorator).to(taskExecutor::setTaskDecorator);
222241
map.from(this.taskTerminationTimeout).as(Duration::toMillis).to(taskExecutor::setTaskTerminationTimeout);
223242
if (!CollectionUtils.isEmpty(this.customizers)) {

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/task/SimpleAsyncTaskExecutorBuilderTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
* @author Stephane Nicoll
4141
* @author Filip Hrisafov
4242
* @author Moritz Halbritter
43+
* @author Yanming Zhou
4344
*/
4445
class SimpleAsyncTaskExecutorBuilderTests {
4546

@@ -64,6 +65,12 @@ void concurrencyLimitShouldApply() {
6465
assertThat(executor.getConcurrencyLimit()).isEqualTo(1);
6566
}
6667

68+
@Test
69+
void rejectTasksWhenLimitReachedShouldApply() {
70+
SimpleAsyncTaskExecutor executor = this.builder.rejectTasksWhenLimitReached(true).build();
71+
assertThat(executor).extracting("rejectTasksWhenLimitReached").isEqualTo(true);
72+
}
73+
6774
@Test
6875
void taskDecoratorShouldApply() {
6976
TaskDecorator taskDecorator = mock(TaskDecorator.class);

0 commit comments

Comments
 (0)