This is meant to be a bidirectional flow BidiFlow that works exactly as BidiFlow.identity
, except that it completes the stage as soon as one of the Flows (in1 -> out1 or in2 -> out2) is completed.
This can be useful to automatically close a connection fully when one of the two sides is closed.
There are a few tricks to prevent object allocation.
import akka.stream.{ Outlet, Inlet, Attributes, BidiShape }
import akka.stream.stage._
object DisconnectBidiFlow {
def apply[A, B]: GraphStage[BidiShape[A, A, B, B]] = Impl.asInstanceOf[GraphStage[BidiShape[A, A, B, B]]]
private object Impl extends GraphStage[BidiShape[Any, Any, Any, Any]] {
val in1: Inlet[Any] = Inlet("DisconnectBidiFlow.in1")
val out1: Outlet[Any] = Outlet("DisconnectBidiFlow.out1")
val in2: Inlet[Any] = Inlet("DisconnectBidiFlow.in2")
val out2: Outlet[Any] = Outlet("DisconnectBidiFlow.out2")
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) {
def map[T](in: Inlet[T], out: Outlet[T]) = {
val handler = new InHandler with OutHandler {
override def onPush(): Unit =
push(out, grab(in))
override def onPull(): Unit =
pull(in)
}
setHandler(in, handler)
setHandler(out, handler)
}
map(in1, out1)
map(in2, out2)
}
override def shape = BidiShape(in1, out1, in2, out2)
}
}
Questions:
- Can/should the shape be a val
- Suggestions for a better name.
- It is not really a
BidiFlow
but just shaped like one. It is aGraphStage[BidiShape[A, A, B, B]]
- Should the name contain the purpose (FullDisconnectBidiFlow?)
- It is not really a