Blueskyユーザ分析アプリ"ひろがるBluesky!"の開発終了報告(と仕組みの説明)

ひろがるBluesky! という、分散型SNS Blueskyの相関図生成・ユーザ分析Webアプリを作っています。

ロードマップの終わり

3月に以下の記事を公開し、開発ロードマップを作りました。
9月14日に公開したバージョンでロードマップをすべて達成できました
達成内容をそれぞれ説明します。

また、この場を借りて、リリース当初に技術的アドバイスをいただいた、あさのさんはじめDiscordメンバ、また、いつもひろがるを使ってポストしていただいているユーザの方々に感謝申し上げます。

どちらかでも欠けたら、間違いなくこのサービスはここまで継続できなかったと思います。
本当にありがとうございました。

類似サービスとの差別化

ユーザ分析機能を追加しました。
具体的には、活動時間の間隔、活動時間のヒストグラム、ユーザポストの頻出単語の表示、特定ユーザへのリプライ数やいいね数を集計表示などが行えます。
Blueskyには既に相関図生成する類似サービスはいくつかありますが、分析機能はないはずです。
分析も含めて楽しんでもらうには、「ひろがる」に来てもらえばいいという土壌は作れたのかなと思います。

パフォーマンス改善

バックエンドにデータベースを採用し、従来の3倍近いレイテンシ向上を達成しました。(生成にかかる時間10秒から3秒ほどに短縮)

ただ、現状は相関図生成時にローディングスピナーを表示していますが、3秒とはいえ進捗が表示されないのは不安になると思っています。
これについては近いうちにプログレスバーによる進捗のパーセント表示を行うことを予定しています。

つながりのインタラクト促進

これは定性的な表現なので達成判断が難しいですね。
ただこれもデータベース採用の恩恵で、従来の9倍近い相関図のアイコン表示が行えるようになりました。(表示37人から271人に増加。もちろん相関図半径を自由に変更可能)

1回リプライやポストしただけのユーザ=自分が少し気になったユーザ を引っ張ってきて表示し再びインタラクトを促す、という点では達成でいいんじゃないでしょうか。(適当)

ただ当時と異なり今はこの目標は現実的じゃないなとも思っています。
理由はいくつかあって、

  • 人間が作って維持できる関係は多くても30人程度が限界かなと思ってきた

  • ひろがるを使ってそこまで輪を広げようとしている人がいないように見える(というか、自分がその行動を拾うすべがない)

  • 自分が陰キャすぎて、輪を広げるのにどんな機能を入れればいいかというイメージがわかず、これ以上のアプローチが難しい(意見ください…)

とかです。
ま、達成ということで許してつかーさい…。

技術的改善(リファクタリング)

WebフレームワークのSvelteを導入し達成しました。
コードの見通しがよくなり、機能追加がものすごく簡単になりました。

継続的なアナウンス

5~7月は予告通り失踪気味でした。すみません。
そもそもクラウド課金が月800円ほど発生していて、サービスたたむかも、とアナウンスしていました。

ただ毎日ひろがるを使ってくださる方もいて、使ってくれる人がいるなら頑張ろうと思い開発再開した次第です。
8月に開発再開してからはアナウンスを心がけています。

バックエンドと各種機能の解説

ここからは開発者向けに、自分の記録もかねて、ひろがるを支えるバックエンドを解説します。

まずバックエンドの構成を説明します。

ひろがる システム図

ホスティングはVercel、データベースはSupabase、一部バックグラウンド処理にinngestを使用しています。
すべて無料サービスで構成されており、制限超過後に自動的に有料プランに移行するなどもないので、安心して継続できる構築になっているはずです。

バックグラウンド処理

ひろがるの処理はメインプロセスとバックグラウンドプロセスに分かれます。

ひろがる シーケンス図

バックグラウンドプロセスにinngestを使用しているのは、Vercelの無料プランに、サーバ上の処理がリクエストを受けてから60秒またはレスポンスを返すまでしか継続できないという制限があるためです。
レスポンスを返すとスレッドがキルされるので、ワーカースレッドを立ててからレスポンスを返すなどしても駄目でした。
かといって長時間ユーザを待たせるのもあり得ないので、数十秒とか時間がかかる処理をVercel無料プランで実行する場合、inngestが必須になってくると思います。

ここからはバックエンド側で色々工夫した点を説明させてください。

CanvasのCORS制約の回避

ひろがるはCytoscape.jsという描画ライブラリを使っています。
Cytoscape.jsはHTML Canvasを使っています。

ひろがるの相関図にはアイコン画像データが不可欠で、これはAtproto側のサーバからもらってこないといけません。

オリジンをまたいだ画像をCanvasで描画するとCanvas汚染が発生するため、クライアント側で直接ダウンロードして描画することは不可能です。
また、サーバ側でダウンロードして保管しておき、ユーザリクエストの際にそれを提供する方法も検討しましたが、Vercel Blobが非常に遅く、大量の画像データを扱うのは難しかったです。

なので、サーバ側でbase64変換した画像データをクライアント側に送ることで対応しています。

base64変換するとデータサイズが増えるので、アイコン画像は低画質のサムネイル向け画像を選択するようにし、少しでもクライアント側の負荷を減らしています。
大体、相関図1回15MBくらい転送していたと思います。

ログイン機能によるシェア手順簡略化

まず現状のシェア手順は、インテント機能を利用したものです。
インテント機能に対してはテキストのみしか渡せないので、相関図画像はユーザにコピー&ペーストしてもらうという形をとっています。

これにはシェア手順が煩雑になるというデメリットがあります。

シェア手順簡略化の一環で、ブラウザのWeb Share APIを利用する方式もプロトタイプを実装しましたが、少なくともiOSのBlueskyアプリが対応していなさそうで、諦めました。

となると、ハンドル名とアプリパスワードでログインしアクセストークンを発行してもらって、それを使ってpostのエンドポイントをたたくのが王道です。

なのでログイン機能を実装しました。
ログインはセッションIDをクライアントとデータベースに置いて検証するセッションID方式を採用しています。
JWT方式だとリスクがあるとかなんとかで、一般的とされるこちらを採用しました。

おわりに

開発終了とは言いましたが、ローディングバーの件や処理の順番に微妙な部分もあるので、今の熱が続く限りはやろうと思っています。
あとまた今回みたくふらっと戻ってきてなんか追加するかもしれません。

機能追加の要望やアイデア、バグ報告などありましたらコメント欄、すいばりへのリプライ、DMなどなど、なんでもお気軽にどうぞ。

ではまた~