エンジニア達はどう影響を与え合っているのか!?可視化してみました
いつものようにTwitterを眺めていたところ、Auth0のアカウントの
「あなたに影響を与えた開発者は誰?」
というツイート
に対して答えているツイートが流れてきました。
このリプライツリーを眺めると
- 気になっているエンジニアに影響を与えたエンジニア
- まだ見ぬ面白いエンジニア
を知れて面白そうだぞ!
Twitter上でみるのはなかなか大変なので別の表現にしてみよう!
と思いサービス化してみました。
開発周りの諸々
大枠としては
- Twitterからの情報を取得するElixirアプリケーション
- それを表示するNext.jsアプリケーション
になっています。最近Elixirにハマって楽しんでいるのでElixirです。
カオス気味ですが一応コードを公開してます。
ツイートの収集
これはTwitter API v2を使いました。
実はTwitter API v1.1では、あるツイートからリプライで繋がってできるグラフ上のツイートを検索するということが簡単にはできませんでした。これが、Twitter API v2で conversation_id
で検索できるようになりました。
ElixirだとextwitterといったTwitter APIクライアントがあるようでしたが、v2周りはまだ実装されていないようだったので自分でhttpクライアントで叩きました。
Cloud SchedulerとCloud Runで定期実行しようかなと思い、Plugを使ったHTTPサーバになっています。
収集したデータの保存
結論から言うとFirestoreに入れることにしました。
- 静的ファイルとして、公開リポジトリに収集したツイートを含めるとなると、Twitterのポリシー上idしか含められず不便
- 利益を生まない趣味開発なので運用コストは金銭的にも労力的にも小さくしたかった
- Elixirだと、Firestoreをどの程度の開発コストで使えるのか試してみたかった
最後に関しては、予想していたよりも大変でした。
一応googleapis/elixir-google-apiはあるのですが、コードもドキュメントもスキーマから自動生成されている雰囲気です。 batchWrite
したいだけだったのですが、それでもそれなりの試行錯誤が必要でした。
可視化
Cytoscape.jsというグラフ描画用のライブラリに頼りました。
全データを使うと、データの転送量的にも計算の重さ的にもまともに使えなかったので、メンションを10回よりも多くもらっているユーザのみを表示することにしました。エッジは表示されているユーザ間のメンションのみ残しています。
デプロイ先
- 英語圏でも見てもらえたら嬉しいのでCDNを使いたい
- コストは可能な限り抑えたい
のでVercelにしました。
- データが頻繁に変化しない
- 表示のためにFirestoreから取得するデータ量がそれなりにあるので、レイテンシ的にも、費用的にも毎回Firestoreから取得させたくない
ということで revalidate
を大きくしたIncremental Static Regenerationになっています。
課題
ユーザのプロフィール画像周り
- Twitterのプロフィール画像URLは、ユーザがプロフィール画像を変更するとすぐに404になってしまう
- cytoscape.jsでノードの
background-image
が404の場合、その場でエラーになってグラフ描画が途中で止まってしまう
のですが、404時の対応はcytoscape.jsのコードを少し読んでみたもののサッと解決できそうにはなかったので、とりあえずプロフィール画像をbase64で埋め込んでいます。HTMLドキュメント自体が結構デカくなってしまっているしキャッシュの効率も悪いと思うので、自分のオブジェクトストレージに入れるか、404になったときの工夫を何か入れた方がいいかなと思いつつ…
本当に欲しい情報がとれているか?
エッジをタップするとツイートが表示されるのでみていると「ありがとー」と言っているだけのツイートもあったりします。表示するユーザをメンション数でフィルタリングしていますが、複数回リプライでやりとりしているだけだったりというのもあったり、「影響を与えた」という情報のみを取り出すことはできていません。
またTwitterアカウントを持っていない人をテキストで上げているツイートもあるので、そういうものも抽出できるとよさそうだなぁなど、ちゃんとやろうと思うといろいろありそうです。
埋め込みツイートが激重
Twitterのwidgetを使っているのですが、埋め込みツイートが複数あると数千リクエスト、数百MB転送と、とんでもないことになります。大量に読み込みうるところは、一応ボタンでワンクッションおくようにしてみました。
最後に
以上です。
Firestore周りのこともあり、全部Nodeで書いた方がだいぶ楽だった感はあります。Elixirでの知見が少し溜まったのでよしとします。
いろいろ課題はありつつも、自分で触っていても結構楽しいです。よかったら触ってみてください!
Discussion