リアルタイム
聞いている全員に、
そのまま届ける
チャット、プレゼンス、通知、ひとりでに更新されるダッシュボード。1 回の publish で多数の購読者へ、ポーリングなしで届きます。そしてブラウザ向けビルドでは、同じ pub/sub がサーバーなしで、2 つのタブの間で動きます。
なぜ向いているのか——そして、どこで向いていないのか
pub/sub は投げっぱなしです。メッセージはその瞬間に購読している相手へ届きます。1 秒後に接続した人が受け取ることは決してなく、確認応答もありません。プレゼンスの ping やライブなカウンタにはまさに正しく、失って困るものには、まさに間違っています。
メッセージを失うことが問題なら、代わりにストリームを使ってください——キューを参照してください。ストリームは履歴を保持し、コンシューマグループに対応し、オフラインだったクライアントが追いつけます。pub/sub は安い手段であり、その安さが、取引の条件です。
手順
# subscriber
SUBSCRIBE room:42
PSUBSCRIBE room:* # every room, one connection
# publisher — returns how many subscribers received it
PUBLISH room:42 '{"user":"ada","text":"hello"}'
-> (integer) 3
# presence: the TTL does the expiry, the client refreshes every 10 s
SET presence:ada online EX 30
# who is here. on a large keyspace prefer a set:
SADD online ada
SMEMBERS online
SREM online ada同じことを、ブラウザのタブで
import { open } from "@goliajp/kevy";
const db = await open({ persist: { name: "app" } });
// tab A
db.subscribe("room:42", (payload, channel) => {
render(JSON.parse(new TextDecoder().decode(payload)));
});
// tab B — tab A receives it
db.publish("room:42", JSON.stringify({ user: "ada", text: "hello" }));
何を差し出すことになるか
遅い購読者は、いつまでも待たれるのではなく、切り捨てられます。クライアントが追いつけない場合、そのメッセージは、サーバーのメモリを際限なく増やす代わりに破棄されます。意図した選択であり、配信を当てにする前に知っておくべきことです。確認応答も、再送もありません。そのどちらかが必要なら、必要なのはチャネルではなくストリームです。pub/sub のガイドに、限界を具体的に書いてあります。