我有一个JdbcPollingChannelAdapter定义如下:
Button
集成流程:
@Bean
public MessageSource<Object> jdbcMessageSource(DataSource dataSource) {
JdbcPollingChannelAdapter jdbcPollingChannelAdapter = new JdbcPollingChannelAdapter(dataSource,
"SELECT * FROM common_task where due_at <= NOW() and retries < order by due_at ASC FOR UPDATE SKIP LOCKED");
jdbcPollingChannelAdapter.setMaxRowsPerPoll(1);
jdbcPollingChannelAdapter.setUpdateSql("Update common_task set retries = :retries, due_at = due_at + interval '10 minutes' WHERE ID = (:id)");
jdbcPollingChannelAdapter.setUpdatePerRow(true);
jdbcPollingChannelAdapter.setRowMapper(this::mapRow);
jdbcPollingChannelAdapter.setUpdateSqlParameterSourceFactory(this::updateParamSource);
return jdbcPollingChannelAdapter;
}
服务激活器定义为
@Bean
public IntegrationFlow pollingFlow(MessageSource<Object> jdbcMessageSource) {
return IntegrationFlows.from(jdbcMessageSource,
c -> c.poller(Pollers.fixedRate(250, TimeUnit.MILLISECONDS)
.maxMessagesPerPoll(1)
.transactional()))
.split()
.channel(taskSourceChannel())
.get();
}
集成流程中的轮询器定义为事务性的。根据我的理解,这将 1.执行选择查询并更新事务中的查询。 2.还将在同一事务中执行doSomething()方法。
目标:我想执行1而不是2。我想在事务中进行选择和更新以确保两者均发生。但是,我不想在同一事务中执行doSomething()。如果对doSomething()有所了解,我仍然希望保留轮询期间所做的更新。我该如何实现?
答案 0 :(得分:2)
这是通过简单的线程转移完成的。因此,您只需要离开轮询线程,允许它提交TX并在单独的线程中继续进行处理即可。
根据.split()
的逻辑,分割后已经有新的线程处理会更好,因此项目甚至将由该doSomething()
并行处理。
只需使用ExecutorChannel
即可实现目标。由于您已经拥有该taskSourceChannel()
,因此只需考虑根据某些托管的ExecutorChannel
将其替换为ThreadPoolTaskExecutor
。
请参阅参考手册中的更多信息:https://docs.spring.io/spring-integration/reference/html/messaging-channels-section.html#channel-configuration-executorchannel
及其Javadocs。
简单的Java配置变体如下:
@Bean
public MessageChannel taskSourceChannel() {
return new ExecutorChannel(executor());
}
@Bean
public Executor executor() {
return new ThreadPoolTaskExecutor();
}