Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 流量数据依赖于流中稍后的数据,以寻求更好的模式_Java_Reactive Programming_Spring Webflux_Project Reactor - Fatal编程技术网

Java 流量数据依赖于流中稍后的数据,以寻求更好的模式

Java 流量数据依赖于流中稍后的数据,以寻求更好的模式,java,reactive-programming,spring-webflux,project-reactor,Java,Reactive Programming,Spring Webflux,Project Reactor,我对反应式编程非常陌生,但我正试图在Spring Boot应用程序中使用ProjectReactor的Flux/MonoAPI编写一些新代码 我有一个来自某个库的有限数据流(具有唯一ID) 流中的每个基准在流中都有一个“父”基准,该基准可能在之前已发出,或仍将发出 在将数据发送到另一个系统之前,我需要将其转换为包含父对象的对象 我必须要写 List data=library.getData() Map lookup=data.stream().collect(toMap(Datum::getId

我对反应式编程非常陌生,但我正试图在Spring Boot应用程序中使用ProjectReactor的Flux/MonoAPI编写一些新代码

  • 我有一个来自某个库的有限数据流(具有唯一ID)
  • 流中的每个基准在流中都有一个“父”基准,该基准可能在之前已发出,或仍将发出
  • 在将数据发送到另一个系统之前,我需要将其转换为包含父对象的对象
  • 我必须要写

    List data=library.getData()
    Map lookup=data.stream().collect(toMap(Datum::getId,Function.identity());
    List outData=data.stream()
    .map(d->OutDatum.builder()
    .id(d.getId)
    ...
    .parent(lookup.get(datum.getParent()))
    .build())
    .collect(toList());
    发送(输出数据);
    
    作为第一步我做了什么

  • 从数据中创建流量(目前从列表中发出,希望库以后能够以流式方式提供数据)
  • cache()
  • 基于创建查找映射的数据流创建另一个查找Mono
  • 使用数据流上的
    map()
    将基准转换为OutDatum,使用上面的查找Mono获取父数据
  • 将映射的数据流传递到WebClient以发送
  • 通量数据=emitAsFlux(库::getData) .cache(); Mono lookup=data.collectMap(数据::getId) .cache(); 发送(data.map(d->OutDatum.builder() .id(d.getId) ... .parent(lookup.block().get(d.getParent())) .build())
    我知道阻塞不是我们喜欢在反应式编程中看到的东西,但由于对映射的依赖性,它是必要的(据我的理解,因为cache()多次阻塞并不是有害的,但如果必要的话,我会在以后重构它)

    我这里的问题是它挂起。因为它们引用的是相同的原始流量,所以无法构建查找映射,因为不允许流量继续。出现了死锁。 我尝试使用
    share()
    创建代理流量,但似乎没有帮助

  • 当employee Flux仍在处理流中较早的元素时,是否有一种方法可以让Map耗尽流
  • 我很想知道什么是一个很好的模式来实现这个反应
  • 我还想知道我在哪里愚蠢或者看起来缺乏理解
  • FYI
    emitAsFlux
    看起来像这样:

    专用流量emitAsFlux(最终可调用数据提供程序){
    返回通量。创建(发射器->{
    taskExecutor.execute(()->{
    试一试{
    dataProvider.call()
    .forEach(发射器::下一个);
    emitter.complete();
    }捕获(例外e){
    误差(e);
    }
    });
    });
    }
    
    源库正在返回列表,这意味着它已经是一个阻塞代码

    不确定,但我猜,问题是由于以下代码引起的-

    .parent(lookup.block().get(d.getParent()))
    
    由于源代码已经可用,因为它是列表,不是被动的,所以我建议我们创建一个简单的映射来查找,而不是Mono而不是map

    您的命令式代码看起来不错,它的修改版本和响应式支持如下所示:

    List<Datum> data = library.getData()
    Map<String, Datum> lookup = data.stream().collect(toMap(Datum::getId, identity()));
    
    Flux<OutDatum> outData = Flux.fromIterable(data)
                                 .map(d -> OutDatum.builder()
                                                   .id(d.getId)
                                                   ...
                                                   .parent(lookup.get(datum.getParent()))
                                                   .build());
    send(outData); 
    
    List data=library.getData()
    Map lookup=data.stream().collect(toMap(Datum::getId,identity());
    通量输出数据=通量fromIterable(数据)
    .map(d->OutDatum.builder()
    .id(d.getId)
    ...
    .parent(lookup.get(datum.getParent()))
    .build());
    发送(输出数据);
    
    在send(outData)中,您可以将数据作为流量发送,如果您希望服务器以块的形式发送OutDatum,请使用TEXT\u EVENT\u STREAM内容类型

    关于改进,目前您的方法看起来不错,如果您认为-
    这里可以做的一个改进是关于源数据,它现在是非反应性的。也许在某个时候,我们可以使用反应性数据库作为父查找的源数据。但我不确定,这取决于用例。

    非常感谢。是的,我曾发表评论“希望库以后能够以流式方式提供数据”在我的帖子中。我想知道在传入数据是流的情况下应该做什么。我能想到的一种方法(不确定是否最好)。让流来,我们获取一个数据并在DB中运行查询,以反应性地再次获取父项。然后,我们可以进行监视。如果需要改进,我们可以在流的源处进行委托查找。例如,如果是分布式系统的事件,我们要求他们在事件中也包含父项。如果是数据库,则在我们的选择查询中,我们确实加入到f将父项和子项一起蚀刻。如果需要更多的改进,我们会像在NoSQL中一样将子项实体本身的部分父项信息保存在DB中。这些想法对您有用吗?