概要
GASでWebサービスをホストしていて、たまに権限を承認しないといけない問題。
利用がないタイミングでそれが訪れても気付けるように、エラー通知はメールが即時に飛ぶようにして、トリガーで定期的にアクセスして検出できるようにしている。
課題
LINE BotのバックエンドにSpreadsheetのGASでWebhookを作成し運用している。
Webサービスをデプロイする際、Webアプリから誰でもアクセスできるようにするため、アクセスを承認する必要がある。
そしてこれがデプロイのタイミングだけかというとそうでもなく、しばらくするとアクセスができなくなり、Webサービスとして機能しなくなってしまう。
そうなってしまったらどうするか。。 いまのところ叩き起こすしかない。
が、気付けないことが問題で、利用者から「止まってるみたい」と通報があって初めて回復措置に動くことになる。
解決方法
根本解決として、明示的に永続的な権限を承認ないし付与することができれば良いのだが、ときどきネットを探すも良い情報に行き当たらず。
次善の策として、定期的にサービスにアクセスし、エラーを起こさせてその通知を受け取るというアプローチをとることにした。
GASではトリガーでスケジュール実行ができる。(ほかに、スプレッドシートやカレンダーがイベントソースとして利用できる)
WebhookはPOSTだが、定期的に死活監視のためのGETリクエストを送ってエラー時はトリガの設定にある通知を利用してメールを受信することにした。
こうすることで、利用者がアクセスし初めてエラーが起きるのではなく、エラーが起きる状態になったら速やかに(トリガの実行インターバルで)通知を受け取り回復措置に動けるようになる。
もちろん自動で回復できればよいのだが、アクセスの承認は人がポチッとやる以外の方法がなさそうなのだ。
実装
簡単なdoGet関数を書き、トリガを作成して一定間隔で実行されるようにします。
// HealthCheck用ダミーGETメソッド
function doGet() {
return ContentService.createTextOutput(JSON.stringify({"success":true})).setMimeType(ContentService.MimeType.JSON);
}
// HealthCheck invoke by scheduled trigger
function checkSelf() {
var url = HEALTH_CHECK_URL;
var response;
try {
response = UrlFetchApp.fetch(url, {
"muteHttpExceptions" : true,
"validateHttpsCertificates" : false,
"followRedirects" : true
});
Logger.log('checkSelf() : ' + response.getResponseCode());
if (response.getResponseCode() != 200) {
// お知らせ
// sendLine(ADMIN_LINE_ID, '寝たかも。 status:' + response.getResponseCode());
}
return 'OK';
} catch(e) {
// 例外エラー処理
Logger.log('Error:')
Logger.log(e)
return null;
}
}
トリガは以下のように設定しています。
checkSelf()の中で自分自身をリクエストし、エラーが起きた場合は「今すぐ通知を受け取る」設定によりメールを受信します。
近況
概ね七日おきに起きている感じである。Gmailで受け取っているので、新着に気づいた時に対処していますが対処するまで繰り返し届くので気付きやすくなりました。
スレッド毎の通数は、気づくまでの15分おきの継続回数。。
今後に向けて
簡単な実験的実装はよしとして、やはり本格的に運用するにはAWS LambdaやGCPのCloud Functionなどを検討すべきだなというところで、来年はその辺もみていきたいと思います。