可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to use the Source.actorRef method to create an akka.stream.scaladsl.Source object. Something of the form
import akka.stream.OverflowStrategy.fail import akka.stream.scaladsl.Source case class Weather(zip : String, temp : Double, raining : Boolean) val weatherSource = Source.actorRef[Weather](Int.MaxValue, fail) val sunnySource = weatherSource.filter(!_.raining) ...
My question is: how do I send data to my ActorRef based Source object?
I assumed sending messages to the Source was something of the form
//does not compile weatherSource ! Weather("90210", 72.0, false) weatherSource ! Weather("02139", 32.0, true)
But weatherSource
doesn't have a !
operator or tell
method.
The documentation isn't too descriptive on how to use Source.actorRef, it just says you can...
Thank you in advance for your review and response.
回答1:
You need a Flow
:
import akka.stream.OverflowStrategy.fail import akka.stream.scaladsl.Source import akka.stream.scaladsl.{Sink, Flow} case class Weather(zip : String, temp : Double, raining : Boolean) val weatherSource = Source.actorRef[Weather](Int.MaxValue, fail) val sunnySource = weatherSource.filter(!_.raining) val ref = Flow[Weather] .to(Sink.ignore) .runWith(sunnySource) ref ! Weather("02139", 32.0, true)
Remember this is all experimental and may change!
回答2:
As @Noah points out the experimental nature of akka-streams, his answer might not work with the 1.0 release. I had to follow the example given by this example:
implicit val materializer = ActorMaterializer() val (actorRef: ActorRef, publisher: Publisher[TweetInfo]) = Source.actorRef[TweetInfo](1000, OverflowStrategy.fail).toMat(Sink.publisher)(Keep.both).run() actorRef ! TweetInfo(...) val source: Source[TweetInfo, Unit] = Source[TweetInfo](publisher)
回答3:
Instance of ActorRef
, like all 'materialized values', will become accessible only once whole stream is materialized, or, in other words, when RunnableGraph is being run.
// RunnableGraph[ActorRef] means that you get ActorRef when you run the graph val rg1: RunnableGraph[ActorRef] = sunnySource.to(Sink.foreach(println)) // You get ActorRef instance as a materialized value val actorRef1: ActorRef = rg1.run() // Or even more correct way: to materialize both ActorRef and future to completion // of the stream, so that we know when we are done: // RunnableGraph[(ActorRef, Future[Done])] means that you get tuple // (ActorRef, Future[Done]) when you run the graph val rg2: RunnableGraph[(ActorRef, Future[Done])] = sunnySource.toMat(Sink.foreach(println))(Keep.both) // You get both ActorRef and Future[Done] instances as materialized values val (actorRef2, future) = rg2.run() actorRef2 ! Weather("90210", 72.0, false) actorRef2 ! Weather("02139", 32.0, true) actorRef2 ! akka.actor.Status.Success("Done!") // Complete the stream future onComplete { /* ... */ }