处理Project反应器中的ListenableFuture

时间:2017-03-08 19:08:26

标签: project-reactor

我已经开始玩项目反应堆了,并希望将我们的API之一移动到被动的做事方式。我想知道什么是处理像ListenableFuture这样的东西。

就我而言,我正在使用Cassandra,当我调用session.executeAsync()时,这会返回一个ResultSetFuture,它扩展了ListenableFuture。 下面是我现在编写的代码示例,我似乎并不满意将ListenableFuture暴露给客户。

public Mono<ListenableFuture<Void> save(Publisher<AccountDTO> accountPublisher) {
 return Mono.just(accountPublisher)
.map(accountDTO -> {
                Account accountEntity = modelMapper.map(accountDTO, Account.class);
                return mappingManager.mapper(Account.class).saveAsync(accountEntity);
            })
            .retry(1)
            .doOnError(throwable -> log.error("Unable to create account "))
            .mapError(throwable -> new MyCustomException("")

}

我的问题是,暴露ListenableFuture是一个好习惯,我个人不想把这样的东西送回他们可以阻止的客户端。有没有更好的方法在项目反应堆中处理这个问题,我可以返回Mono?

4 个答案:

答案 0 :(得分:3)

您可以使用ListenableFuture<Void>工厂方法轻松桥接Mono<Void>异步API,而不是公开Mono.create()。该方法采用Consumer<Sink>,您将其作为lambda提供:

  1. 为调用sink.success()的未来添加成功侦听器(因为没有实际值,或者您也可以使用侦听器收到的success(aVoid)值调用Void
  2. 向未来调用sink.error(failure)
  3. 添加失败侦听器

    这就是它!请参阅create上的参考文档(尽管有人提到Flux版本,由于必须处理多个值而稍微复杂一点):http://projectreactor.io/docs/core/release/reference/docs/index.html#producing.create

答案 1 :(得分:1)

发布我在@Simon上面指导编码的代码段。

 @Override
    public void onTaskTypePick()
    {
        getSupportFragmentManager().popBackStack();
    }

答案 2 :(得分:0)

在使用lambdas的Java 8中,如果您正在寻找Simon使用ListenableFutures创建Flux的答案的实现,

Flux.create(fluxSink -> {
            future.addCallback(
                    result -> {
                        fluxSink.next(result);
                        fluxSink.complete();
                    },
                    ex -> fluxSink.error(ex));
        });

答案 3 :(得分:0)

由于这篇文章比较老,两个库的API都已经成熟,可以提供一种更简单的解决方案。

一个人可以简单地将library Sheetfudefault CompletableFuture completable()结合使用。

这里是改编自public static Mono fromFuture(CompletableFuture<? extends T> future)

的示例
public void sendToKafka(final MyOutputData data) {
  final ProducerRecord<String, String> record = createRecord(data);

  CompletableFuture<SendResult<Integer, String>> future = template.send(record).completable();
  
  Mono<SendResult<Integer, String>> mono = Mono.fromFuture(future)
    .doOnSuccess((result) ->  handleSuccess(data))
    .doOnError((ex) -> handleFailure(data, record, ex))
    .doFinally((signalType) -> { if(signalType == SignalType.CANCEL) future.cancel(true); });
  
  mono.subscribe();
}

Spring for Apache Kafka

请注意,取消Mono时,未来不会取消,但是可以通过使用Note from Reactor JavaDocs来检查doFinally(Consumer)并调用SignalType.CANCEL来获得该行为。