Google Apps Scriptとスプレッドシートで非同期処理(Queue)
はじめに
今回、とある社内のフローを効率化するため、Slackとスプレッドシートを連携するツールをGAS(Google Apps Script)で開発することになりました。
しかし、開発を進める中で、いくつかの大きな壁にぶつかりました。
直面した問題
1. スプレッドシートのアクセス権限
社内情報ということもあり、スプレッドシートのアクセス権限は「組織内のみ」に制限されていました。
GASで作成するAPIも同様に制限され、外部からのSlack Webhookリクエストを直接処理できませんでした。
2. Slack APIのレスポンスは3秒以内
Slack APIでは、3秒以内にレスポンスを返す必要があります。
しかし、GASからスプレッドシートの参照・更新処理を行うには時間がかかり、この制約が大きな課題となりました。
試した方法
1. Cloud FunctionsからGASをコール
GCPのサービスアカウントが必要で、権限付与も煩雑でした。
そもそも、GASの関数をコールするのに3秒以上かかってしまうようでした。
2. 他のGASからGASをコール
権限付与の問題は解決できませんでした。
同様に、GASの呼び出しに時間がかかりました。
3. GASのトリガー機能で遅延実行
そもそも、GASの処理内でトリガー設定するのに3秒以上かかり、断念しました。
Queueで非同期実行しよう!
これらの問題を解決するために、Queue(キュー)を用いた非同期処理の仕組みをGAS上に実装しました。具体的には、以下の2つのGASプロジェクトとスプレッドシートを用意しました。
Queue(キュー)用GASプロジェクト + スプレッドシート
Slackなどからのリクエストを受け付け、処理待ちのデータをスプレッドシートに蓄積します。
このGASプロジェクトは、外部からのリクエストを受け付ける必要があるため、ウェブアプリケーションとして公開します。
Worker(処理実行)用GASプロジェクト + スプレッドシート
定期的にQueue用スプレッドシートを監視し、処理待ちのデータがあれば処理を実行します。
このGASプロジェクトは、外部からのリクエストを受け付ける必要はありません。
この構成により、Slackなどの外部からのリクエストはQueue用GASプロジェクトが即座に受け付け、処理はWorker用GASプロジェクトが非同期で実行するため、3秒のレスポンス時間制限をクリアすることができます。また、スプレッドシートのアクセス権限も、Queue用とWorker用で分離することで、セキュリティを確保することができます。
ソースコード
検証用の実装はClaspというパッケージを利用して開発しました。
ソースコードは以下のリポジトリを参照ください。
Queueクラス
キューの追加(enqueue)と取得(dequeue)を行うシンプルなクラスです。
排他ロッククラス
Worker側で重複実行を防ぐための排他ロックをGASのキャッシュ機能で実装しました。
Queueメイン処理(doPost)
外部からのリクエストを受け取り、キューに追加します。
Workerメイン処理(handleQueue, addTrigger)
キューからデータを取り出し、処理を実行します。
定期トリガーでhandleQueueを1分ごとに実行します。
GASの追加手順
1. Queueのソースをデプロイする
Queue用のスプレッドシートを作成し、GASを作成。
Claspからソースコードをデプロイします。
2. Queueをウェブアプリとして公開する
Slack APIなどからアクセスできるよう、ウェブアプリとして公開し、URLを控えます。
3. Workerのソースをデプロイする
WorkerのGAS単体としてClaspでソースコードをデプロイします。
4. addTriggerを実行する
Workerのデプロイ後、addTrigger関数を実行してトリガーを追加します。
Queueを実行してみる!
今回の検証では、以下の手順でQueueシステムの動作確認を行いました。
1. APIクライアントツールでデータ送信
PostmanなどのAPIクライアントツールを使用し、Queue用GASプロジェクトのウェブアプリケーションURLへPOSTリクエストを送信しました。
2. Queueスプレッドシートの確認
データ送信後、Queue用スプレッドシートを開き、送信したデータが新しい行として追加されていることを確認しました。
3秒以内に処理されていることも確認しました。
3. Workerログの確認
Worker用GASプロジェクトの実行ログを確認しました。
ログには、WorkerがQueueスプレッドシートを定期的に監視し、新しいデータを発見して処理を実行した記録が残っていました。
まとめ
今回の開発では、GASを用いてSlackとスプレッドシートを連携させるツールを構築し、Queueによる非同期処理を実装しました。これにより、Slack APIのレスポンス時間制限をクリアし、スプレッドシートのアクセス権限の問題も解決できました。
Worker側の処理が1分ごとのトリガー実行であるため、即時性は求められませんが、社内ツールとしては十分機能します。GASだけでも工夫次第で様々なツールが開発できることを実感しました。
ただし、今回の構成では以下の点に注意が必要です。
- 排他制御の実装
- エラーハンドリング
- トリガーの管理
- スケーラビリティ
これらの点を考慮することで、より安定したシステムを構築できます。
GAS開発を行う上で、今回の経験が参考になれば幸いです。
Discussion