=str #16957 Refactor actor creation api for sinks and sources

* also solves #16952, dispatcher for ActorPublisher
This commit is contained in:
Patrik Nordwall 2015-04-10 14:39:48 +02:00
parent 386ff80a0e
commit 4fcd3d0392
7 changed files with 149 additions and 67 deletions

View file

@ -19,17 +19,6 @@ import org.reactivestreams._
import scala.concurrent.{ Await, ExecutionContextExecutor }
object ActorFlowMaterializerImpl {
import OperationAttributes._
private[akka] def calcSettings(opAttr: OperationAttributes)(settings: ActorFlowMaterializerSettings): ActorFlowMaterializerSettings =
opAttr.attributes.collect {
case InputBuffer(initial, max) (s: ActorFlowMaterializerSettings) s.withInputBuffer(initial, max)
case Dispatcher(dispatcher) (s: ActorFlowMaterializerSettings) s.withDispatcher(dispatcher)
case SupervisionStrategy(decider) (s: ActorFlowMaterializerSettings)
s.withSupervisionStrategy(decider)
}.reduceOption(_ andThen _).getOrElse((x: ActorFlowMaterializerSettings) x)(settings) // FIXME is this the optimal way of encoding this?
}
/**
* INTERNAL API
*/
@ -43,12 +32,24 @@ private[akka] case class ActorFlowMaterializerImpl(override val settings: ActorF
import ActorFlowMaterializerImpl._
import akka.stream.impl.Stages._
def withNamePrefix(name: String): FlowMaterializer = this.copy(namePrefix = name)
override def withNamePrefix(name: String): FlowMaterializer = this.copy(namePrefix = name)
private[this] def nextFlowNameCount(): Long = flowNameCounter.incrementAndGet()
private[this] def createFlowName(): String = s"$namePrefix-${nextFlowNameCount()}"
override def effectiveSettings(opAttr: OperationAttributes): ActorFlowMaterializerSettings = {
import OperationAttributes._
opAttr.attributes.foldLeft(settings) { (s, attr)
attr match {
case InputBuffer(initial, max) s.withInputBuffer(initial, max)
case Dispatcher(dispatcher) s.withDispatcher(dispatcher)
case SupervisionStrategy(decider) s.withSupervisionStrategy(decider)
case Name(_) s
}
}
}
override def materialize[Mat](runnableFlow: Graph[ClosedShape, Mat]): Mat = {
runnableFlow.module.validate()
@ -63,23 +64,26 @@ private[akka] case class ActorFlowMaterializerImpl(override val settings: ActorF
override protected def materializeAtomic(atomic: Module, effectiveAttributes: OperationAttributes): Any = {
def newMaterializationContext() = new MaterializationContext(ActorFlowMaterializerImpl.this,
effectiveAttributes, stageName(effectiveAttributes))
atomic match {
case sink: SinkModule[_, _]
val (sub, mat) = sink.create(ActorFlowMaterializerImpl.this, stageName(effectiveAttributes))
val (sub, mat) = sink.create(newMaterializationContext())
assignPort(sink.shape.inlet, sub.asInstanceOf[Subscriber[Any]])
mat
case source: SourceModule[_, _]
val (pub, mat) = source.create(ActorFlowMaterializerImpl.this, stageName(effectiveAttributes))
val (pub, mat) = source.create(newMaterializationContext())
assignPort(source.shape.outlet, pub.asInstanceOf[Publisher[Any]])
mat
case stage: StageModule
val (processor, mat) = processorFor(stage, effectiveAttributes, calcSettings(effectiveAttributes)(settings))
val (processor, mat) = processorFor(stage, effectiveAttributes, effectiveSettings(effectiveAttributes))
assignPort(stage.inPort, processor)
assignPort(stage.outPort, processor)
mat
case junction: JunctionModule materializeJunction(junction, effectiveAttributes, calcSettings(effectiveAttributes)(settings))
case junction: JunctionModule materializeJunction(junction, effectiveAttributes, effectiveSettings(effectiveAttributes))
}
}
@ -166,13 +170,17 @@ private[akka] case class ActorFlowMaterializerImpl(override val settings: ActorF
session.materialize().asInstanceOf[Mat]
}
lazy val executionContext: ExecutionContextExecutor = dispatchers.lookup(settings.dispatcher match {
override lazy val executionContext: ExecutionContextExecutor = dispatchers.lookup(settings.dispatcher match {
case Deploy.NoDispatcherGiven Dispatchers.DefaultDispatcherId
case other other
})
private[akka] def actorOf(props: Props, name: String): ActorRef =
actorOf(props, name, settings.dispatcher)
override def actorOf(context: MaterializationContext, props: Props): ActorRef = {
val dispatcher =
if (props.deploy.dispatcher == Deploy.NoDispatcherGiven) effectiveSettings(context.effectiveAttributes).dispatcher
else props.dispatcher
actorOf(props, context.stageName, dispatcher)
}
private[akka] def actorOf(props: Props, name: String, dispatcher: String): ActorRef = supervisor match {
case ref: LocalActorRef
@ -237,11 +245,11 @@ private[akka] object ActorProcessorFactory {
private val _identity = (x: Any) x
def props(materializer: ActorFlowMaterializerImpl, op: StageModule, parentAttributes: OperationAttributes): (Props, Any) = {
def props(materializer: ActorFlowMaterializer, op: StageModule, parentAttributes: OperationAttributes): (Props, Any) = {
val att = parentAttributes and op.attributes
// USE THIS TO AVOID CLOSING OVER THE MATERIALIZER BELOW
// Also, otherwise the attributes will not affect the settings properly!
val settings = calcSettings(att)(materializer.settings)
val settings = materializer.effectiveSettings(att)
op match {
case Identity(_) (ActorInterpreter.props(settings, List(fusing.Map(_identity, settings.supervisionDecider)), materializer), ())
case Fused(ops, _) (ActorInterpreter.props(settings, ops, materializer), ())