Akka流流从`failStage`恢复

时间:2018-03-15 20:51:40

标签: scala akka akka-stream akka-http

GraphStage取自https://stackoverflow.com/a/40962834/772249,看起来像这样。它作为WebSocket服务器工作:

class TerminateFlowStage[T](
                             predicate: T => Boolean,
                             forwardTerminatingMessage: Boolean = false,
                             terminate: Boolean = true)
  extends GraphStage[FlowShape[T, T]]
{
  val in = Inlet[T]("TerminateFlowStage.in")
  val out = Outlet[T]("TerminateFlowStage.out")
  override val shape = FlowShape.of(in, out)

  override def createLogic(inheritedAttributes: Attributes): GraphStageLogic =
    new GraphStageLogic(shape) {

      setHandlers(in, out, new InHandler with OutHandler {
        override def onPull(): Unit = { pull(in) }

        override def onPush(): Unit = {
          val chunk = grab(in)

          if (predicate(chunk)) {
            if (forwardTerminatingMessage) {
              push(out, chunk)
            }
            if (terminate) {
              failStage(new RuntimeException("Flow terminated by TerminateFlowStage"))
            } else {
              completeStage()
            }
          } else {
            push(out, chunk)
          }
        }
      })
    }
}

val termOnKillMe = new TerminateFlowStage[Message]((chunk: Message) => chunk match {
case TextMessage.Strict(text) => text.toInt > 5
case _ => false
})

val route =
path("") {
    get {
    extractUpgradeToWebSocket {
        upgrade =>
        complete(upgrade.handleMessagesWithSinkSource(
            Sink.ignore,
            Source(1 to 10).
            map(i => TextMessage(i.toString)).throttle(1, 1.second, 1, ThrottleMode.shaping).via(termOnKillMe)
        ))
    }
    }
}

因此,在5条消息之后,WebSocket服务器断开连接。

我为WebSocket客户端提供了这个流程:

  val flow: Flow[Message, Message, Future[Seq[Message]]] =
    Flow.fromSinkAndSourceMat(
      Sink.seq[Message],
      Source.maybe[Message])(Keep.left)

  val (upgradeResponse, promise) =
    Http().singleWebSocketRequest(
      WebSocketRequest("ws://localhost:8080/"),
      flow.recoverWithRetries(1, {
        case _ => Source.empty
      })
    )

问题是,WebSocket客户端流无法从TerminateFlowStage引发的异常中恢复。获得Future(Failure(akka.http.scaladsl.model.ws.PeerClosedConnectionException: Peer closed connection with code 1011 'internal error'))

无一例外地提出,一切都很好。

0 个答案:

没有答案