简体   繁体   English

在Akka Stream中抛出异常的最佳做法是什么 - Scala?

[英]What is the best practice for throwing exceptions inside an Akka Stream - Scala?

I am new to Akka Stream and trying to figure out what is the best practice for handling unexpected behaviors inside a stream. 我是Akka Stream的新手,并试图弄清楚在流中处理意外行为的最佳做法是什么。

I am building a stream which uses Account Kit API to exchange short-term code to a long-live access token. 我正在构建一个使用Account Kit API将短期代码交换为长期访问令牌的流。

Here is the relevant code for building the stream: 以下是构建流的相关代码:

override def ExchangeCode: Flow[String, AccessTokenInfo, NotUsed] =
Flow[String].mapAsync(1) { code =>
  ws.url(buildUrl("access_token"))
    .withQueryString(
      "grant_type" -> "authorization_code",
      "code" -> code,
      "access_token" -> appToken
    )
    .withRequestTimeout(timeout)
    .get
    .map { response =>
      if (response.status != 200) throw new RuntimeException("Unexpected response")
      else response.json
    }
    .map { json =>
      AccessTokenInfo("123456", 123, "123456")
    }
}

I wonder if throwing an exception if status code is not 200 is the right way to deal with it, but this is the only way of terminating a stream ahead of time as I know it. 我想知道如果状态代码不是200就抛出异常是处理它的正确方法,但这是我知道它提前终止流的唯一方法。 (Currently the return value is a dummy one) (目前返回值是虚拟的)

Why is it a strict necessity that the stream terminate if the status is not 200? 如果状态不是200,为什么流终止是非常必要的? Usually you want to send even the failures downstream so any user of the Flow can be informed and act accordingly. 通常您希望甚至向下游发送故障,因此可以通知Flow任何用户并采取相应措施。

The typical way of dealing with this type of failure is with Try . 处理此类故障的典型方法是使用Try Slightly modifying your Flow: 略微修改你的流程:

//                                  Add Try Output
//                                       |
//                                       v
override def ExchangeCode: Flow[String, Try[AccessTokenInfo], _] = 
  Flow[String] 
    ...
    .map { response => response.status match {
        case 200 => Try { response.json }
        case _   => Try { throw new RuntimeException("Unexpected Response") }
      }
    }
    .map( _ map (json => AccessTokenInfo("123456", 123, "123456")))

Now any user of the flow can get the valid access token if it was possible to retrieve or get the Exception and be able to handle the failure case. 现在,如果可以检索或获取异常并且能够处理故障情况,则流的任何用户都可以获得有效的访问令牌。

Option when there's only 1 Failure Type 当只有1种故障类型时的选项

In the particular use case of the question a Try doesn't even seem to be necessary. 在问题的特定用例中, Try似乎甚至没有必要。 Since there is only 1 Exception that can be generated by only 1 cause an Option seems better: 由于只有1个Exception可以仅由1生成,因此Option似乎更好:

override def ExchangeCode: Flow[String, Option[AccessTokenInfo], _] = 
  ...
        case 200 => Some(response.json)
        case _   => None
  ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM