如何从另一个线程向函数抛出异常?

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

我遇到了一个非常奇怪的问题:基本上,我正在用Java实现服务器流式grpc客户端,并且我将微配置文件用作库/结构。当涉及到自动重试和回退时,Microprofiles具有非常方便的拦截器,但是它依赖于在带有拦截器注释的函数中引发的异常,否则不会触发重试。

对于一元grpc调用,这很好,它的工作原理与普通REST调用非常相似。但是,当使客户端成为grpc服务器端流时,protobuf将创建它自己的线程并请求回调以处理onNext,onError和onCompleted。因此,在流范围内调用onError时,抛出的任何异常都不会发送回用于启动流的任何函数,因此不会引发任何异常来触发@Retry。

无法更改异步流的处理方式,也无法更改@Retry的触发方式。 Grpc是生成的代码,并且@Retry触发器基于微配置文件库。

示例:

  @Retry(
          retryOn = {IOException.class, TimeoutException.class, StatusRuntimeException.class},
          maxDuration = 10,
          durationUnit =  ChronoUnit.SECONDS,
          maxRetries = 1,
          delay = 10,
          delayUnit = ChronoUnit.SECONDS
  )
  public void subscribeToLocations() {
    // --> Throwing an exception here triggers the @Retry <--
    SubscribeRequest locSubscribeRequest = SubscribeRequest.newBuilder().build();
    streamObserver = grpcStreamHandler();
    grpcBlockingstub.subscribeServerStreaming(locSubscribeRequest, streamObserver); // Can't change this.
  }

  private StreamObserver<SubscribeResponse> grpcStreamHandler() {
    return new StreamObserver<SubscribeResponse>() {
      @Override
      public void onNext(SubscribeResponse value) {
        // Handle grpc response
      }

      @Override
      public void onError(Throwable t) {
        // --> ERROR: Here, it should trigger the @Retry somehow. <--
      }

      @Override
      public void onCompleted() {
        // Handle oncomplete
      }
    };
  }

我试图找到解决方案的时间超过了我希望承认的时间,但是我仍然茫然。有没有一种方法可以在一个范围内引发一个异常,而该范围又在另一个范围内终止?还有其他解决方法吗?

java java-ee-6 grpc-java microprofile
1个回答
0
投票

您在此处混合了同步操作和异步操作,因此您需要为您明确定义什么是“成功”,并且不需要重试。它可能取决于您的逻辑,很少有流式传输选项:

  • 至少收到一次对onNext的更新,然后完成或出错
  • onCompleted收到,有或没有任何更新

一旦定义了“成功”规则,就可以将订阅包装到Future中,并等待提供的超时解决该订阅。如果未解决,则从原始调用中引发Exception。

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