2017-08-23 70 views
2

我想要做的是改变我的主管尽最大努力让孩子继续奔跑,但如果他们的失败率超过强度,就放弃。这样,其余的孩子继续跑。但是,对于现有的管理员配置,这似乎不可能,所以看起来像我唯一的选择可能是实现我自己的主管,所以当它收到EXIT时,我可以按照这种方式行事。尽力而为OTP监督

有没有一种方法来实现这样的自定义OTP主管行为,而无需编写自己的主管?

+0

你能解释更多关于具体用例吗?你所描述的内容听起来不像是主管不能满足你的需求,更像是你可能试图做一些有更好选择的监督。这听起来很像在'init/1'中尝试做某些事情,这很容易失败,导致进程在重新启动时很快崩溃。 – bitwalker

+0

所以我在这里为各种来源的内部监测工具提供服务遥测数据。我使用'simple_one_for_one'监督并根据配置文件中的值动态创建这些孩子,这些配置文件在启动孩子时通过。这些孩子是'gen_server',可以根据延迟的消息周期性地处理请求,而在init中完成的唯一事情就是将配置存储为状态并排队处理最初的延迟消息。这使我可以定期安排数据,每个工作人员独立于其他人员。 –

回答

5

这听起来像我想你想要的是每个孩子的个人主管,负责保持它的活力达到极限,如你所说,作为一个上面有一个单独的主管(一对一或简单一对一),他们的孩子被标记为临时的,所以当他们中的一个放弃时,其余的一直保持运行。

+0

谢谢!这听起来正是我需要的! –

4

您不能“扩展”Supervisor以添加不同的监督行为,但您不必从头开始。 :supervisor模块本身是在:gen_server之上实现的,所以如果您发现自己需要某种自定义监督行为,那么我将查阅:supervisor(其中您可以找到here)的源代码;它会给你一个基础,以避免你可能遇到的一些陷阱。

一旦我对您的使用案例有了更好的了解,我可以扩展我关于替代解决方案的答案。正如我在我的评论中提到的那样,在我看来,在您的流程的init/1期间,您很可能会做某些事情,这很容易失败; init/1不是处理这些事情的地方,因为如果暂时无法在该行动中取得成功,您几乎肯定会打击主管的最大重启力度。例如,假设您有一个与数据库交谈并需要数据库连接的进程;在init/1期间,您不想尝试连接到数据库。相反,您应该获得连接后初始化(可能是首次使用,或通过使用Process.send_after(self(), :connect, 0)立即向流程发送post-init消息),并且如果连接失败,则在尝试重新连接时返回类似{:error, :database_unavailable}的任何呼叫者建立连接。使用这种方法进行设计可以让您的监督树保持稳定,而是将如何处理失败的决定推到可能拥有更好信息的客户身上(例如,他们是否应该重新尝试操作,返回错误给他们的呼叫者,退出例外等)