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 の実行に必要なファイル以外は含めるべきではないんですが、ムシムシ

cosmosdb-query-builderというnpmパッケージを作った

www.npmjs.com

node用DocumentDBのライブラリと組み合わせて使うことを想定しています。

動機とか

Win機が手元になくても大丈夫だったり、Lambda と同じノリで書けたりという理由で Azure Functions での開発にはもっぱら node を選択しているのですが、

  1. ありがちな動的に where 句の構成条件が変わるような要件を、文字列操作しまくってなんとかするのは(開発時はよくてもメンテが)なかなかストレスフル
  2. せっかく SQL(的記法)が使えるんならORMまではいかずともクエリビルダーが欲しくなってきた
  3. ざっと探してもなさそうなので、どうせならさいくろん先輩の馴染みのアレみたいな書き方をしたい

というわけで作りました。
そもそも日本で Azure Functions を、しかも Node.js でやっていき人口はだいぶ少ないと思うのですが*1、ありがたいことに多少は npm i されてるっぽいので、必要な人に届いたらいいなあと思います。

DocumentDB は他の RDBMS 達と違って以下のようなしんどめの diff があります:

  • 単一コレクション(テーブル)のクエリでもカラムにコレクション名をつけないといけない
  • LIMIT 句は SELECT とカラムの間に指定する(!?)

主にこの2点と、あとは値のバインドの形が若干煩わしいので、主にそのあたりを解消することを目的としています。

つかいかた/できること

Inspired by CPAN module なので SYNOPSIS とかついてます。

const querySpec = builder.query(
  'SELECT %l %c FROM %t WHERE %w %o',
  20,
  ['id', 'age'],
  'c',
  { id: 200 },
  {
    order: {
      sort: 'desc',
      key: 'createdAt'
    }
  }
);
// SELECT TOP @_top c.id, c.age FROM c WHERE ( c.id = @id ) ORDER BY c.createdAt desc

LIMIT 句を表現するのに、本家のように %o のようなキーワードで吸収できたらいいんですがなかなか…。
また前述の理由で引数にコレクション名を取ります。一応 %t 記法もサポートしたけど今のところあんまり意味ない。

WHERE 句は operator 指定できたり AND/OR のネストができたり関数指定ができたりします。
あとは DocumentDB はストアしている json の型にはめちゃんこ厳しいので、対応するために type 句を取ったりしてます(string 型はちゃんとクオートしないと引けない)。
というわけで地味に便利な仕上がりになっていると思います。

できないこと

現状 JOIN, GROUP 系の記法には対応していません。PRお待ちしてます!

*1:しかし Azure Functions + CosmosDB はベーシックなユースケースでは Lambda + Dynamo より楽で安いと思う。中小企業の味方!なんとベータ版ならNode10も使える!

2017年夏、Apple ATS対応における試行錯誤

ATS(App Transport Security)*1対応にかんして、あれこれ試してみた結果を備忘的に残しておこうという記事です。
なんか延期とか言われてますけどね…
ATSの概要と詳細については以下:
[iOS 9] iOS 9 で追加された App Transport Security の概要 | Developers.IO

TL;DR

やりたいこと
  • 新規アプリで、不特定多数(含 http)のサイトのOGPを表示したい
  • タップで Safari に遷移

これだけ?ええ、これだけです。これだけなんですけど…。

結論

Cocoa Keys/App Store Review for ATS にあるように、
今回のケースは(きっと)

Must connect to a server managed by another entity that does not support secure connections

に該当するはずなので、 NSAllowsArbitraryLoads を立ててレビューをゴリ押しする…のがよさそうですね。

ただ一度は全展開がアナウンスされた機能ですし、レビューで蹴られるポイントを増やすのもなー、ということで、Azure Functionsでさくっとプロキシさせることに*2しました。PaaS最高。
ただこれ、どう考えてもAppleの思惑からは大きくずれているんですよねえ…。

*1:iOS App からwebページを表示させる際に、httpなサイトやAppleの定めた基準を下回るものは弾かれるようになる設定

*2:今回はAPIサーバをAzure Functionsで用意していることもあり

続きを読む

Sierra+Hammerspoonでキーバインドを設定する

新MBPのセットアップをしていたところ、愛しの Karabiner が Sierra に倒されてしまったという報を聞き、 Hammerspoon に乗り換え。
(Karabiner にはなにかしらの形で恩を返したい…)

Karabiner 使えない対策: Hammerspoon で macOS の修飾キーつきホットキーのキーリマップを実現する - Qiita
Hammerspoonで macOS Sierra + Xcode に emacs ライクなキーバインドを設定した - Qiita
Hammerspoon docs

このあたりを見つつ。
長ったらしいですが Emacs 以外で Emacs Like なキーバインドをやろうというヤツ、以上。です。
kill の再現にちょっとハマった。
nginx lua なども通ってこなかったので、まさかこのタイミングで Lua プチ入門するとは…という思い。
C-x 系のキーバインドも増やしていきたい。

gist.github.com

YAPC::Hokkaidoのつくりかた #yapcjapan

http://yapcjapan.org/2016hokkaido/

今年もつつがなくお祭りを終えることができました。
今まで以上にいろんなことをやらせていただいたので備忘や知見の共有も兼ねてまとめておきます。

体制

コアスタッフは7名
このうちJPAからは代表理事(nekokakさん)とわたし(小間使い)が参画。

準備

  • Webサイトコーディング/更新
  • 文言(About、トークレギュレーション、チケット販売、#yapcjapanに流したお知らせ、PassMarket経由のお知らせ、etc、etc...)の作成
  • 入稿データチェックおよび入稿作業
  • スポンサー様とのやりとり(一部)
  • YAPCブログ編集
  • 個人スポンサーノベルティ内容検討〜手配
  • その他球拾い

を主にやっていました。

大きな舵取りはねこかくさんに、会場の手配など道内の作業は永谷さん、くみさん、篠原さんに。お金まわりとスポンサー様とのメインのやりとりは貞永さん、ねこかくさんに。目玉企画であるところのクラウドセッションはふぉんさんに。その他細々したところをりこさんに拾っていただきつつ進めていきました。

忙しさには波がありましたが、それぞれが「確認する」「決める」「手を動かす」の3つを定常的にやっていた気がします*1

確認する

基本的にリモートかつ東京-北海道で離れているので、オンラインコミュニケーションは密に取りつつ、タスクを持っている人の状況がわかるようにissueを切ったり声をかけたりスプレッドシートにまとめたり。

決める

「これどうなってたっけ?」を極力減らす。自分で決められることはさっさと決めて周知。判断が付かないものはさっさとエスカ。

手を動かす

やるべきことと方向性が決まればあとは走るのみ。うまく走れていない人がいれば手助けを、逆に自分が走れていないなというときは早めに助けを求めるようにしていました。

当日

途中までA会場の番長(進行など)をやっていたんですが、遊撃を担当するほうが会がスムーズに回りそうということでaloelightさんにお願いして引き継ぎ。
スペシャルセッションにご参加された福田さんに飛行機が新千歳にたどり着けないというアクシデントもありましたが、予めリハーサルしていたかのようにしっかりとハングアウトにフォールバックされて、皆さんの対応力の高さにおののきました。
当日スタッフとして入っていただいたみなさまにもたくさんたくさん助けていただきました。ありがとうございました!

ふりかえり


最低限礼節をわきまえたメールのやりとり、モノの取りまとめや発注、コーディング、想定外の事態への対応力、などなど、今まで各所でやっていたあれやこれやが全部必要になる面白いお仕事だと改めて思いました。
もちろん人により向き不向きがあるので、それは各メンバーが補完しあえばいいだけの話なのですが、一人あたりのカバー範囲は広ければ広いほど柔軟な対応ができますね。

「エイヤ人」の存在

前述の「確認する」とか「決める」とかって、手を動かすことよりは実際のコストはあまりかからないのにやたら体力をつかうアクションだと思っていて、なかなか手が付けられなかったりするんですよね。
出た案に対して賛同は出ても、それを具体化して問題点を事前に洗い出したうえで粛々と実行していく…というのはけっこう骨が折れます。
みんな忙しい、でもデッドラインはずらせないという状況で、腹を括ってエイヤとやっつけてしまおう!と旗を振れる(責任を持って動ける)人というのが、カンファレンス運営には不可欠だなと他のコミュニティの話を聞いていても思いますし、正直ここが一番冗長化が難しそうです。
全員が本業のかたわらでの参加で、そこまでの(精神的な)コミットを求めるのは厳しかったりもするんですが、中途半端に関わるよりはそのほうがぜったい楽しいです。ので、ぜひ。



「持続可能なカンファレンス」

カンファレンスの運営は、100%とはいかずとも、あるていどはフォーマット化することができると思っていて。
ほぼ0の状態からリブートした今回は、今のコアメンバーが抜けたとしても持続可能なYAPC::Japanを作っていくために色々と試行錯誤をしてみています。
次回のYAPC::Kansaiか、次々回のYAPC::Fukuokaまでには一通りのテンプレートが揃うんじゃないかなと目論み中。
この先も各地のpmとタッグを組みつつ、色々なところで楽しくYAPCができるといいなー!

感想

先に「ほぼ0の状態から」と書きましたが、体制面はそうでも「YAPCというカンファレンスの知名度」「ブログを書くまでがYAPC」などなど、先代の皆さまと、YAPC::Asiaから変わらずYAPCを愛してくださっている参加者の皆さまのお力をたくさんお借りしているんだなと改めて感じた会でもありました。本当に有り難いです。

永谷さんがぜひ北海道で!と声を上げてくださったこと、篠原さんくみさんふぉんさんりこさんにとっっってもサポートいただいたこと、ボランティアスタッフの皆さまのご助力、各スポンサー様のご協力、そしてねこかくさんの大旗振りがあってこそのYAPC::Hokkaidoでした。
とてもたのしいお祭りでした。改めまして、ありがとうございました!



それではみなさん、来年の3/4に大阪にてお会いしましょう!

*1:文字にすると当たり前っぽいんですが、これが意外と難しい

YAPC::HokkaidoでLTしてきた #yapcjapan

せっかくYAPCがリブートしたっていうのにPerl成分ゼロの発表をしてしまった…!後悔はしていません。


システム設計って、あるていど経験を積むと「なんとなくしっくりくるかこないかで判断」できるようになってきて、
「ざっくり判断したのちにそれを裏付けるロジックを組み立てていく」という流れを取るようになるのかなと思っています*1
サービス設計やUI設計をやらせてもらうようになって、この感覚がある程度横にスライドできるなということに気づけたのが自分の中ではわりと大きかったので、趣味プロダクトやOSS業などでみなさんにもお役立ていただければなと思い発表しました。

さて、YAPC::Hokkaidoではコアスタッフをやっていたわけなんですが、こちらについては書きたいことが山のようにあるのでまた後日したためます。私のYAPCはまだまだ終わらないぞ*2

*1:出典元は恩師じごろうさんのお言葉です

*2:なお残タスクも山のようにある模様

極小規模のフロントエンド開発をしてみたまとめ@2016年

とても久々に(というかわりと初めてまともに)HTML5 な Web アプリを作った気がするので、作ったものとやって捗ったことをまとめておく。

つくったもの

f:id:ar_tama:20161117154217p:plain

理研の仁科加速器研究センターさんの展示コンテンツ。
陽子・中性子の数を組み合わせて原子核を探してみよう、というもの。

まずはこちらをどうぞ:
原子核を見つけよう! – 仁科加速器研究センター

コーディングスタイル

こちらを参照しながら生JSで書いてみた。
Google流 JavaScript におけるクラス定義の実現方法

AltJSは長くメンテするプロダクトではない+重厚長大にはならないと判断しスルー。

ライブラリ

Three.js

three.js - Javascript 3D library

JSで3Dを手軽に扱うためのライブラリ。Processingの3Dと似たかんじで書ける。
ただ重力(引力)が特定"方向"のみにしかかけられず、特定の点(x, y, z)に対しては発生させられずじまいで、原子核を「それっぽく」見せるのが難しかった。
結局Unityで特定点(0, 0, 0)に引力を発生させて球を集め、座標を緯度経度の歪みを取りつつ計算して外部ファイル化という力技*1で解決。
個数によってもちょうどよくおさまる座標が違うので、合計個数に応じてよむファイルを変えたりもした。

Tween.js

GitHub - tweenjs/tween.js: Javascript tweening engine

おなじみTweenのJS移植版。
メソッドチェーンでモリモリ書ける。

simple-drawing-board.js

今さらcanvasにフリーハンドで絵が書けるライブラリ - console.lealog();
GitHub - leader22/simple-drawing-board.js: Just simple minimal canvas drawing.

手書きでコメントを残してもらいたいシーンがあり活用させていただきました。:pray:
描画領域は base64 encoded image として取得できるので、local storage に保存→次のシーンで background-image 指定して表示、という使い方をしていた*2

Gulp

  • gulp-sass
    • 途中まで生CSSでがんばっていたけど、いったい何と戦っているんだ感が出てきたので早々に移行。postcssで揃えてもよかったかもしれない。
  • gulp-autoprefixer
  • gulp-postcss
    • vendor prefix(-webkit とか -ms とか)をつけてくれる君を postcss で。Chrome で開発して Edge で動作確認していたのでとても重宝した。input:range は鬼門…!
  • gulp-concat
  • gulp-uglify
  • gulp-cssmin
    • おなじみの。

Surface

(展示機は日本マイクロソフトさまのご厚意により Surface BookSurface Pro 4 をお借りしておりました)
Book は GPU なしモデルだったけどパフォーマンスが著しく悪いということはなく、どちらも安定していた*3
当日ずっと動かしていると描画が重くなってしまった(リロードしたら直る)けど、これはメモリリーク対策が不十分だっただけだと思う。

あとは Windows Hello がとてもストレスフリーでよかった(PCを開いた意瞬間に顔を認識してロック解除してくれる)。Touch Bar よりよいのでは。

そしてペンが便利すぎてこうなった。

twitter.com

Microsoft Edge

開発中は基本的にはあまり不満はなかった。デバッガも Chrome と同じノリで使える。
まだ開発途中ということもあるのか、展示で使うには以下がつらかったのでメモ。

  • フルスクリーンモードがない
    • window.open で新しくウィンドウを開いてもアドレスバーが出たまま。なおリロードは効かず。ウィンドウサイズの調整がなかなか厳しかった*4
  • Webページが保存できない
    • データのエクスポートを兼ねてCtrl+Sでさくっと保存しようとしたらどうがんばっても効かなくて泣いた。展示中はデータをlocal storageにおいていたのでそちらをエクスポート(気合でコピペ)。

*1:社長謹製

*2:会場内ではネットワークが使えなかったので、ローカルで完結させるために local storage を使用

*3:まあたいしたことしてないからなのだけど

*4:特に Three.js で window.innerWidth / Height を使って全面に描画をしていたので、わりかしハマった