我正在尝试在akka演员之间建立一个消息传递过程来代表主人给工人一份工作,并密切关注它。我的问题是
我喜欢这个过程
1)主人使用ask
向工作人员发送工作。它希望在5秒内得到答复,否则它认为工人失去了它的机会,它将不得不再次进入竞标。
import context.dispatcher
implicit val timeout = Timeout(5 seconds)
val workCompletedFuture = (worker ? WorkTicket(work)).mapTo[Future[WorkCompleted]]
2a)如果工作人员在5秒钟内没有响应,我希望主人向自己发送一条消息,说明要重新分配工作。
self ! WorkAllocationFailed(work, worker)
2b)如果工作人员确实做出了回应,那么它会给我们一个未来[WorkCompleted]。我想等待那个未来完成,比如2分钟。
3a)如果Future [WorkCompleted]未能在超时内完成,则重新分配工作
self ! WorkFailed(work, worker)
3b)如果Future [WorkCompleted]成功,则收集结果
我尝试过创建这个逻辑,但是我遇到了嵌套onComplete
的混乱,我不知道如何在Future [WorkCompleted]上执行超时。我尝试阅读Akka 2.10 Futures docs,但无法找到解决方案。
答案 0 :(得分:2)
一般的想法是,你有一个将工作交给工人池的大师是一个合理的模式。
另一方面,当系统的所有部分都已经是演员时,我不建议使用期货。您可以通过tell发送,而不是使用ask提交作品。然后,主人可以定期检查超时工作,然后重新提交。
此外,在actor的主体中调用onComplete非常危险,因为它在可能不同的线程上执行。与演员沟通的安全方式是通过消息传递。如果你有一个Future,并且你希望在Future完成时在actor中完成某些事情,那么最好使用管道模式。
您的代码段中还有一个小错误。如果你的工作者回复了WorkCompleted,那么这就是你真正想要的那条线:
val workCompletedFuture = (worker ? WorkTicket(work)).mapTo[WorkCompleted]
答案 1 :(得分:2)
我同意恩德雷的回答 - 所有非常好的观点。
这个怎么样:
1)为超时安排一条消息(使用system.scheduler.scheduleOnce
)
2)使用常规tell
3a)如果完成的工作在超时消息之前返回,则取消预定作业并使用步骤1和2重新分配工作
3b)如果完成的工作在超时消息之后返回,则忽略它或取消重新分配的工作。
一个地方的期货可能对工人有帮助,特别是如果工作需要很长时间或阻塞。工作人员可以使用未来来完成工作并保持可用以处理更多传入消息,例如取消工作。