2017-08-23 137 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}的任何呼叫者建立連接。使用這種方法進行設計可以讓您的監督樹保持穩定,而是將如何處理失敗的決定推到可能擁有更好信息的客戶身上(例如,他們是否應該重新嘗試操作,返回錯誤給他們的呼叫者,退出例外等)