EnableAsync есть, запросы что вызываюся из @RestController нормально реагируют на @Async
@Configuration
@EnableAsync
public class ThreadConfig {
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(60);
executor.setMaxPoolSize(200);
//other proeprties to be set here
executor.setThreadNamePrefix("ASYNC-");
executor.initialize();
return executor;
}
}
но дальше внутри сервис что ловит Exception и его пытается записать, упорно не реагирует на @Async, хотя вроде все условия соблюдаются: метод в отдельном сервисе
@Service
public class BatchLogGateway {
@Autowired
private NamedParameterJdbcTemplate jdbcTemplate;
private static final Logger logger = LoggerFactory.getLogger(BatchLogGateway.class);
@Async
// @Transactional(isolation= Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, noRollbackFor = LockTimeoutException.class)public void writeBatchLog(int batchNo, String errorTxt) {
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
namedParameters.addValue("batchNo", batchNo);
namedParameters.addValue("error", errorTxt);
try {
jdbcTemplate.update("INSERT INTO batches_error_log (error_log, batch_no) values (:error, :batchNo)", namedParameters);
} catch (Exception e) {
logger.error("writing into batchLog {} error was unsuccessful", batchNo);
}
}
}
в логе вижу что writeBatchLog() выполняется в том же треде, что и его вызывающий метод. Spring boot свежий: 3.1.1
B>[...] упорно не реагирует на @Async, хотя вроде все условия соблюдаются: метод в отдельном сервисе
Так у тебя планировщик асинхронно вызывает "непроксированную" версию метода writeBatchLog() с @Async без контекста транзакции.
Раздели вызываемые методы планировщика (с @Async) и метод непосредственного журналирования (с @Transactional). Это два разных метода должны быть (потому что SOLID).
PS. В любом случае лучше всегда создавать интерфейсы на сервисы/компоненты это позволяет глубже понимать что вообще пишется и, конечно, избегать инжекта полей (Why Is Field Injection Not Recommended?)
...<< RSDN@Home 1.3.1 ✪ ♪Die Toten Hosen — Unter Den Wolken>>
вынес в соседний метод, поставил @Transaction аннотацию какая была закоментирована — не помогло.
если BatchLogGateway это спинговый сервис, почему у него вызывают "непроксированную" версию метода ?
может это как-то связанно с каскадом вызовов ? в прикладухе есть @RestController, он дергает бизнес логику, где расставлены @Async (что бы рест клиента не задерживать). тут все отлично работает, вижу, что бизнес логика в отдельных тредах, дальше если вдруг случается exception то BatchGateway апдейтит статус батча и дергает BatchLogGateway#writeBatchLog(), записать сам exception. вот его я и ожидал увидеть в третьем треде, вроде все компоненты в каскаде вызовов спринговые сервисы. как я понял это все, что требуется.
Здравствуйте, Ballista, Вы писали:
B>может это как-то связанно с каскадом вызовов ? в прикладухе есть @RestController, он дергает бизнес логику
Добавь для твоих @Async и твоего @Bean public Executor taskExecutor() имена, например:
@Bean("taskExecutor")
public Executor taskExecutor() {
// ...
}
и не забудь про твои @Async
@Async("taskExecutor")
PS.
Если это не помогло, то распиши внятно что у тебя не работает, возникают ли исключения, стартует ли boot без ошибок, сделай снипетов твоего REST-контроллера?
1. код, который вызывает метод writeBatchLog
т.к. если
— вызов из того же класса(BatchLogGateway )
— инстанс BatchLogGateway создаётся не контейнером, а конструктором ( и такое видели )
будет вызван непроксированный метод.
2. распечатать перед вызовом метода инстанс BatchLogGateway, у которого вызывается метод, и прислать лог.
— будет видно имя класса, по нему иногда можно определить, а было ли прокси.
--
0. Всё-таки проверить, что ThreadConfig подхватывается.
— убрать @EnableAsync и посмотреть, если все отлично работает, вижу, что бизнес логика в отдельных тредах, и без @EnableAsync,
значит конфиг таки не подхватывается и его нужно подхватить.