Erlang 20.1.7でglobal名が衝突してtakeoverが失敗する
この本を読みながら遊んでいたらハマった。
chuckyというアプリケーションをつくってfailoverとtakeoverを試してみる章で、failoverはうまくいくけどtakeoverできない、という現象が見られた。 A, B, Cという3つのnodeがあり、Aでchuckyが動いているとする。
A [chucky] B C
ここでAが死ぬ
🔥 B [chucky] C
すると、failoverしてBでchuckyが動きはじめる。ここでAが復活すると、本来はtakeoverして以下のようにAでまたchuckyが起動するが、なぜかここがコケる。
A [chucky] B C
どのようにコケるかというと、chuckyが立ち上げているプロセスのうちglobalな名前を持っているものが、その名前のプロセスはもう立ち上がっているよ、というエラーで立ち上がれない、というもの。つまり、Aがtakeoverして立ち上がりプロセスにglobalな名前をつけようとしたところで、その名前はBで使われていて落ちる。
回避策として、最初はglobalな名前を付けずに立ち上げて、起動後に:global.re_register_name/2
をつかう、とするべきなのかなあと思ったけど、そんなことしないといけないんだっけ、と思って色々試したところ、Erlangのバージョンを今の最新の20.2.2に上げたら本の通りに動いた。失敗していたときはErlang 20.1.7。ちなみにElixirは1.6.0。
原因はよくわかっていないのでもにょり。