Elixir試飲録 (6) – exrm で hot upgrade すると static assets のパスが古いバージョンのまま更新されない問題への対処

前回のElixir試飲録exrm (Elixir Release Manager) を利用した Phoenixアプリケーションのデプロイ自動化について紹介した。この仕組みの上で、手始めに簡単な Web API を開発している間は何の問題もなかったのだが、JavaScript と CSS を使って UI を作り始めるとすぐに表題の不具合に遭遇した。JavaScript (static assets) を更新してデプロイしても、稼働中のアプリケーションに変更が反映されないのである。

同じ問題に遭遇している人はやはりいて、Issue #206 で報告されていた。

Phoenixアプリケーションの config/config.exs を見ると以下のような設定がある。

config :example_app, ExampleApp.Endpoint,
  ...
  root: Path.dirname(__DIR__),
  ...

Issue #206 では、この Path.dirname/1 という関数が、前回紹介した「config内の環境変数参照がリリースパッケージをビルドする際に評価されてしまう問題(Issue #75 · bitwalker/exrm)」と同様、ビルド時に評価されてしまうので assetsへのパスが更新されないのではないか、と説明されている。

なので、config/prod.exs についてだけ、

config :example_app, ExampleApp.Endpoint,
  ...
  root: ".",
  ...

のように変更すれば問題は解決するとのこと。

しかし解せないのは、root のパスがビルド時のもの(しかも絶対パス)になってしまうのであれば、たまチームのようにビルド環境(CircleCI + Docker)と実行環境(AWS EC2)が異なる場合、そもそもこの設定が機能しないように思えるのだが…?

という疑問はさておき、とりあえず上のように修正して再びデプロイすると、無事 assets が更新されていることを確認できた….と思いきや、再び JavaScript を修正してもう一度デプロイを行うと、更新されない… その後は何度やっても更新されなかった。つまり、問題は解決されていない。

同じく Issue #206 に書かれている対策を施しても解決されないという Issue を投稿して放置されている人がいた(友よ)。

この問題がここまで放置されているということは、こちらのやり方がおかしいのか、あるいはそもそもこのツールを使って無停止デプロイをやっている人がほとんどいないのではないかという疑念が湧いてくるが、解決できなければ快速無停止デプロイ生活は終焉を迎えてしまう。

諦めてなるものかと試行錯誤を続けていると、どうやら root: "." の部分は、この問題とは関係がなく、単に :example_app, ExampleApp.Endpoint の設定がデプロイ時に更新されていれば、assetsのパスが正しく更新されることに気付いた。

試しに、以下のようなダミーの設定を追加して、

config :example_app, ExampleApp.Endpoint,
  ...
  version: "1",
  ...

デプロイの度にこのversionの値を更新すると、assetsのパスが正しく更新されることを確認できた。というわけで、今はこの方法で運用している。

具体的には、Conformの設定ファイルに以下のような項目を追加しておき、

example_app.conf

...
Endpoint.version = "default_version"
...

example_app.shema.exs(Conformの変換ルール)

    ...
    "Endpoint.version": [
      commented: false,
      datatype: :binary,
      default: "default_version",
      doc: "Workaround for https://github.com/bitwalker/exrm/issues/253",
      hidden: false,
      to: "example_app.Elixir.ExampleApp.Endpoint.version"
    ],
    ...

upgradeの際に以下のように値を置き換える。

upgrade.sh(このファイルの詳細についてはこちらを参照)

...
cp ${APP_HOME}/app.conf ${DEPLOY_TO}/${VERSION}/${APP}.conf
sed -i -e "s/default_version/${VERSION}/" ${DEPLOY_TO}/${VERSION}/${APP}.conf
...

この現象について Issue の方に報告したところ、開発者の Paul Schoenfelder氏の方でも問題に気付いて頂けたようである。近い将来に修正されるのを楽しみに待ちたい。

さて、以上のように、この問題は「Configに変更がない場合に、リフレッシュされずに古い状態が残ったままになる」という問題のようなので、keichan34氏が最初のIssueに投稿している以下の対策でも機能するのではないかと思う。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中