#scala #akka #akka-stream
#scala #akka #akka-stream
Вопрос:
У меня есть оператор / компонент в потоке Akka, который предназначен для вычисления значения в течение 5 секунд. Итак, я создал свой оператор / компонент, использование TimerGraphStageLogic
которого вы можете увидеть в приведенном ниже коде. Чтобы протестировать это, я создал 2 источника, один с увеличением, а другой с уменьшением, затем я объединяю их, используя Merge
форму, затем я использую my windowFlowShape
и, наконец, создаю их в Sink
форме. Я гарантирую, что TimerGraphStageLogic работает, потому что я тестировал его в другом PoC. В этом примере я просто заменяю общий тип T
на Int
, поскольку мне нужно указать, что будет агрегировать мое окно.
Однако моя проблема в том, что я не могу агрегировать Int
значения внутри оператора window stage. При попытке выполнить я получаю сообщение об ошибке во время выполнения sum = sum elem
, в котором говорится:
overloaded method value with alternatives:
(x: scala.Int)scala.Int <and>
(x: Char)scala.Int <and>
(x: Short)scala.Int <and>
(x: Byte)scala.Int
cannot be applied to (Int(in class WindowProcessingTimerFlow))
sum = sum elem
Вот мой код, который компилируется, но выдает указанную выше ошибку во время выполнения:
import akka.actor.ActorSystem
import akka.stream._
import akka.stream.scaladsl.{Flow, GraphDSL, Merge, RunnableGraph, Sink, Source}
import akka.stream.stage._
import scala.collection.mutable
import scala.concurrent.duration._
object StreamOpenGraphWindow {
def main(args: Array[String]): Unit = {
run()
}
def run() = {
implicit val system = ActorSystem("StreamOpenGraphWindow")
val sourceNegative = Source(Stream.from(0, -1)).throttle(1, 1 second)
val sourcePositive = Source(Stream.from(0)).throttle(1, 1 second)
// Step 1 - setting up the fundamental for a stream graph
val windowRunnableGraph = RunnableGraph.fromGraph(
GraphDSL.create() { implicit builder =>
import GraphDSL.Implicits._
// Step 2 - create shapes
val mergeShape = builder.add(Merge[Int](2))
val windowFlow = Flow.fromGraph(new WindowProcessingTimerFlow[Int](5 seconds))
val windowFlowShape = builder.add(windowFlow)
val sinkShape = builder.add(Sink.foreach[Int](x => println(s"sink: $x")))
// Step 3 - tying up the components
sourceNegative ~> mergeShape.in(0)
sourcePositive ~> mergeShape.in(1)
mergeShape.out ~> windowFlowShape ~> sinkShape
// Step 4 - return the shape
ClosedShape
}
)
// run the graph and materialize it
val graph = windowRunnableGraph.run()
}
// step 0: define the shape
class WindowProcessingTimerFlow[Int](silencePeriod: FiniteDuration) extends GraphStage[FlowShape[Int, Int]] {
// step 1: define the ports and the component-specific members
val in = Inlet[Int]("WindowProcessingTimerFlow.in")
val out = Outlet[Int]("WindowProcessingTimerFlow.out")
// step 3: create the logic
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new TimerGraphStageLogic(shape) {
// mutable state
val batch = new mutable.Queue[Int]
var open = false
// step 4: define mutable state implement my logic here
setHandler(in, new InHandler {
override def onPush(): Unit = {
try {
val nextElement = grab(in)
batch.enqueue(nextElement)
if (open) {
pull(in) // send demand upstream signal, asking for another element
} else {
var sum: scala.Int = 0
val set: Iterable[Int] = batch.dequeueAll(_ => true).to[collection.immutable.Iterable]
set.toList.foreach { elem =>
sum = sum elem // ************* WHY I CANNOT DO IT? *************
}
push(out, sum)
open = true
scheduleOnce(None, silencePeriod)
}
} catch {
case e: Throwable => failStage(e)
}
}
})
setHandler(out, new OutHandler {
override def onPull(): Unit = {
pull(in)
}
})
override protected def onTimer(timerKey: Any): Unit = {
open = false
}
}
// step 2: construct a new shape
override def shape: FlowShape[Int, Int] = FlowShape[Int, Int](in, out)
}
}
Ответ №1:
Потому что вы создаете параметр типа с именем Int
, который затеняет определение типа Int
, где определяется:
class WindowProcessingTimerFlow[Int](silencePeriod: FiniteDuration) extends GraphStage[FlowShape[Int, Int]] {
Попробуйте удалить из него общий:
class WindowProcessingTimerFlow(silencePeriod: FiniteDuration) extends GraphStage[FlowShape[Int, Int]] {