Slack APIとLambdaの仕様による板挟みを回避した話

はじめに

こんにちは。レバレジーズ株式会社エンジニアの原田です。

私は、レバレジーズのシステムマネジメントチームに所属し、社内の業務改善のため、さまざまなWebサービスの導入や社内ツールの開発を行っています。

例えば、SlackとDocBaseのWebサービス同士のグループを同期させるツールを開発しました。いくつか問題が起きたことがあったので、どうやって対策したのかを紹介させていただきます。

DocBaseとは

DocBaseは気軽に書き込めるナレッジ共有サービスで、弊社では毎日数百件ナレッジが作られ共有されています。 このナレッジの閲覧権限はグループで管理することができ、ユーザーをグループに参加させることで簡単にアクセス権を管理することができます。

同期ツールとは

同期ツールは、AWSのLambda上で動作し、下記のイベントでグループの作成やリネーム、グループ参加者の管理を自動で行うツールです。

f:id:harada9853:20210405140949p:plain

  • Slackチャンネルが作成された
  • Slackチャンネルがリネームされた
  • Slackチャンネルに誰かが参加した
  • Slackチャンネルから誰かが退出した

このイベントをもとに、Slackチャンネルと同名のグループをDocBase上に用意します。その後、Slackチャンネルに参加しているメンバーをグループ参加者として追加する動作を行います。

ただし、稀にSlackからのイベントを取得できないことがあり、「ナレッジを閲覧することができない」お問い合わせが発生することがありました。そのため、定期的にSlackチャンネルの情報をDocbaseに一括して同期するバッチ処理を追加で作ることにしました。

バッチ処理の内部動作

当初、バッチ処理は以下の図のように動作させることを考えていました。

f:id:harada9853:20210405141055p:plain

早速バッチ処理用のLambdaを作成し、Slack APIを使って実装を行いました。 動作確認のためテストを行ったところ、次のような問題が発生しました。

  • 一定期間内におけるSlack APIの実行回数上限を上回ってしまう
  • Slack APIの実行回数上限を超えないようウエイト処理を挟むと、Lambdaの実行時間上限を超えてしまい処理が中断される

この時上限に達することを想定していなかったため、どのように問題を解決すれば良いかとても困った記憶があります。

なぜ上限に達したのか

Slack APIには毎分実行できるAPIの実行回数が設定されており、それを超えると429エラーが返ってくるよう設計されています。 なのでAPIを実行した後に2 ~ 3秒のウエイト処理を実行することでこの実行回数上限は回避できる、という仕様が存在します。

また、Lambdaは15分以上実行させようとするとタイムアウトしてしまい、処理が中断してしまうという仕様が存在します。

今回の追加開発では全Slackチャンネル情報が必要になるため、Slackチャンネル数分APIを実行する必要がありました。 この時、APIの実行が必要な回数は3,000回を上回っており、ウエイト処理を実行させると15分以上処理に時間がかかるため、Lambdaが途中で処理を中断させてしまうのです。

どのように解決したか

Slack APIとLambdaの仕様をチームメンバーに伝え、どのようにこの問題を解決するか相談したところ「1度にまとめてやろうとせず、処理を分割して行う」方針で解決する話になりました。

処理を分割すれば、Lambdaの実行時間上限を超えないようSlack APIを実行できるのでSlack APIとLambdaの仕様どちらも解決可能です。

f:id:harada9853:20210405141113p:plain

こうして、同期ツールのバッチ処理開発を行うことができ「記事が閲覧できない」というお問い合わせを大きく減少させることができました。

もし、同じように困っている方がいましたら、参考にしていただけますと幸いです。

まとめ

今回の問題に遭遇したことで、予め上限や制約などがないか調べる癖を付けると良いなと実感しました。

レバレジーズでは、業務上の問題や課題は、一人ひとりの問題ではなく、チームメンバー全員の問題や課題として扱うことで自然と知見を共有できるため、すぐに問題解決が行えます。

システムマネージメントチームでは一緒にレバレジーズを支えてくれる仲間を募集しています!ご興味を持たれた方は、下記リンクから是非ご応募ください。
https://recruit.jobcan.jp/leverages/