「リアルタイム更新」の正体は cron と静的ファイルのコミットだった

転職用のポートフォリオとして、個人でWebアプリ「Hubpin」を作っています。
制作の経緯は「Hubpin 開発記録」に時系列でまとめています。
設計と判断は自分で行い、実装も原則自分で書いています。AIには手順書・レビュー・調査を任せています。

アプリの題材を探しているときに、開催中の競技の結果をほぼリアルタイムに出している個人サイトを見つけました。
サーバーを持っていないように見えるのに、更新が速い。
不思議でした。
どうやっているのか気になって、公開されているコードを読みました。
1918行ありました。

先に書いておくと、対象は MIT ライセンスで公開されているリポジトリです。
読んだ目的は構造を知ることで、評価ではありません。
以下は「そうなっていた」という記録です。

目次

結論: 高度なことは何もしていなかった

更新スクリプトとワークフローを読んだ結果はこうでした。

GitHub Actions の cron で外部データを取り、取得した JSON をリポジトリにコミットして静的配信していた。

常時起動のサーバーも、WebSocket も、データベースもありません。
定期実行と、ファイルのコミットだけ。

リアルタイム性は3つの掛け算だった

面白かったのは、「速い」が単一の技術で成り立っていなかったことです。
掛け算でした。

要素 中身
サーバーを持たない 取得した JSON をリポジトリにコミットして静的配信。差分がなければコミットしない
監視する時間を絞る 試合は 13:00〜18:50 にしか起きない。24時間回す必要がない
叩ける穴があった 公開元サイトの内部通信が実質 API になっていて、HTML を解析せずに済む

3つ目はデータの取り方の話なので、ここでは深追いしません。
別の記事の領域です。
自分が持ち帰りたかったのは、上の2つのほうです。

とくに2つ目が効いています。
「リアルタイム」と聞くと常時接続を想像しますが、
更新が起きる時間帯にだけ短い間隔で叩けば、見え方は同じになります。
必要だったのは常時接続ではなく、更新が起きる時間帯だけ叩くことでした。

細部に運用の工夫が入っていた

読んでいて、細かいところに手が入っているのが分かりました。

  • 取得の間隔にランダムな揺らぎを入れている(random.uniform(0, 1)
  • リクエストの間に 0.3 秒の待ちがある。コメントに「サーバーに礼儀正しく」と書いてある
  • 失敗したときは、間隔を空けながら再試行する

どれも、動かすことより「動かし続けても迷惑をかけない」ための工夫でした。

さらに、オフシーズンの扱いもありました。
定期実行のワークフローが手動専用に落としてあって、
コードの中にはスケジュール実行を前提にした記述が残っています。
シーズンが来たら戻す運用に見えました。
止めっぱなしではなく。
「動かし続ける」というより「動かす時期を決める」形です。

自分の設計に持ち帰ったこと

いま作っているアプリでも、外部のフィードを定期実行で取ってきて、データベースに置く構成にしています。
表示のたびに外部を叩かず、取っておいたものを出す。
同じ考え方でした。

この構成は、面接で聞かれる論点そのものだとも思っています。
「なぜ表示時に外部 API を叩かないのか」。
答えは、外部が落ちていても自分のページは出せるからで、
その判断ができるかどうかが見られる部分なんだろうと思っています。

読む前は、リアルタイムに見えるサイトは何か特別なことをしていると思っていました。
「リアルタイムに見える」と「リアルタイムである」は別でした。
求められているのが前者なら、定期実行と静的ファイルで足ります。
それで足りていました。

目次