Java反应器流量未按预期映射

时间:2018-11-16 15:31:48

标签: java spring-boot project-reactor

我为演示应用程序进行了以下设置:

  • mongodb包含2个集合:1个包含加密货币,1个包含这些加密货币的汇率
  • spring webflux项目使用服务器已发送事件获取这些汇率的实时更新

我有一个服务,该服务根据加密货币集合中存在的货币返回Flux中的List<CryptoCurrencyRateDTO>。我会为每种货币生成随机汇率,并将其流式传输到Web客户端。

服务是这样的:

@Service
public class CryptoCurrencyRateService {
  @Autowired private CryptoCurrencyRateRepository rateRepository;
  @Autowired private CryptoCurrencyRepository currencyRepository;

  // constructor

  public Flux<List<CryptoCurrencyRateDTO>> realtimeRates() {
    return currencyRepository.findAll()
      .map(CryptoCurrency::getSymbol)
      .flatMap(rateRepository::findTopBySymbolOrderByTimestamp)
      .zipWith(
        Flux.<Long>generate(sink -> sink.next(Instant.now().toEpochMilli())),
        (rate, timestamp) -> new CryptoCurrencyRate(rate.getSymbol(), timestamp, randomRateBasedOnPrevious )
      )
      .flatMap(rateRepository::save)
      .map(rateMapper::toDto)
      .collectList()
      .delayElement(Duration.ofSeconds(5))
      .repeat();
  }
}

CryptoCurrencyRateRepository如下:

@Repository
public interface CryptoCurrencyRateRepository extends ReactiveMongoRepository<CryptoCurrencyRate, String> {
    Mono<CryptoCurrencyRate> findTopBySymbolOrderByTimestamp(String symbol);
}

但是,在调用.flatMap(rateRepository::findTopBySymbolOrderByTimestamp)之后,我只得到一个包含1个项目的Flux,而我想我会得到一个Flux,其中包含{{1} }致电,因为我的加密货币集合包含3种货币。

当我查看日志记录时,发现对currencyRepository.findAll().map(CryptoCurrency::getSymbol)的调用已执行了3次

findTopBySymbolOrderByTimestamp

2 个答案:

答案 0 :(得分:1)

我无法重现您的问题。这就是我模仿的方式

public static void main(String[] args) {
    Flux<String> stringFlux = Flux.fromStream(Stream.of("a", "b", "c"));
    System.out.println(realtimeRates(stringFlux).blockFirst());
}

static Flux<List<String>> realtimeRates(Flux<String> list) {
    Flux<String> symbols = list.map(Scratch::getSymbol);
    Flux<String> topRates = symbols.flatMap(Scratch::findTopBySymbolOrderByTimestamp);
    Flux<String> zip = topRates.zipWith(
        Flux.<Long>generate(sink -> sink.next(Instant.now().toEpochMilli())),
        (rate, timestamp) -> rate + timestamp.toString());
    Mono<List<String>> listMono = zip.collectList();
    Mono<List<String>> delayElement = listMono.delayElement(Duration.ofSeconds(5));
    Flux<List<String>> repeat = delayElement.repeat();
    return repeat;
}

static Mono<String> findTopBySymbolOrderByTimestamp(String symbol) {
    return Mono.just("other-" + symbol);
}

static String getSymbol(String rate) {
    return rate.toLowerCase();
}

如您所见,您将得到类似[other-a1542821666133, other-b1542821666133, other-c1542821666133]的信息。

您如何检查平面图结果?请注意,如果您使用blockFirst()blockLast()方法执行此操作,您将仅获得一个元素,因为其元素为Flux<String>(请检查上面代码中的topRates变量)< / p>

答案 1 :(得分:0)

看来我的期望是正确的。唯一出问题的是并非所有对象都丢失了,因为它们缺少ID。