项目反应器:重复服务调用并收集响应结果,直到满足条件



问候尊敬的SO社区。。。

我今天来找每个需要一个反应式解决方案的人,解决我还没有遇到的问题。在这一点上,我仍然认为自己是一个反应迟钝的新手,尽管我一直在读";Hands-On Reactive Programming in Spring";如果你知道我的意思的话,我仍然有老板在看着我,轻拍他的脚,所以我再次希望一些仁慈而聪明的灵魂能为我目前的任务指明正确的方向。

情况如下:我必须调用一个外部服务,该服务提供给定日期范围的事务列表(包含事务数据(。除了在请求中传递给外部服务的日期范围外,还有每页的事务数,我们称之为";N";,和页码,我们将称之为";P";

因此,假设某个日期范围内共有23笔交易。

然后:

  • 对于N=10和P=1,他们将返回10个事务,从1-10
  • 对于N=10和P=2,我们将得到11-20的交易
  • 对于N=10和P=3,我们将得到21-23个交易
  • 对于N=10和P=4或更高,将不返回任何交易
  • 对于N=7和P=3,我们将得到15-21的交易
  • 对于N=30和P=1,我们将获得所有23个事务,并且知道我们拥有所有事务,因为返回的数量小于请求的数量

(请注意,我们不知道最终会返回多少交易记录。(

因此,我所追求的是某种反应式构造,它可能会重复调用远程事务列表服务,检查返回的总数是否小于请求的总数,如果不是,则在另一个列表中保存/累积所有记录的同时再次调用,然后当我们到达末尾时,将所有事务的另一个列表作为对调用此代码的服务的响应发送回。

这有道理吗?

我一直在搜索SO,到目前为止,我发现这篇文章似乎有点适用,并有望使用";重复";功能,但我真的不确定这是否是正确的路径。

我还发现了这篇文章,它似乎也很相关。

再次,一如既往,我们非常感谢这里的任何帮助/指导!

再次问候SO社区。

多亏了一位更有经验的同事的帮助,我终于想出了解决这个问题的办法。

public Flux<TransactionListData> getTransactionList(String cardId, TransactionLookupCriteria lookupCriteria) {
return cardService.getByCardId(cardId)
.map(Card::getAccountId)
.flatMap(accountService::getAccount)
.flatMap(account -> fetchTransactions(account, lookupCriteria))
.flatMapMany(Flux::fromIterable)
.map(this::negateTransactionAmountIfNecessary)
.map(this::setTransactionApprovalFlag);
}
private Mono<List<TransactionListData>> fetchTransactions(Account account,
TransactionLookupCriteria lookupCriteria) {
final PageNumber pageNumber = new PageNumber();
return Flux.defer(() -> getTransactions(account, lookupCriteria, pageNumber))
.repeatWhen(transactions -> transactions.takeWhile(transactionCount -> transactionCount == TRANSACTIONS_REQUESTED_PER_PAGE))
.collectList();
}
private Flux<TransactionListData> getTransactions(Account account, TransactionLookupCriteria lookupCriteria, PageNumber pageNumber) {
return Mono.just(createGetTransactionListServiceRequestData(account, lookupCriteria, pageNumber.get()))
.flatMap(cartaClient::getTransactionList)
.map(GetTransactionListServiceResponse::getServiceResponseData)
.switchIfEmpty(Mono.defer(() -> Mono.error(new ServiceException("Transaction response data empty"))))
.doOnNext(x -> pageNumber.increment())
.flatMapIterable(GetTransactionListServiceResponseData::getTransactionList);
}
private class PageNumber {
int page = 1;
void increment() {
page++;
}
public int get() {
return page;
}
}

最新更新