コンテンツにスキップ

配管を書かずに、リアルタイムな部屋を作る

本番稼働中のリアルタイムアプリから切り出した、小さな依存ゼロのパッケージ3つ。デプロイを生き延びる WebSocket トランスポートと、サーバーなしでテストできる状態 store。
$npm install @insession/space-state @insession/ws-resilient-transport

@insession/ws-resilient-transport

本番デプロイの都合に合わせて再接続する WebSocket トランスポート。サービス再起動時は即座に、 それ以外はジッター付き指数バックオフで、terminal な close code なら再接続を完全に止める。

依存ゼロ約130行

@insession/space-state

共有ルームの状態(メンバー・チャット・プレゼンス・プラグイン)を持つ store。受信は純粋 reducer で畳み込み、副作用は実行せず記述子として返すだけ。

依存ゼロ純粋 reducer

@insession/space-state-react

space-state の React バインディング。useSyncExternalStore を包む フック1つ・約10行で、ロジックは一切持たない。

フック1つreact は peer

3つの間にある依存は space-state-reactspace-state の1本だけ。 ws-resilient-transport は独立しています — バイトを運ぶことと状態を持つことを意図的に 切り離してあるので、どちらか一方だけを採用できます。

下に何も入らない

トランスポートと store のランタイム依存はゼロ。フレームワークもソケットライブラリも DOM も 要りません。これは偶然ではなく、このパッケージの狙いそのものです。

サーバーなしでテストできる

store はただのオブジェクトを受け取り、ただの記述子を返します。だから状態遷移まるごとを node —test のプロセス内で assert できます — ブラウザもソケットも実時間の待ちも不要。

実際のデプロイが形を決めた

再接続の挙動は「デプロイのたびに全クライアントが同時に切れる」という現実から来ています。 サービス再起動時は高速に、ジッターで殺到を避け、サーバーが二度と受け付けないと言ったら止まる。