新卒が社内懇親会アプリを開発したら、障害対応まで経験できた話

こんにちは。
2019年4月に新卒入社しましたサーバサイドエンジニアのたかです。
社内懇親会のコンテンツにて、新卒エンジニアが奮闘した記録をご紹介させていただきます。

発端

マネーフォワードでは、半期ごとに全社員が集まり、各事業の振り返りやワークショップを行う半期総会を開催します。

そんななか、総会・懇親会を運営担当から
「半期総会後の社内懇親会、新卒でコンテンツを運営して欲しい」
と依頼があったことが始まりです。

要件は
1. 懇親会コンテンツの時間は40分
2. 目的は社内コミュニケーションの活性化

そこで、往年の人気クイズ番組『クイズダービー』をマネフォ風にもじった『MFクイズダービー』を企画することに決まりました。

そして、「せっかくならゲーム進行に必要な部分を自分たちで作っちゃおう」という流れになった次第です。

 

どんなアプリケーション?

ゲームのフロー

  1. 解答者チームと投票者チームに分かれる
  2. 4択のクイズが出題される
  3. 解答者チームは投票者チームに分からないように解答する
  4. 投票者チームは正解する解答者チームを予想し、自分の持ち点からいくらポイントを預けるか決め、投票する。
  5. 投票した解答者チームが正解した場合は預けたポイント x 倍率 の得点を獲得。不正解だった場合は預けたポイントは没収される。倍率は各問題、解答者チームごとに異なる。

この流れを6回繰り返し、総得点上位6つの投票者チームに食事券のプレゼントを贈呈する、というゲームです。

システム概要

  • 投票者グループの作成
  • 問題や問題ごとの倍率の表示
  • 得点を預ける処理
  • 倍率を含めた払い戻しの処理
  • 投票者チームの順位表示

など、このゲームを進行するにあたって必要な部分を新卒エンジニアで作成しました。

以下に実際のアプリケーション画面の一部を紹介します。

投票画面

最終結果画面

(花火の打ち上げには相当こだわっています)

 

使用した技術スタック

Ruby on Rails / Javascript (anime.js / p5.js) / MaterialDesignLite
heroku / cleardb / db: hobby dyno: hobby

 

開発の進め方

プロトタイプをもとに、開催日の1週間前の日曜日から開発開始。

自分は主に、投票ポイントと各解答者チームの倍率から投票者チームごとのポイントを計算するロジック、各投票者チームへの反映部分、を開発しました。

最初は1人で作っていましたが、新卒のエンジニアをどんどん巻き込み、最終的には6人のエンジニアで開発を進め、なんとか当日の朝に完成することができました。

発見したバグや改修ポイントをGitHubのprojectで管理し、各々得意な分野のissueを片付けていました。

GitHubとSlackを連携させることでmergeを全チームメンバーで共有していたことや、GitKrakenを使ってmergeによって発生したバグの切り分けなど、限られた時間の中で、開発効率を上げられるようなツールや仕組みがチームの中に浸透していたことは、期限までに完成できた要因の1つだと思います。

 

当日の悲劇

と、ここまで順調で、当日も大成功!

かと思いきや、実は当日、サービスがダウンしてしまいゲームを最後まで終えることができませんでした。。。

障害は2回にわたって発生し、1回目は1問目の投票状況をリアルタイム表示する画面でサービスが停止しました。

その時のエラー、、、

ActiveRecord::StatementInvalid
(Mysql2::Error: User '**************' has exceeded the 'max_questions' resource (current value: 3600):
SET NAMES utf8,  @@SESSION.sql_mode =
CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), 
@@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483):

解答者チームに投票された様子をリアルタイムにグラフで表示する機能を、JavaScriptのsetintervalを使って3秒おきにリロードするという仕組みで実装していました。

つまり、3秒ごとにherokuのdbへクエリが走っていて、herokuの1時間当たりに発行できるクエリ数(3600)を超えてしまったためにアプリケーションが落ちてしまいました。

後からSQLの発行数を調べると3秒おきのリロード時に12クエリが走っていたことがわかったので、900秒(15分)で上限の3600クエリに達してしまう計算になります…。
1時間あたりに発行できるクエリ数に上限があることをこのときまで把握していませんでした。

大慌て(大騒ぎ)で修正している様子

ゲーム序盤でのシステム障害だったため開発陣はかなり焦りましたが、先程説明したjsのsetintervalによる3秒おきのリロードが怪しいと決め打ちし、その部分のコードを削除してherokuへ再デプロイしたことでゲームの再開をすることができました。
(投票状況のリアルタイム表示は諦め、運営側が適宜リロードを挟む形で対処しました。)

デバッグ完了!

1問目、2問目の投票や結果の表示まで問題なく動作し、これで安寧を取り戻したかのように思えました。
が、3問目の結果表示で同様のエラーで再びシステム障害が発生しました。

1回目の障害時に、もう一度障害が発生した時はシステムを使わずバックアップ用の手段でゲームを進行することを決めていたので、当日はこれ以上深掘りしませんでした。
時間がかなり後ろ倒しになってしまっていたので、最終的にじゃんけん大会を開いて食事券を争ってもらうという形で何とかMFクイズダービーを締めました。(クイズとは)

哀愁漂うデバッグ跡地

 

全体振り返り

アプリケーションを落としてしまったことがどうしても悔しくて、後日エンジニア内で検証を行いました。

特に2回目の障害の原因が特定できていなかったのでそこを調査することにしました。
断定はできていませんが、システムとして負荷が一番高いと思われる、各投票者チームへのポイントの反映部分に問題があった (発行されるSQLが非効率だった) のではないかという意見で一致。
RailsのActiveRecordの裏側でどんなSQLが走っているのか、その視点がチーム全体で大きく抜け漏れていました。

またエンジニアだけでなくビジネス職のメンバーも含めた全体の反省会も有志で開きました。

良かった点

  • 各個人の与えられた仕事をやり抜く力が高い
  • 会場レイアウト設営の手際の良さ
  • MFクイズダービーというコンテンツとしての面白さ
  • システムも作り込めた
  • 問題の難易度がちょうどよかった

悪かった点

  • 全体的にスケジュールが後ろ倒しになっていた
  • キックオフから開発スタートまで遅かった
  • タスク管理を始めたのが最後の最後になってから
  • 機材(マイク音声が一部聞こえない)トラブル
  • 当日の運営サポート役を用意していなかった
  • 当日の参加人数など不確定要素がある状態だった

などなど、予定では1.5時間ほどのMTGでしたが、気付けば3時間ほど話し込んでいました。(良くないMTGの例)

スケジュールに合わせてどうタスク管理していくかは、今後の業務にも活きてくる部分なので、そこをしっかり全体で反省できたことは大きな価値になると思っています。

 

個人的総括

良かった点

1度目の障害から復旧したあと、数問ですが正常なゲームフローを楽しんでもらえる時間がありました。

参加者が自分たちのシステムを触って、ポイントの増減で一喜一憂し、結果発表画面で盛り上がって、そんな様子を運営の立場から見ていて、作ったものをユーザに届けて使ってもらう喜びを強く感じました。
だからこそ最後までMFクイズダービーを完遂させたかった‥。
(ちなみに盛り上がりのピークは2度目の障害画面が表示された瞬間だったと記憶しています。笑)

また、妥協を許さない空気が開発チームの中にあったなと思います。
いかに結果の表示画面を作り込むか、いかに投票の不正を防ぐか、いかにユーザの使いやすさを高めるか、延いては如何にMFクイズダービーを楽しんでもらうか、そこは開発メンバーがそれぞれこだわりを持って取り組んでいました。
(同期のビジネス職の子からこだわりが強すぎて少し引いたとまで言われるレベル)

さらに自分も含め開発チーム全員が楽しみながら開発をしていたことも印象的です。

懇親会後、社内の方々から我々新卒のチャレンジを歓迎するような温かいコメントをたくさん頂きました。
失敗を恐れずチャレンジしようという社内の雰囲気を改めて感じることが出来て、今後の業務を通じてチャレンジすることへの障壁が取り除かれたように思えました。

上はセキュリティ担当役員、下は人事担当役員からの心温まるメッセージ

解答者チームの方々

反省点

本番当日にサービスを停止し、継続できなかったこと、これに尽きると思います。
重ねて、デザイン面や演出面に多くの時間を割いてしまい、本番を想定した規模での運用テストをしていなかったことは大きな反省点です。

また懇親会後はもう開発する必要がないからという理由で、保守性や拡張性の低いコードを乱立してしまったこと。
(slimファイルにjsとスタイルをまとめて書いたり、コメントが全くなかったり、ロジックが適当だったり )

それにより、新しく開発に加わったチームメンバーが困惑するという影響もありました。

保守性や拡張性を意識して効率のいいコード書こうという意識を持っていれば、チーム全体の開発スピードをもっと上げられただろうし、非効率なSQLが走っているということにも気づけたかもしれません。

ただ、これは懇親会を終えた今だからこそ言える事であるとも考えていて、懇親会の当日までに完成するか分からない不確実性の高い状態で、効率性や保守性とどう折り合いを付けていくかは難しい点だなぁと思っています。

 

感想

クオリティへのこだわりから圧倒的睡眠不足に陥ったり、本番で障害を起こしてしまったり、ネガティブな要因はありましたが、一言でまとめると 「楽しかった」 です!

自分が別の作業に取り組んでいる間に、UIがめちゃくちゃ進化していたり、かゆいところに手が届く機能が実装されていたり、チーム開発のパワーを存分に感じることが出来ました。
また、改めて同期の技術力を肌で感じて、自分も負けたくない、もっと技術力を付けていきたいという気分にさせられました。
これからも同期の動向には目を配って、お互いに刺激を与え合う関係でいられたらなと思っています。

システム外のところでは、新卒同期のデザイナーが素敵なロゴやスライドを作成してくれたり、同期のビジネス職のメンバーが当日の誘導や細かい道具の用意、司会を請け負ってくれたり、エンジニア、ビジネス、デザイナー三位一体となってこの懇親会というプロジェクトを進めることができ、新卒全体でTeamworkを発揮できていたと思います。

いつか必ずMFクイズダービーのリベンジをしようと開発チームで話しました。
(次のコンテンツの草案が出ていたり)

それまでに業務を通じて各々スキルアップして、次こそは大成功を収めたいです!

思いの外盛り上がったシステム障害後のじゃんけん大会

 

最後に

マネーフォワードでは、エンジニアを募集しています。
ご応募お待ちしています。

【採用サイト】
マネーフォワード採用サイト
Wantedly

【マネーフォワードのプロダクト】
お金の見える化サービス 『マネーフォワード ME』 iPhone,iPad Android

ビジネス向けバックオフィス向け業務効率化ソリューション 『マネーフォワード クラウド』

おつり貯金アプリ 『しらたま』

おトクが飛び出すクーポンサービス 『tock pop』

金融商品の比較・申し込みサイト 『Money Forward Mall』

くらしの経済メディア 『MONEY PLUS』

本業に集中できる新しいオンライン融資サービス 『Money Forward BizAccel』

Pocket