システム運用を考慮した上での気を付けるべき点まとめ

## はじめに

現在進行形で運用中の予約システムについて、運用を初めて経験してわかった、気をつけるべきだった点がいくつかあります。
それらを踏まえて、プログラム面とテスト面に分けて、やるべき事を書き出してみました。

一覧で簡単に見返せるようにしたかったため、それぞれを詳細に述べる事はしていません。
システムが仕様通り動けばいいやと思っている方は、運用中に苦労する危険信号が出ていると思いますので、ぜひ参考にしていただけたらと思います。

以下一覧です。

**プログラム面**
- LINE, Slack などのメッセージ送信に関して、誰に対して何のメッセージを送信したかのログを取る
- 運用に直接関係しない通知系の処理は transaction に含めないようにする
- backend で外部 API を使う場合は非同期実行する
- backend で時間のかかる処理は非同期実行する
- jobシステム の監視をする
- 自動テストにおいて LINE・slack メッセージ送信箇所では mock を使う
- 不必要なステータスを増やさないようにする

**テスト面**
- ロールプレイを必ずやる
- 作業手順書を作る
- 本番相当のデータを使ったテストをする

## プログラム面

### LINE, Slack などのメッセージ送信に関して、誰に対して何のメッセージを送信したかのログを取る
  本番運用中にメッセージ送信に関連する箇所でシステムのバグが発覚すると、必ずユーザーに対する影響確認として、ユーザーにメッセージが送信できたかどうか調査する必要が出てきます。

  クライアントが一番気にするポイントはシステムを利用するエンドユーザーに対しての影響が出ない事であり、臨時で行うリカバリー対応により、エンドユーザーへの影響を最小限にとどめる事ができるか？を最優先としています。
リリース前に想定できない事は起こりうるため、必ずリカバリー対応が行えるようログを取る仕組みを導入しておきしょう。

### 運用に直接関係しない通知系の処理は transaction に含めないようにする
  例えば、何かのエンドユーザーが行う処理が成功した時に、それをリアルタイムで確認したい場合に slack 通知の実装を入れる事があると思います。
  ここで問題として発生するのが、slackAPI のような外部 API は、障害を起こしてしまう可能性があることです。
  slackAPI のレスポンスとして正常を受け取るはずが、異常を受け取ってしまう場合が想定されます。
  もし メッセージ送信の処理を、transaction に含めてしまっていると、エンドユーザーが行う処理が成功しているのにも関わらず、slackAPI の障害により、全ての処理がロールバックしてしまいます。
  なので、運用に直接関係しない通知系の処理は transaction に含めないようにしましょう。

### backend で外部 API を使う場合は非同期実行する
  外部 API を使うという事は、外部との通信が発生するという事です。
  エンドユーザーからの瞬間アクセスが多すぎて、外部 API が保証する秒間（あるいは分間）のリクエスト数を超えてしまった時、timeout が発生したりエラーのレスポンスが返却されたりします。
  そうなった時に対応できるよう、backend 側の非同期処理化をして、処理を平すのと、失敗時にはリトライする仕組みを導入しておきましょう。

### backend で時間のかかる処理は非同期実行する
これをやらないとユーザーの体験が悪くなってしまうので、問題として取り上げています。
  時間のかかる処理を行う場合に関しては、最後クライアントサイドに何らかのレスポンスを返す時、その間クライアントを待たせてしまいます。
  なので、時間のかかる処理は非同期で実行されるようにし、メインスレッドでは 1 秒や 2 秒ほどで先にレスポンスを返してあげるようにするのが良いです。
  そして、時間のかかる処理が終わった際に再度クライアント側にレスポンスを返すような仕組みにしましょう。

### jobシステム の監視をする
私の場合、backendの非同期処理を行うための仕組みとして、RubyOnRailsのDelayedJobという仕組みを導入していました。（詳細を知りたい方は[公式ドキュメント](https://github.com/collectiveidea/delayed_job)をご覧ください）

この仕組みでは、DBのレコードにキューを追加していき、管理する仕組みなのですが、エラーのレコードが溜まりすぎると job システムが停止してしまう事があります。
  なので、停止時にも検知できるように cron による定期実行処理を作成し、停止時はslack通知を行うなどの対応で、監視しておくのが良いです。
  この場合、各々のサーバーで起動している job システムを監視したいため、各々のサーバー内で cron による監視をするようにしましょう。（バッチサーバーによる監視はNG）

### 自動テストにおいて LINE・slack メッセージ送信箇所では mock を使う
  LINE や Slack の API では一定時間内のメッセージ送信回数に制限があります。
  自動テストで大量のメッセージを送信すると、制限にかかってしまい、429(Too Many Requests)エラーが出てしまい、正しくテストができなくなってしまいます。
  なので mock を使ってテストをするのが良いでしょう。
  しかし、mock のテストコードしかないと、本当にメッセージ送信がされたかのテストができていない状況になるため、mock を使わない場合のテストもいくつか用意してあげるのが良いと考えます。

### 不必要なステータスを増やさないようにする
  例えば、データベースのテーブルのカラムに status が存在した場合、status は最低限の数になるような設計にした方が良いです。
  理由としては、status が関係する箇所全てのテストパターンが、status の数だけ増えてしまうからです。
  ステータスを増やす検討が始まった場合、今一度、ステータスを増やさなくても判別できないか考えてみるのが良いでしょう。

## テスト面

### ロールプレイを必ずやる
  かなり重要です。実際のシステムを動かし、ロールプレイをすることで、自分が想定している以上に何か不具合が見つかったり、新しい発見があったりします。

  -  漏れているテストケースを発見しやすい
  - そもそもの仕様に問題があり、仕様を修正しないといけない事に気づくこともある
  - バグが見つかったりする
  - 作業手順の誤りや、改善点が見つかる

### 作業手順書を作る
  以下の良い点があると考えています。最初は面倒でも後で楽になるため、作りましょう。

  - 手順に則り実際に作業すると、手順の誤り、改善点が見つかるため、ミスを減らせる
  - 自分が病欠の時に自分以外の人が作業できる
  - あまり頭を使わなくても（脳死で）作業できるため、ミスを減らせる
  - 次に同様・似たような作業を行う時に、コピペで手順書を作れば良いので次からの作業が楽

### 本番相当のデータを使ったテストをする
  本番から dump して取得したデータを使ってテストする事で、想定できていなかったバグが出たりします。（個人情報を扱っている場合はきちんとマスクしましょう）
  また、本番相当のデータでテストして大丈夫だったので、本番でもおそらく大丈夫だろう、という少しの安心も生まれます。
  営業への説得力も増すため、本番相当のデータを使ったテストを行うのが良いです。
  注）データ数が多いからといって、本番相当のデータの一部を取り除いて使用するのはやめましょう。そういうところからバグの見落としが発生したりするためです。（体験談）

## まとめ
システムを運用し、不具合を経験してみていろいろ学んだ点を書き出してみました。
運用前は考えれていなかった事が多いため、反省点が多いですが良い経験だったので、次に活かしていきたいと考えています。