より正確には:
動的な数の子供のスーパーバイザーがいます。特定の子が追加されて最初に開始されたときに、後で発生するすべての再起動よりも異なる init 関数を使用する必要があります。オプションで、プロセスが再起動されたことを検出できる場合は、同じ関数を使用できます。
より正確には:
動的な数の子供のスーパーバイザーがいます。特定の子が追加されて最初に開始されたときに、後で発生するすべての再起動よりも異なる init 関数を使用する必要があります。オプションで、プロセスが再起動されたことを検出できる場合は、同じ関数を使用できます。
技術的には、プロセスがスーパーバイザーによって再起動されたのか、それとも最初の起動であったのかを調べるために使用できる副作用があります。たとえば、プロセスの pid をチェックして、スーパーバイザの pid と比較できます。ただし、これは見苦しく、エラーが発生しやすく、OTP の原則と矛盾しています。実際、スーパーバイザ自体、またはアプリケーションまたはノード自体が再起動された可能性があります。調べようとしても無駄です。
代わりに、OTP の原則に従って、監視対象のプロセスが初めて開始された場合でも再起動された場合でも同じタスクを実行するようにする必要があります。これは、プロセス間の依存関係を処理する適切な監視ツリーで実現できます。
プロセスが開始または再起動されたかどうかを確認したい一般的な理由は、プロセスが最初に開始されたときに、再起動時にやり直す必要のない何かを実行する必要があるためです。最終的には、開始時に実行する必要があることを終了時に元に戻す必要があるため、プロセスはすべての状況で開始時に同じことを実行できます。
たとえば、別のプロセスを開始し(Bと呼びましょう)、開始時に子とプロセスBをリンクし、子が終了すると、Bも終了します(そして相互に)。B プロセスのスーパバイザが子プロセスを再起動しないように設定する必要があります (つまり、一時的にします)。
(以下の最初のコメントに基づいて更新)
工場の追加は問題をさらに押し進めるだけで、完全に解決するわけではありません。子の作成を担当するファクトリがあるとします。このプロセスにより、子の状態が保存され、再起動時に復元されます。これを実現するには、次のようにします。
erlang:monitor/2
ます。子が終了するたびに、ファクトリはメッセージを受け取ります。その後、子を再起動して状態を提供できます。メモリ効率のために、別のメッセージでプロセスの状態をファクトリから復元する必要があることに注意してください。実際、保存された状態を仕様に入れると、スーパーバイザーがコピーを保持します。
また、工場が停止した場合に子供が死亡するようにしたい場合もあります。これを実現するには、2 つのプロセスをリンクする必要があります。その結果、 を使用する代わりに、erlang:monitor/2
( を使用して) exit をトラップするようにプロセスを構成することにより、EXIT メッセージを受信するようにファクトリを構成できますerlang:process_flag/2
。
ただし、ファクトリ自体が異常終了する可能性があるため、これでは問題は解決しません。スーパーバイザによって再起動され、適切なクリーンアップが行われずにすべての状態が失われます。したがって、ファクトリが終了したときに、子の開始時に実行する必要があることを元に戻す必要があります。
プロセスが停止する理由を明確にすることから始めるべきだと思います。次に、適切に再起動するための関連する戦略は何ですか (これについては情報を提供しません)。次に、これらのプロセスが終了するのがアプリケーションの通常の動作である場合 (たとえば、セッション タイムアウト)、私の意見では、終了する可能性のあるタスクを状態の保存を担当するタスクから分離する必要があります。ets、dets、または mnesia に情報を保持することも関連している可能性があります。しかし、ポールが言ったように、OTP の原則に固執するようにしてください。
監視対象プロセスは OTP プロセスです。したがって、スーパーバイザーは gen_server などの otp プロセスを開始しています。プロセスがいつ再起動されるかを確認するには、独自のネームサーバーを作成し、gen_server:start_link({via, YourModule, Identifier}... を使用して再起動を追跡します。