Bedrud ドキュメント

このドキュメントでは、Bedrudのシングルバイナリアーキテクチャの背後にある内部技術的判断について説明します。

1. Fiberから標準ライブラリへのブリッジ

Bedrudは速度のためにFiberを使用していますが、Goth(OAuth)やLiveKit SDK(Twirp)などの一部の依存関係は標準Goのhttp.ResponseWriterhttp.Requestを必要とします。

これら2つの世界を橋渡しするため、Bedrudはinternal/handlers/auth.goアダプタパターンを実装しています:

responseWriterアダプタ

type responseWriter struct {
    ctx     *fiber.Ctx
    headers http.Header
    status  int
}

この構造体はhttp.ResponseWriterインターフェースを実装しています。標準ライブラリ関数(Gothなど)がHeader().Add()を呼び出すと、アダプタはローカルのheadersマップに保存します。WriteHeader()が呼び出されると、すべてのヘッダーをFiberコンテキストに手動でコピーし戻します。

目的

Bedrudは極めて高速なまま(Fiberを使用)、標準Goウェブライブラリの広大なエコシステムとの完全な互換性を維持できます。

2. LiveKitリバースプロキシ

Bedrudはメインポート経由ですべてのメディアシグナリングをルーティングすることで、ポート管理の問題を回避しています。

仕組み:

  1. 検出: LIVEKIT_INTERNAL_HOST127.0.0.1を指している場合、Bedrudは内部メディアエンジンを起動します。
  2. マウント: /livekitルートにhttputil.NewSingleHostReverseProxyをマウントします。
  3. パスストリッピング: カスタムDirector関数を使用して/livekitプレフィックスを削除し、メディアサーバーがルートにリクエストが来たかのように受け取れるようにします。
  4. WebSocketサポート: プロキシはadaptor.HTTPHandlerを経由して基盤のTCPストリーム上で動作するため、LiveKitがリアルタイムシグナリングに使用するWebSocketsをネイティブにサポートします。

3. ストレージ効率: 埋め込み構造体

BedrudはGORMのembeddedタグを活用して、データベーススキーマをフラットかつ最適化された状態に保っています。

models/room.goの例:

type Room struct {
    ID       string       `gorm:"primaryKey"`
    Settings RoomSettings `gorm:"embedded;embeddedPrefix:settings_"`
}

これにより、GORMはsettings_allow_chatのようなカラムをroomsテーブルに直接作成します。これはJOINよりも高速で、JSONブロブよりも検索性に優れています。

4. テストインフラストラクチャ

Bedrudはinternal/testutilパッケージを使用した「DB-First」テスト戦略に従っています。

SetupTestDBの仕組み:

  • 各テストごとに固有のSQLiteインメモリデータベースを作成します。
  • すべてのマイグレーションを自動的に実行します。
  • クリーンな状態を提供し、テストが決定論的で並列実行可能であることを保証します。

バックエンドテストを実行するには:

go test ./internal/...

5. セキュリティ: トークンローテーションと失効

シンプルなJWT実装とは異なり、Bedrudは更新のたびに両方のトークンをローテーションします。

  • リフレッシュトークンの再利用検出: リフレッシュトークンが新しいペアの取得に使用されると、直ちにブロックされます。
  • クリーンアップ: BlockedRefreshTokenテーブルにより、リフレッシュトークンが盗まれた場合でも、ユーザーが正常にログアウトまたはセッションを更新した後は使用できなくなります。