我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'))
无一例外地提出,一切都很好。