GH-8642: Revise executors in the project (#8647)

* GH-8642: Revise executors in the project

Fixes https://github.com/spring-projects/spring-integration/issues/8642

* Rework some `Executors.newSingleThreadExecutor()` to `ExecutorServiceAdapter(new SimpleAsyncTaskExecutor())`
* Expose `TaskExecutor` setters; deprecate `ExecutorService`-based
* Some other code clean up in the effected classes: `LogAccessor`, no `synchronized` in critical blocks
* Give a meaningful prefix for default threads in the context of components, e.g. `SubscribableRedisChannel` - `getBeanName() + "-"`

* * Fix `PostgresChannelMessageTableSubscriberTests` for
`PostgresSubscribableChannel` initialization to let it create
its internal `Executor`

* Use an `AsyncTaskExecutor` injection instead of `ExecutorServiceAdapter` wrapping

* Fix `LockRegistryLeaderInitiatorTests` for `taskExecutor` injection

* Bring back `LockRegistryLeaderInitiator.setExecutorService()`
as an accident after property auto-renaming
This commit is contained in:
Artem Bilan
2023-06-14 13:33:46 -04:00
committed by GitHub
parent aac2adbaa3
commit 4db9bad50d
9 changed files with 142 additions and 174 deletions

View File

@@ -24,7 +24,6 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@@ -33,10 +32,12 @@ import org.postgresql.jdbc.PgConnection;
import org.springframework.context.SmartLifecycle;
import org.springframework.core.log.LogAccessor;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.support.TaskExecutorAdapter;
import org.springframework.integration.jdbc.store.JdbcChannelMessageStore;
import org.springframework.integration.util.UUIDConverter;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.util.Assert;
/**
@@ -73,8 +74,7 @@ public final class PostgresChannelMessageTableSubscriber implements SmartLifecyc
private final String tablePrefix;
@Nullable
private ExecutorService executor;
private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("postgres-channel-message-table-subscriber-");
private CountDownLatch latch = new CountDownLatch(0);
@@ -108,9 +108,21 @@ public final class PostgresChannelMessageTableSubscriber implements SmartLifecyc
* listening for notifications as a blocking operation which will permanently block a thread of this executor
* while running.
* @param executor The executor to use or {@code null} if an executor should be created by this class.
* @deprecated since 6.2 in favor of {@link #setTaskExecutor(AsyncTaskExecutor)}
*/
public synchronized void setExecutor(@Nullable ExecutorService executor) {
this.executor = executor;
@Deprecated(since = "6.2", forRemoval = true)
public synchronized void setExecutor(ExecutorService executor) {
setTaskExecutor(new TaskExecutorAdapter(executor));
}
/**
* Provide a managed {@link AsyncTaskExecutor} for Postgres listener daemon.
* @param taskExecutor the {@link AsyncTaskExecutor} to use.
* @since 6.2
*/
public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
Assert.notNull(taskExecutor, "A 'taskExecutor' must not be null.");
this.taskExecutor = taskExecutor;
}
/**
@@ -141,18 +153,11 @@ public final class PostgresChannelMessageTableSubscriber implements SmartLifecyc
if (this.latch.getCount() > 0) {
return;
}
ExecutorService executorToUse = this.executor;
if (executorToUse == null) {
CustomizableThreadFactory threadFactory =
new CustomizableThreadFactory("postgres-channel-message-table-subscriber-");
threadFactory.setDaemon(true);
executorToUse = Executors.newSingleThreadExecutor(threadFactory);
this.executor = executorToUse;
}
this.latch = new CountDownLatch(1);
CountDownLatch startingLatch = new CountDownLatch(1);
this.future = executorToUse.submit(() -> {
this.future = this.taskExecutor.submit(() -> {
try {
while (isActive()) {
try {

View File

@@ -65,7 +65,7 @@ public class PostgresSubscribableChannel extends AbstractSubscribableChannel
private RetryTemplate retryTemplate = RetryTemplate.builder().maxAttempts(1).build();
private Executor executor = new SimpleAsyncTaskExecutor();
private Executor executor;
/**
* Create a subscribable channel for a Postgres database.
@@ -115,6 +115,14 @@ public class PostgresSubscribableChannel extends AbstractSubscribableChannel
this.retryTemplate = retryTemplate;
}
@Override
protected void onInit() {
super.onInit();
if (this.executor == null) {
this.executor = new SimpleAsyncTaskExecutor(getBeanName() + "-dispatcher-");
}
}
@Override
public boolean subscribe(MessageHandler handler) {
boolean subscribed = super.subscribe(handler);

View File

@@ -124,6 +124,8 @@ public class PostgresChannelMessageTableSubscriberTests implements PostgresConta
this.postgresSubscribableChannel =
new PostgresSubscribableChannel(messageStore, groupId, postgresChannelMessageTableSubscriber);
this.postgresSubscribableChannel.setBeanName("testPostgresChannel");
this.postgresSubscribableChannel.afterPropertiesSet();
}
@AfterEach