Open zacky1972 opened 3 years ago
I believe that will be useful to support mix upload.hotswap
.
In case that NIFs exist but mix upload.hotswap
is newer than them, Pelemay should give up to load NIFs and fallback to execute the user code by Elixir.
This issue is related to #156
Sorry, in Japanese.(I explained at Nerves JP Slack)
Pelemayの仕組みを説明すると,次のような感じです。
Application.app_dir(:pelemay, "src")
に生成するApplicatoin.app_dir(:pelemay, "build")
に生成してビルドする。生成したNIFライブラリは Application.app_dir(:pelemay, "priv")
に生成されるApplication.app_dir(:pelemay, "priv")
に生成する。このコードをロードすると NIFライブラリが読み込まれる。mix firmware && mix upload
は,lib
配下にあるモジュールに加えて,Application.app_dir(*, "priv")
もターゲットに転送します。
これに対し,mix upload.hotswap
は lib
配下にあるモジュールをホットスワップしますが, Application.app_dir(*, "priv")
をターゲットに転送することはしません。
したがって,Pelemayを組み込んだプロジェクトを mix upload.hotswap
すると,上記の5だけが見えて,Application.app_dir(:pelemay, "priv")
に配置したはずのNIFライブラリとスタブElixirコードが見えないので,スタブElixirコードのモジュールが存在しないというエラーになります。
NIFライブラリを転送することができないのはどうしようもないのですが,スタブElixirコードについては,ファイルを配置してロードするというアプローチをやめて,マクロで実現すれば,現状のmix upload.hotswap
の仕組みで実現できます。
あとは,スタブElixirコードがNIFライブラリが存在しない,もしくは古いことを検出した場合に,NIFライブラリを読み込んで実行することを諦めて,元のElixirコードをそのまま実行するようにすれば良いというわけです。
実運用を考えた時,
mix upload.hotswap
で動作確認をして,というのをある程度繰り返し,mix firmware && mix upload
して動作確認をしてファームイメージを更新する,というような感じになると思います。
このような運用の時に,Pelemayは,1のときには Elixir での実行で動作し,2 のときにはネイティブコードで動作するという感じにできれば良いかなと思います。
いったん2をすると,Application.app_dir(:pelemay, "priv")
にNIFが転送されるので,そのあとで1をすると,NIFをロードした時に古いNIFを読み込んでしまうと不一致になってしまうと思います。
そこで,バージョンに1対1対応した番号を,スタブElixirコードと Application.app_dir(:pelemay, "priv")
に埋め込んでおき,スタブコードのロード時にこの番号が一致した場合はNIFをロードし,一致しなかったりロードに失敗したら元のElixirコードを実行する,というようにすれば良いかなと思いました。
Current Pelemay will fail to execute user code in
defpelemay
when the NIF generated by Pelemay cannot be loaded for some reasons.So, Pelemay is expected to add a fallback feature to execute the user code by Elixir instead of native code in that case.