Scala 只有在处理完所有消息后,才向Akka actor询问结果
我试图将一大块文本分割成多个段落,并通过调用外部API来并发处理它。 每次来自段落API的响应时,都会更新一个不可变列表 一旦段落被处理并且列表被更新,我想请求参与者在接下来的步骤中使用最终状态 以下方法的问题是,我永远不知道何时处理所有段落。 一旦所有段落都处理完毕并且列表是最终的,我需要返回targetStoreScala 只有在处理完所有消息后,才向Akka actor询问结果,scala,akka,actor,akka-http,akka-actor,Scala,Akka,Actor,Akka Http,Akka Actor,我试图将一大块文本分割成多个段落,并通过调用外部API来并发处理它。 每次来自段落API的响应时,都会更新一个不可变列表 一旦段落被处理并且列表被更新,我想请求参与者在接下来的步骤中使用最终状态 以下方法的问题是,我永远不知道何时处理所有段落。 一旦所有段落都处理完毕并且列表是最终的,我需要返回targetStore def main(args: Array[String]) { val source = Source.fromFile("input.txt")
def main(args: Array[String]) {
val source = Source.fromFile("input.txt")
val extDelegator = new ExtractionDelegator()
source.getLines().foreach(line => extDelegator.processParagraph(line))
extDelegator.getFinalResult()
}
case class Extract(uuid: UUID, text: String)
case class UpdateList(text: String)
case class DelegateLambda(text: String)
case class FinalResult()
class ExtractionDelegator {
val system = ActorSystem("ExtractionDelegator")
val extActor = system.actorOf(Props(classOf[ExtractorDelegateActor]).withDispatcher("fixed-thread-pool"))
implicit val executionContext = system.dispatchers.lookup("fixed-thread-pool")
def processParagraph(text: String) = {
extActor ! Extract(uuid, text)
}
def getFinalResult(): java.util.List[String] = {
implicit val timeout = Timeout(5 seconds)
val askActor = system.actorOf(Props(classOf[ExtractorDelegateActor]))
val future = askActor ? FinalResult()
val result = Await.result(future, timeout.duration).asInstanceOf[java.util.List[String]]
result
}
def shutdown(): Unit = {
system.terminate()
}
}
/* Extractor Delegator actor*/
class ExtractorDelegateActor extends Actor with ActorLogging {
var targetStore:scala.collection.immutable.List[String] = scala.collection.immutable.List.empty
def receive = {
case Extract(uuid, text) => {
context.actorOf(Props[ExtractProcessor].withDispatcher("fixed-thread-pool")) ! DelegateLambda(text)
}
case UpdateList(res) => {
targetStore = targetStore :+ res
}
case FinalResult() => {
val senderActor=sender()
senderActor ! targetStore
}
}
}
/* Aggregator actor*/
class ExtractProcessor extends Actor with ActorLogging {
def receive = {
case DelegateLambda(text) => {
val res =callLamdaService(text)
sender ! UpdateList(res)
}
}
def callLamdaService(text: String): String = {
//THis is where external API is called.
Thread.sleep(1000)
result
}
}
不知道为什么要在这里使用演员,最简单的方法是
// because you call external service, you have back async response most probably
def callLamdaService(text: String): Future[String]
为了处理你的文本,你需要
implicit val ec = scala.concurrent.ExecutionContext.Implicits.global // use you execution context here
Future.sequence(source.getLines().map(callLamdaService)).map {results =>
// do what you want with results
}
如果您仍然想使用actors,可以将callLamdaService
替换为processparagration
,这将在内部向工作者actor执行ask
,后者返回结果(因此,processparagration
的签名将是def processparagration(text:String):Future[String]
)
如果您仍然想启动多个任务,然后请求结果,那么您只需要使用上下文。当您增加每个提取消息的工作人员数量并减少每个更新列表消息的工作人员数量时,就可以使用接收(worker:Int)
。对于非零数量的处理工人,您还需要执行FinalResult
的延迟处理