如何逃离“延续地狱”?

问题描述 投票:0回答:1

我目前正在使用 quarkus 编写一个响应式 Web 应用程序。每隔一段时间,我就会发现自己陷入了一种我称之为“连续地狱”的境地,我将多个调用链接到数据库,直到获得响应所需的所有数据。

以一个端点为例,该端点从三个 Panache 实体

Foo
Bar
Baz
读取数据,并使用这些实体的数据创建一个
MyDto
实例。对于这个端点,我会编写如下代码:

@GET
public Uni<MyDto> get(@QueryParam("criteria") String someCriteria) {
  return Foo.findBySomeCriteria(someCriteria)
          .chain(foo -> Bar.findBySomeCriteria(someCriteria)
            .chain(bar -> Baz.findBySomeCriteria(someCriteria)
              .map(baz -> new MyDto(
                foo.value,
                bar.value,
                baz.value
              ))
            )
          );
}

虽然这是一个微不足道的示例,但我已经将一些重要的缩进和样板代码与我的(最小)业务逻辑混合在一起。这使得代码难以阅读。当我添加错误处理或特殊情况时,它只会变得更糟糕。

不幸的是,我无法合并 Panache 返回的

Uni
。这会给我一个
IllegalStateException
,并显示以下消息:“非法 pop() 与不匹配的 JdbcValuesSourceProcessingState”,因为不可能在反应式 Hibernate 会话上同时启动两个操作。否则,解决方案可能如下所示:

@GET
public Uni<MyDto> get(@QueryParam("criteria") String someCriteria) {
  // This does not work !!!
  Uni<Foo> fooUni = Foo.findBySomeCriteria(someCriteria);
  Uni<Bar> barUni = Bar.findBySomeCriteria(someCriteria);
  Uni<Baz> bazUni = Baz.findBySomeCriteria(someCriteria);
  
  return Uni.combine().all().unis(fooUni, barUni, bazUni)
    .with((foo, bar, baz) -> new MyDto(
      foo.value,
      bar.value,
      baz.value
    ));
}

那么有什么好方法可以逃离这个“持续地狱”呢?

quarkus quarkus-reactive
1个回答
0
投票

在更详细地检查 Mutiny Reference 后,我发现在组合

Uni
时可以限制并发上游订阅的数量。通过将并发设置为
1
,上游
Uni
将顺序执行,从而避免了与Hibernate相关的问题。不幸的是,这种方法意味着我们丢失了有关元素的类型信息,因此我们需要在订阅中重新创建它。

因此,组合

Uni
的第二个示例将像这样工作:

@GET
public Uni<MyDto> get(@QueryParam("criteria") String someCriteria) {
  Uni<Foo> fooUni = Foo.findBySomeCriteria(someCriteria);
  Uni<Bar> barUni = Bar.findBySomeCriteria(someCriteria);
  Uni<Baz> bazUni = Baz.findBySomeCriteria(someCriteria);
  
  return Uni.combine().all().unis(fooUni, barUni, bazUni)
    .usingConcurrencyOf(1)
    .with(results -> new MyDto(
      ((Foo) result.get(0)).value,
      ((Bar) result.get(1)).value,
      ((Baz) result.get(2)).value
    ));
}

除了类型问题之外,这正是我正在寻找的。

© www.soinside.com 2019 - 2024. All rights reserved.