[英]How to return a Reactive Flux that contains a Reactive Mono and Flux?
[英]How to reassign a variable in reactive Flux stream?
我正在向 Web 服务发送请求,将结果转换为大型csv
并将 csv 行保存到数据库中。
由于请求长时间运行(10-20 秒),我想并行化请求。 我在单个StringBuilder
中收集所有数据,该 StringBuilder 包含转换后的 csv 行。
问题:如果在 csv 中达到了我的 1000 行块,我怎样才能将数据取出以进行持久化,而任何其他并发响应都将写入新的StringBuilder
?
因为,无法重新初始化 stream 的最终变量。
final StringBuilder sb = new StringBuilder();
AtomicInteger count = new AtomicInteger();
Flux.fromIterable(requests)
.flatMap(req -> {
return webClientService.send(req); //assume long running response
}, 8) //send 8 requests in parallel, as response takes up to 10s
.map(rsp -> {
//convert response to csv values and add to StringBuilder
int c = addCsv(sb, rsp);
if (count.addAndGet(c) > 1000) {
//TODO how can I assign a new StringBuilder,
//so that all further finished responses will append the csv to the new builder?
//same problem with the counter.
databaseWriter.write(sb.build()); //writes the content so far to db, but not threadsafe so far
}
return c;
})
.blockLast();
也许您可以尝试完全避免副作用,例如:
.map(x -> toCsv(x))
.reduce((a, b) -> {
if (length(a) < 1000) {
return concat(a, b);
}
databaseWriter.write(a);
return b;
})
.doOnNext(x -> databaseWriter.write(x))
在我看来,您可以使用内置运算符来实现相同的结果:
Flux.fromIterable(requests)
.flatMap(req -> webClientService
.send(req)
.subscribeOn(Schedulers.boundedElastic()), 8)// subscribeOn to subscribe from different threads
.map(resp -> converToCsvLine(resp)) //make some transformations on the respnse
.window(1000) //split incoming data into 1000 lines
.flatMap(stringFlux -> stringFlux.collect(Collectors.joining("\n")))// collect last 1000
.flatMap(s -> Mono.fromRunnable(() -> writeToDb(s))) //do some logic on the collected 1000 lines
.blockLast();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.