我想设计一个流程层次结构,其中有一个父流程P,它像一个网守,并将工作(来自其客户流程的消息/事件)委托给它的子流程C1,C2..Cn它们相互协作并可能将结果发送回P.儿童流程无法与外部任何流程进行通信,只有P。
挑战在于虽然P可能有来自其客户端的多条消息,但它应该只接受一条消息,将工作委托给C1..Cn,并且只接受来自其客户的下一条消息
约束:
是否有OTP模式或库可以为我做这件事(在我破解之前?)。我知道process_info
可以让我知道进程的邮箱是否为空,我可以继续检查来自P的子邮箱但是从P进行不必要的轮询。
编辑概述:我正在尝试在Erlang平台上实现Flow Based Programming的反应变体。这有“等级过程”的概念。或复合本身可能包含复合过程,直到我们到达一些实际代码框...我将研究(查看monitor,process_info,process_flag)但我想回答你的优秀答案
编辑递归父母:C1和Cn中的每一个本身都可以是父/复合过程。如果我只是生成流程并让它们立即退出,我每次都必须创建复合材料链,因为C1..Cn本身可能是复合材料(产生复合材料......等等)。最后,当我们到达一个叶子框(它不是一个复合节点)时,它们应该是有限状态机。所以我不确定是否产生并且如果它们是FSM则使它们快速退出。
编辑TKOWAL:因为我正在尝试创建一个通用的父/复合过程,所以它不知道'何时'任务结束。它所做的一切就是将它从孩子那里收到的信息传递给它的兄弟姐妹,并带有“约束”。它不会接受来自其客户/兄弟姐妹的下一条消息,直到它们的孩子完成了#39;孩子C1..Cn不仅可以发送一个而且可以发送许多消息。我从你的提议中了解到,wait_for_task_finish将在收到第一条消息时停止阻止。但P的孩子也可能发出更多信息。 P应该等待所有消息。此外,具有task_end符号将不会出于同样的原因(即可能来自孩子的多条消息)
答案 0 :(得分:2)
考虑到启动Erlang流程的成本是多么便宜,你的看门人可以为每个传入的任务启动新的孩子,然后等待他们一旦完成工作就正常退出。
但总的来说,听起来你正在寻找一个流程池。其中有一些已经可用,例如poolboy和sidejob。池可以是harder to get right than you think,因此我建议在尝试编写自己的池之前使用现有的经过验证的池实现。
答案 1 :(得分:1)
编辑后,这成了完全不同的问题,所以我发布了新答案。
如果您正在尝试编写基于流程的编程,那么您可能正在解决错误的问题。 FBP很有效,因为几乎所有东西都是异步的,你在完成上一个请求后立即开始处理下一个请求。
所以,答案是 - 不要等孩子完成:
在FBP中,组件之间没有时间依赖关系。所以,如果我 拥有一大块数据,它应该能够从一端流出 无论其他任何数据如何,都可以向另一方绘制图表 被处理。为了对FBP系统进行编程,您必须最小化 你的依赖。
创建父级和子级时,您知道块之间的所有连接,因此只需将子级配置为将处理后的数据直接发送到下一个块。例如:P1有孩子C1和C2。您向P1发送消息,它将其委托给C1,数据包在C1和C2之间流动几次,之后,C1或C2直接将其发送到P2。
块应该是无状态的。它们的输出不应该依赖于先前的请求,所以即使C1和C2正在处理来自两个不同请求的数据到P1 - 也没关系。可能存在这样的情况,其中P1获得数据包D1然后获得D2,但是将以不同的顺序输出答案R2然后输出R1。这也没关系。您可以使用Erlang reference标记邮件,然后检查哪个响应来自哪个请求。
答案 2 :(得分:0)
我不认为,有一个现成的库,但它很容易入侵,除非我错过了什么。您的P流程应如下所示:
ready_for_next_task() ->
receive
{task, Task, CallerPid} ->
send_task_to_workers(Task)
end,
wait_for_task_finish(CallerPid).
wait_for_task_finish(CallerPid) ->
receive
{task_end, Response} ->
CallerPid ! Response
end,
ready_for_next_task().
在wait_for_task_finish/1
中,您只有一个接收子句,因此它不会接受下一个任务,直到当前的任务完成。如果您正在等待工作人员的多个回复,您可以简单地将第二个子句添加到receive
并进行部分响应,并递归调用wait_for_task_finish/1
。
最好有一些指标,即处理结束,因为您不能保证邮件传递时间。这意味着,你可以检查,所有进程当前正在等待消息并思考,他们已经结束处理,但实际上,他们还没有开始,或者其中一个向其他人发送消息,你在第二个拥有它之前抓住了它们在消息框中。
如果过程C1..Cn只有部分实际工作并且不知道进度,那么看门人P应该知道有多少部分,然后逐个接收所有部分,然后致电{ {1}}。