この記事は LINEBot&Clova Advent Calendar 2018 の 9日目のエントリーです。
しかしこれを書いているのは、アドベントカレンダーももうすぐ終わるという、12/24、クリスマスイブでございます。
イエスキリストの誕生日はもう明日!大変遅くなってすみませんでした。。。
ジャンピング土下座・・!!
はじめに
どんな記事?
LINE Boot Awards 2018に出品した「らくらく移動ちゃん」の開発のしくじりを懺悔し、供養する記事です。
対象者はこんな人
自分。
次は同じ失敗を繰り返さないために。
LINE Boot Awards 2018ありがとう
こんなバカでもコンテストに応募し、「LINE Boot Awards 2018」のファイナル候補とXperia Ear Duo賞候補のダブルで候補に選ばれることもある、という奇跡で、誰かに勇気を与えることができたらと思います。ちなみに完成度低く両方落ちました。しかし、思いもよらぬことに、Qiita賞をいただきましたので、このエントリもQiitaで書かせていただいてます!ヒューヒュー!
温泉♨️BBA(元木理恵さんと私の二人チーム)
@ LINE Boot Awards 2018の記念写真
Qiita様thanks!
Tシャツ一生大事にします!
システム構成図
使用したClova & LINE APIたち
- Clova CEK
- LINE Messenger API
- LINE Beacon
しくじりポイント
細かいのをあげると大変な量になるので、でかいのだけです。
カッコ内は、どこでその問題を起こしてしまったかです。
1. Node.jsが非同期処理のためDBへの書き込み/読み出しが間に合わず値がnull (Clovaスキル)
本格的なNode.jsのプログラミングは9月以降が初めてだったので、ここら辺が全然わかってなかったです。
そこでセッションの引き回しは、DBではなく、SessionAttributesを使うようにしました。
2. SessionAttributesの長さ制限にひっかかる (Clovaスキル)
しかし、駅の授乳室やエレベータの場所を調べた結果を、
LINEに送るという箇所で、SessionAttributesの長さをオーバーしてしまいました。
そこで、ここだけDB処理を復活させたのですが、
非同期処理なので、本当に送れているかがわからないまま終了するという、激しいもにょり。。
修正前
Clova :「この情報をLINEに送りますか?」
ユーザー:「はい」
Clova:(SessionAttributesから取り出そうとしてできず)「LINEに送りました。」
↓
修正後
Clova:(検索結果を、セッションIDとともにDBに保存)
Clova :「この情報をLINEに送りますか?」
ユーザー:「はい」
Clova:(DBから読み出しして送る処理を起動、戻りを待たずに)「LINEに送りました。」
うーん、背に腹ではあるものの「戻りを待たずに」がひどい。。
お金の勘定が絡むものとか、絶対にやっちゃだめですね。
3. Node.jsのコールバック地獄 (Clovaスキル)
可読性が異様に悪くなって発狂し、或る日突然、async使って書き直しました。
たしか、11月の4日だったと思います。LINE Boot Awardsのファイナルプレゼン大会まであと1週間きってました。
動画撮影の日の朝に大改造してしまい、部分的にしか動かず。
祐天寺駅前のスターバックスで、元木さんと相談しまして、
ちょうどLINEさんにお貸しいただいた、デモ用のXperia ear Duoを使い、口パクでとりました。
ほんとすいません。全部書き直すとか、ほんとやっちゃダメな日だった・・。
差し入れのじゃがいもシュウマイ美味しかったっす。
4. Macのローカルで動かしてて、本番直前にLambdaに移行したら問題噴出 (Clovaスキル)
[LINE Messaging API]のほうはLambdaで何の問題もなかったのですが、
[Clova CEK]のほうは、LambdaからだとDBに書き込みがうまくいかず、発狂してEC2に移行しました。
変更後のアーキテクトは以下です。
- [Clova CEK]=AWS EC2 + Node.js + Ngrok + MySQL
- [LINE Messaging API]= Lambda
LambdaからDynamoDBに書き込みは、Alexaスキルではよくやっているんですが、
Lambda上のNode.jsで、exports.handler = clova.Client
として受け取ったハンドラの中では、
DBのインスタンスが正常に受け取れないという怪現象が起きました。
いろいろためして、Macのローカルと同じく、EC2にNodeのプロセスを起動したらうまくいったので、それで最後まで駆け抜けました。
しかし・・(次へ)
5. EC2だと時々落ちてる・・永続化しなきゃ (Clovaスキル)
nodeのプロセスは、数時間後には落ちてしまいます。
そこで、npmのpm2を使ってデーモン化しました。
6. EC2だとhttps化にお金がかかるじゃないか (Clovaスキル)
LambdaだとAPIGatewayが使え、これなら自動的にhttpsのURLが発行されますが、EC2だとそういう訳にいかず、
手持ちのドメインに「お名前.com」でサブドメインを切り、
Let's EncryptでSSLサーバ証明書を発行したり頑張りました。
しかし問題が・・。
そもそもプロセスがnodeなので、apacheやNginxのように復号化のモジュールが簡単に使えず.
しかたなしに、Macのローカルと同じく、NgrokのクライアントをAWS Linuxにインストールしたところ
あっさり動いたので、そのまま最後まで使いました。
お金さえあれば。。くっ。。
7. ClovaからLINEにメッセージ送るようにしたが、と、・・「友達登録してください」が抜けとるやんけ! (Clovaスキル & LINE Bot)
ClovaからLINEにメッセージ送る際、ユーザー連携が必要になります。
具体的には、Clovaを動かすLINEアカウントで、スマホからBotのQRコードを撮影して、フレンド登録するのです。
私は開発の早い段階で連携してしまったので忘れてましたが、エンドユーザー向けには、
「友達登録がまだのようです」というようなメッセージを出さなきゃなぁ〜と気づいたのが前日でした。
しかし時間切れ。実装まで至りませんでした。
ClovaとBot連携アプリでは、必須のフローだと思います。
8. どのIntentにもヒットしない時のエラー処理が抜けてた(Clovaスキル)
よく聞き取れない時の受け皿。
これを入れたら、スキルが格段に安定稼働しました・・。おまじないみたいなもんですかね。。
クオリティあげの話なので、運用フェイズでは必須かと。
const handle = clova.Client
(略)
.onIntentRequest(async responseHelper => {
const intent = responseHelper.getIntentName();
switch (intent) {
case 'GetCommandElevator_Intent': //エレベーターの場所を応答
(略)
case 'Clova.GuideIntent':
case 'Clova.NoIntent':
var resTxt= 'エレベーターの位置、出口、授乳室、トイレを調べることができます。どれが知りたいですか?';
responseHelper.setSimpleSpeech(
clova.SpeechBuilder.createSpeechText(resTxt)
);
break;
//ここからどのIntentにもヒットしない時のエラー処理
default:
var resTxt = 'すみません。よくわかりませんでした。';
responseHelper.setSimpleSpeech(
clova.SpeechBuilder.createSpeechText(resTxt)
);
}
})
まとめ
よくもこんな状態で人前に出したもんだと、我ながら呆れかえっております。
「らくらく移動ちゃん」の敗因は、「つくりこみの足りなさ」だと思います。
【東京】LINE Bot & Clova CEK開発者2018大忘年会の時に@kenakamuさんに相談したら、
TypeScryptでやったら良かったかもね〜とアドバイスをいただきました。
えっ、、、そうなの。。。!?
年末年始に勉強しようと思います♫
運営面の課題
また、「らくらく移動ちゃん」にはサービスの継続面での課題もあり、
11/10のLINE Boot Awardsのプレゼン時の審査員の方からの質問は、おおきくわけて以下の2点でした。
- どうやって駅情報をメンテするのか?工事情報とか..
- 温泉♨️BBAの名前の由来は何か?
後者はちょっと置いておきまして、前者は大きな課題でした。
もし賞をとれた場合、サービスを一般公開する必要が出てくると思いますが、
ご指摘のあった情報の更新については、ほぼ無策でした。
データの収集が命というサービスは、たった二人の温泉♨️BBAにできるのか。。?
次は、サービスの運営が自動化できる、あるいは、エンドユーザー間で運営が自走するような種類のものを
考えたほうが、良い気がしております。となるとコンテンツ配信ではなく、ツール系になりますかね。
では、みなさま、今年は大変お世話になりました。
来年もよろしくお願いしまーす!(๑˃̵ᴗ˂̵)و