Scala 尝试为自定义有状态实现提取GraphStageLogic,然后将其作为参数传递给GraphStage是一个异常
下面是简化的代码段,其中GraphStateLogic实现作为构造函数参数传递给GraphStage:-Scala 尝试为自定义有状态实现提取GraphStageLogic,然后将其作为参数传递给GraphStage是一个异常,scala,exception,akka,akka-stream,Scala,Exception,Akka,Akka Stream,下面是简化的代码段,其中GraphStateLogic实现作为构造函数参数传递给GraphStage:- package akka.shapes.examples.notworking import akka.actor.ActorSystem import akka.stream._ import akka.stream.scaladsl.{GraphDSL, RunnableGraph, Sink, Source} import akka.stream.stage.{GraphStage,
package akka.shapes.examples.notworking
import akka.actor.ActorSystem
import akka.stream._
import akka.stream.scaladsl.{GraphDSL, RunnableGraph, Sink, Source}
import akka.stream.stage.{GraphStage, GraphStageLogic, InHandler}
//This is base graph stage, where GraphStageLogic and SinkShape are passed in constructor parameter
class BaseGraphStage[T](val shape: SinkShape[T], graphStageLogic: GraphStageLogic) extends GraphStage[ SinkShape[T] ] {
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = graphStageLogic
}
//this is a sample stateful extension of GraphStageLogic, that accepts first ten elements only
class CountLogic(sinkShape: SinkShape[Int], maxValue: Int) extends GraphStageLogic(sinkShape) {
var counter: Long = 0
override def preStart(): Unit = {
pull(sinkShape.in)
}
setHandler(sinkShape.in, new InHandler {
override def onPush(): Unit = {
val e = grab(sinkShape.in)
println("conditional sink : " + e)
counter = counter + 1
counter == maxValue match {
case true => completeStage()
case false => pull(sinkShape.in)
}
}
})
}
object SampleSinkNotWorking {
def main(args: Array[String]): Unit = {
implicit val actorSystem = ActorSystem("NotWroking")
implicit val actorMaterializer = ActorMaterializer()
val inlet = Inlet[Int](name = "sampleInlet")
val sinkShape = SinkShape( inlet )
val countGraphStateLogic = new CountLogic(sinkShape, 10)
val sinkGraphStage = new BaseGraphStage[Int](sinkShape, countGraphStateLogic)
val sink = Sink.fromGraph( sinkGraphStage )
val graph = GraphDSL.create() { implicit builder =>
import GraphDSL.Implicits._
Source(1 to 100) ~> sink
ClosedShape
}
val runnableGraph = RunnableGraph.fromGraph(graph)
runnableGraph.run()
}
}
运行上述代码会导致ArrayIndexOutOfBoundsException:-
线程“main”java.lang.ArrayIndexOutOfBoundsException中的异常:
-1在akka.stream.stage.GraphStageLogic.setHandler(GraphStage.scala:439)在
akka.shapes.examples.notworking.CountLogic.(SampleSinkNotWorking.scala:24)
在
akka.shapes.examples.notworking.SampleSinkNotWorking$.main(SampleSinkNotWorking.scala:46)
在
akka.shapes.examples.notworking.SampleSinkNotWorking.main(SampleSinkNotWorking.scala)
我试过调试,看起来入口id是-1,但没有重置
但是,当GraphStateLogic作为构造函数参数传递给GraphState时,为什么它没有被重置呢?我正在重构您的代码,问题已经解决,请看:
类BaseGraphStage(maxValue:Int)扩展了GraphStage[SinkShape[Int]]{
val入口=入口[Int](name=“sampleInlet”)
重写def createLogic(继承的属性:属性):GraphStageLogic=
带有分段图的新GraphStageLogic(shape){
变量计数器:Int=0
设置处理器(入口,新入口处理器{
覆盖def onPush():单位={
val e=抓斗(入口)
日志信息(s“$e已消耗”)
计数器+=1
如果(计数器==最大值){
完成测试()
}否则{
牵引(入口)
}
}
})
覆盖def preStart():单位=
牵引(入口)
覆盖def postStop():单位=
计数器=0
}
覆盖def形状:SinkShape[Int]=SinkShape(入口)
}
对象示例SinkNotWorking{
def main(参数:数组[字符串]):单位={
隐式val actorSystem=actorSystem(“不工作”)
隐式val-actorMaterializer=actorMaterializer()
val sink=sink.fromGraph(新BaseGraphStage(10))
源(1到100)。运行时使用(接收器)
}
}
我不能完全回答您的最后一个问题,但我认为所有的技巧都是在graph阶段的上下文中创建入口,而不是从中创建入口,并使用pre和post处理程序。希望这能有所帮助。我正在重构您的代码,问题已经解决,请看:
类BaseGraphStage(maxValue:Int)扩展了GraphStage[SinkShape[Int]]{
val入口=入口[Int](name=“sampleInlet”)
重写def createLogic(继承的属性:属性):GraphStageLogic=
带有分段图的新GraphStageLogic(shape){
变量计数器:Int=0
设置处理器(入口,新入口处理器{
覆盖def onPush():单位={
val e=抓斗(入口)
日志信息(s“$e已消耗”)
计数器+=1
如果(计数器==最大值){
完成测试()
}否则{
牵引(入口)
}
}
})
覆盖def preStart():单位=
牵引(入口)
覆盖def postStop():单位=
计数器=0
}
覆盖def形状:SinkShape[Int]=SinkShape(入口)
}
对象示例SinkNotWorking{
def main(参数:数组[字符串]):单位={
隐式val actorSystem=actorSystem(“不工作”)
隐式val-actorMaterializer=actorMaterializer()
val sink=sink.fromGraph(新BaseGraphStage(10))
源(1到100)。运行时使用(接收器)
}
}
我不能完全回答您的最后一个问题,但我认为所有的技巧都是在graph阶段的上下文中创建入口,而不是从中创建入口,并使用pre和post处理程序。希望有帮助