我们将拥有一个包含多个工作单元的Mongo集合。我的想法是该文档将具有一个带有四个选项的状态字段:未处理,处理,完成,失败。 Spring Integration将配置为从该数据库读取并处理存储在该数据库中的消息。
将根据值UNPROCESSED从集合中读取入站Mongo DSL流:
MongoDbMessageSource messageSource = new MongoDbMessageSource(mongo, new LiteralExpression("{'status' : 'UNPROCESSED'}"));
return IntegrationFlows.from(messageSource)...
这是问题所在:如果我有几台工作机从同一数据库中读取数据,我想阻止它们在相同行的未处理数据上进行操作,因为我的轮询器将保守值用于maxMessagesPerPoll
或消息处理需要一会儿。
似乎合适的场所是使用TransactionSynchronizationFactory
定义 ProcessBeforeCommit 阶段以将状态更新为“正在处理”,以及 ProcessAfterCommit 阶段以更新状态。完成或失败。但是,在查看轮询器和TransactionManagers的API时,添加此功能的机制尚不清楚。 XML中有一些示例,但是使用DSL我看不到任何示例。
我还想确保 ProcessBeforeCommit 在读取数据库时发生,而不是在处理之后发生……是吗?另外,如果这不是设计从Mongo集合中读取的解决方案的最佳方法,请随时提出更好的体系结构。
答案 0 :(得分:1)
否,ProcessBeforeCommit
和ProcessAfterCommit
是非常接近的回调。它们肯定会在您的过程结束时发生。让我们考虑一下您有一种方法:
@Transactional
void foo() {}
当您调用这样的方法时,事务将在输入方法主体之前 开始。
当我们在方法主体执行后退出时,将执行 beforeCommit 回调。它可能会失败,因为在我们的过程中可能会丢失外部连接(DB?)。并且只有在可以的情况下,我们才能继续进行afterCommit
。
您可以通过AbstractMessageSourceAdvice
实现https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-channels-section.html#conditional-pollers来完成您的要求。因此,在afterReceive()
实现中,您可以将文档更新为PROCESSING
,甚至决定返回null
而不是消息:仅仅是因为它在数据库中的状态已经为{{1} }。可以将这样的PROCESSING
注入Advice
中:
PollerSpec
/**
* Specify AOP {@link Advice}s for the {@code pollingTask}.
* @param advice the {@link Advice}s to use.
* @return the spec.
*/
public PollerSpec advice(Advice... advice) {
和DONE
实际上可以通过将FAILED
应用于TransactionSynchronizationFactoryBean
来实现:
PollerSpec