我有一个正在编排数据库更新的actor。我需要确保每个操作仅在前一个操作完成后执行。 这是因为操作B将重用操作A的结果。
这是我为演员写的代码。
class DbUpdateActor(databaseOperations: DBProvider) extends Actor {
implicit val ec:ExecutionContext = context.system.dispatcher
def receive: Receive = {
case newInfo : UpdateDb =>
val future = Future {
// gets the current situation from DB
val status = databaseOperations.getSituation()
// do db update
databaseOperations.save(something)
}
future onComplete {
case Success(result: List[Int]) =>
//
case Failure(err: Throwable) =>
//
}
}
}
该代码适用于单个操作。如果我触发两个更新,那么第二个更新将异步执行,以便在第一个更新完成之前启动。
我正在阅读有关不同类型邮箱的信息,不确定是否有其他类型的邮箱会有所帮助。
有什么建议吗?
答案 0 :(得分:1)
您可以探索的一个选项是删除Future
并允许阻止db代码在actor中运行。然后,使用单独的调度程序(可能是PinnedDispatcher)从主actor系统的调度程序中解除阻塞代码,为其提供自己的运行线程。通过阻塞正文并删除Future
,您将确保正确顺序执行actor的邮箱。这项改变的粗略草图如下:
object DbUpdateActor{
def props(databaseOperations:DBProvider) =
Props(classOf[DbUpdateActor], databaseOperations).
withDispatcher("db-update-dispatcher")
}
class DbUpdateActor(databaseOperations: DBProvider) extends Actor {
def receive: Receive = {
case newInfo : UpdateDb =>
val status = databaseOperations.getSituation()
databaseOperations.save(something)
}
}
然后,只要您在actor系统配置中配置了以下调度程序:
db-update-dispatcher {
executor = "thread-pool-executor"
type = PinnedDispatcher
}
你启动了db update actor就像这样:
val updater = system.actorOf(DbUpdateActor.props(databaseOperations))
然后你应该全部设置这个演员,以不会对主调度员的吞吐量产生负面影响的方式运行阻塞代码。
答案 1 :(得分:0)
这个怎么样:在孩子中开始手术A;当孩子完成时,它会向父母发送一条消息,说明已完成。然后,您可以在现有孩子或新孩子中开始操作B.