Azure Functions の breaking changes で派手にシステムがブレイクした話

誰得感しかないんですが備忘のためにも一連の顛末を記しておきます。
結論から言うと、v2(beta)を使っていたのですが派手にぶっ壊れたので泣く泣く v1 に向けて実装しなおしました。

ことの始まり

これ。
Azure Functions Runtime 2.0 breaking changes

詳細を見ても自分のプロジェクトに大きく影響のありそうな変更はなく、休暇中だったこともあり全力でスルーしていました。
日本時間で8/31のお昼すぎに適用されたようです。

環境

  • Azure Functions 2.0(beta)+ Node.js
    • 6 batches (Timer trigger)
    • 7 endpoints (HTTP trigger)
    • 10 workers (Queue trigger)
  • Azure AppService に置いた WebApp から Functions に立てた API を叩いている
beta 使用の動機

Node7以降が使いたかったから。それだけ。それがこんな大事になろうとは……。
async/await と spread operator, util.promisify などが主な動機ですね。

第一報〜一次対応

クライアントから「エラーが出ている」とお知らせがあり確認したところ、たしかに401エラーが出ている。
WebApp からは default キーでアクセスさせていたはずだけど……と見たら、キーの内容が変わっていた。
おそらく "Function App secrets storage change" が原因だろうというのがわかったので、渋々キーを置き換えて再チャレンジ……したらすごい500返ってくるー!

調査

Portal からエラーが出る Function を見にいってみると、なにやら見たことあるエラーが。

Function (xxx) Error: The binding type(s) 'cosmosDB' are not registered. Please ensure the type is correct and the binding extension is installed.

さっきまで動いていたので extension がインストールされていないわけはないのですが……とりあえず、テンプレートから新規に CosmosDB Trigger な Function を作ってみました。
しかし特に新規に extension のインストールを促すダイアログも出ず、エラーも変わらず。
再度変更内容を見ると、host.json の形式が変わったらしい。
JSON のトップレベルに各 extension の設定を書いていたのが、"extensions" の中に入れるようになったようですね。
元々なんの設定もしていなかった(自動で "version": "2.0" のみが入っていた)んですが、例にならって host.json を更新してみる…………

CosmosDBの設定例がない!

詰んだ。
質問のissueが上がっているものの、回答なし。

このあたりで Azure ユーザの先輩の わいとん先生まいんだ先生に泣きつくものの、おふたりともv2を使っておらず派手に散る。
わいとんさんには調査にガッツリお付き合いいただいたものの、ふたりしてウーンわからん、となる。(切り分けなどとても助かりました、本当にありがとうございました)

探しているうちに CLI で最新の extensions が入れられるらしい*1ことがわかり、念のために入れて publish してみたものの状況は変わらず。
いろいろコードをいじってみて、かろうじて documentDB module での CRUD には影響が出ていないことが確認できたので、このあたりで v1 に移植することを考え始める。

にっちもさっちもいかなくなってきたので、一縷の望みをかけて陳情しつつ、他の影響範囲を確認……したところ、host.json で設定したはずの Queue Trigger も動いてないことが判明。もうだめだ!

v1(Node6)移植時にやったこと

1. ばべる
{
  "plugins": [
    "@babel/plugin-transform-async-to-generator",
    "@babel/plugin-proposal-object-rest-spread",
    "babel-plugin-transform-util-promisify"
  ]
}

なお Babel7.0 を使っています。
元のファイルを src ディレクトリ以下につっこんで、commit hook で変換をかけ、元のパスに展開しました。
各 Function の index.js は async style にはせず、batch, endpoint, worker でそれぞれエントリーポイントのフォーマットを揃え、固有ロジックは services ディレクトリに移して変換対象に。*2
これが一番時間がかかった…。

2. 外部ライブラリの変換が必要か調査・対応

ひとつだけ spread operator を使っているライブラリがあったのですが、難しくないものだったのでサクっと自前で実装して完了。

3. bindings の設定変更

CosmosDB まわりの bindings type が 1.0 だと "documentdb" なので、そのあたりを中心に各 function.json を修正。

4. CosmosDB out bindings を JSON.stringify する

これは今回のと直接関係ない気もするんですが…
v1 で動かしたところ、マルチバイト文字の入ったオブジェクトを documentdb:out bindings に渡したら、盛大に文字化けしてしまいました。
理由がわからず悶々としていたのですが、ヤケになって JSON.stringify 噛ませたらなんかうまくいっちゃった、という…。

以上です。とりあえず今は目立った不具合もなく動いてくれているようで、ほっと胸を撫で下ろしています。
事態に進展があったら更新するかも。しないかも。

*1:各 extension の最新バージョンは Nuget に行くとわかる

*2:本当は function の実行に必要なファイル以外は含めるべきではないんですが、ムシムシ