Rabbitのキャッシュ・バッチ化の仕組み
by
Syusui Moyatani
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
Rabbit🐰の キャッシュ・バッチ化のしくみ @syusui_s Rabbitのキャッシュ・バッチ化の仕組み © 2023 by Syusui Moyatani is licensed under CC BY-SA 4.0
Slide 2
Slide 2 text
自己紹介 しゅうすい @syusui_s Webエンジニアです。 ● Scrapbox書いてます(仕様や使い方) ● Nostrクライアントを作っています 0:10 +30
Slide 3
Slide 3 text
🐰Rabbit TweetDeck風クライアント https://syusui-s.github.io/rabbit/ ● 軽快な動作 ● マルチカラム ● ショートカット 0:40 +20
Slide 4
Slide 4 text
投稿の表示が大変 外部 サーバの 画像 プロフィール (kind0) リポスト数 (kind 6) リアクション数 (kind 7) 色々な関連情報が必要になる 1:00 +20
Slide 5
Slide 5 text
毎回取得すると遅い 表示のたびに取得するのは遅くて通信量も多い ● プロフィール等の表示が遅くなる ● スマホの通信量を消費してしまう ● サーバの制限に引っかかる ○ 一部リレーは購読数を制限している 1:20 +20
Slide 6
Slide 6 text
通信量・回数を減らす仕組みが欲しい Rabbitでは以下の手法を取り入れています ● キャッシュ ○ データを保存し、しばらくの間再利用する ● バッチ化 ○ 複数のイベントに対する購読をまとめて行う 1:40 +10
Slide 7
Slide 7 text
キャッシュ 1:50 +5
Slide 8
Slide 8 text
キャッシュ データを保存し、しばらく再利用する仕組みのこと ● プロフィール ○ あまり変更されないので、使いまわしても問題が少ない ○ 保存すればアイコンと名前がすぐに見られる ※他にもキャッシュできるものはあるが時間の都合で割愛 フォロー一覧、リポスト数、リポストされた投稿など 1:55 +15
Slide 9
Slide 9 text
TanStack Query 通信向けのキャッシュライブラリ 特徴 ● SWR戦略に基づく ● SolidJSに対応 1:15 +15
Slide 10
Slide 10 text
単純なキャッシュの仕組み 保存したデータはいつかは古くなり、再取得が必要 保存期間を決めておき、時間が経ったら破棄 有効 (データは新しいはず) 破棄 破棄までの期限 保存 1:30 +30 破棄すると、読み込みでユーザを待たせてしまう
Slide 11
Slide 11 text
SWR戦略 (stale-while-revalidate) 期限が切れてもすぐに削除せず一旦持ってるデータを表示 その裏で新しいデータを取得し、画面に表示する 有効 (データは新しいはず) 期限切れ (古いはずだが持っておく) 破棄 有効期限 破棄期限 保存 読み込みでユーザを待たせない 2:00 +30
Slide 12
Slide 12 text
通信の流れ クライアント リレー キャッシュ機構 Aさんのプロフィールがほしい Aさんのプロフィールです Aさんのプロフィールがほしい Aさんのプロフィールです 一旦今あるAさんのデータを返します Aさんのプロフィールがほしい Aさんのは保存してたのがあるよ Aさんのプロフィールがほしい stale Aさんのプロフィールがほしい 新しいAさんのプロフィールです 有効 期限切れ Aさんのプロフィールです 3:00 +60
Slide 13
Slide 13 text
TanStack Queryを使う上での課題 Promise前提 nostr-toolsのコールバックスタイルから変換が必要 4:00 +10
Slide 14
Slide 14 text
イベントのPromise化 まずは単純に一件だけのキャッシュに対応 プロフィール1件、リポストされたイベント1件 など ※nostr-toolsを使っています 4:10 +20
Slide 15
Slide 15 text
複数イベントの場合 更新があるたびにキャッシュを更新 割とゴリ押しな実装… 4:30 +30
Slide 16
Slide 16 text
バッチ化 5:00
Slide 17
Slide 17 text
単純に購読すると クライアント リレー Bさんのプロフィールがほしい Cさんのプロフィールがほしい Aさんのプロフィールがほしい Dさんのプロフィールがほしい Eさんのプロフィールがほしい そんなにリクエストしないで! (イベントEの取得失敗) 5:00 +10
Slide 18
Slide 18 text
動機 一部のリレーは購読数の制限がある (おそらく負荷軽減のため) 制限回避のために 購読数を少なく保ちたい 5:10 +10
Slide 19
Slide 19 text
バッチ化 複数の購読(REQ)を一つの購読にまとめる仕組み kinds: [0] authors: ["8234…e6a2"] kinds: [0] authors: ["3bf0…459d"] kinds: [0] authors: [ "8234…e6a2", "3bf0…459d" ] プロフィールの問い合わせを統合する例 5:20 +20
Slide 20
Slide 20 text
バッチ化 クライアント リレー バッチ化機構 Aさんのプロフィールがほしい Bさんのプロフィールがほしい Cさんのプロフィールがほしい まとめてA,B,Cのプロフィールがほしい Aさんのプロフィールです 3秒 Aさんのプロフィールです Bさんのプロフィールです Cさんのプロフィールです 3つのリクエストを1つにまとめられた Bさんのプロフィールです Cさんのプロフィールです レスポンスの振り分け 5:40 +60
Slide 21
Slide 21 text
レスポンスの振り分け kind: 0 pubkey: "8234…e6a2" content: {"name":"jack"} kind: 0 pubkey: "3bf0…459d" content: {"name":"fiatjaf"} 公開鍵 resolver "8234…e6a2" () => { … } "3bf0…459d" () => { … } Promise Promise ※new Promise((resolve) => …) の resolve関数をMapに保存しておく 公開鍵等のIDに基づいてPromiseをfullfillする 6:40 +60
Slide 22
Slide 22 text
詳しく知りたい人は https://gist.github.com/syusui-s/745a2b507744 073f9009c94222ad78fc 7:40 +10
Slide 23
Slide 23 text
最後に キャッシュとバッチ化で効率よく通信できる 今後の展望 - 楽観的mutation - プロフィール変更、リポスト、リアクションを即座にキャッシュに反映する - タイムラインの情報を拾ってキャッシュに乗せておく - 投機的キャッシュ - 投稿を投機的にキャッシュに乗せて、リポスト等の表示を効率化する - InfiniteQueryによるタイムライン自体のキャッシュ - いつかこの辺に対応したクライアントライブラリを作りたい…
Slide 24
Slide 24 text
おまけ: 発表で話せなかったところ
Slide 25
Slide 25 text
プロフィールのキャッシュ時間の工夫 staleTime: 5分 名前やアイコンがすこし 古くてもあまり問題ない cacheTime: 1日 よくTLに居る人を キャッシュするように 3:00 +30
Slide 26
Slide 26 text
プロフィールのキャッシュ時間の工夫 staleTime: 4時間 投稿は編集できないので 期限切れにしなくてOK cacheTime: 4時間 時間が経ったらリポストは されないので4時間程度で ■■さんがリポスト ●●さんがリポスト