CookieStore::DEFAULT_SAME_SITE を Ractor 安全化
CookieStore がデフォルトで使用する :same_site 判定ロジックを、Ractor 間で安全に共有できるように変更しました。DEFAULT_SAME_SITE に設定された proc を ActiveSupport::Ractors.shareable_proc でラップし、動作はそのまま保ちつつ Ractor の隔離エラーを回避します。
背景
CookieStore はセッションクッキーの SameSite 属性を決定する際、DEFAULT_SAME_SITE 定数に格納された proc を呼び出します。この proc はリクエストオブジェクトの cookies_same_site_protection を取得し、デフォルトの SameSite ポリシーを返すだけのシンプルな実装です。
従来は単純な proc で定義されていたため、Ractor の境界を越えて渡すと Ractor::IsolationError が発生する可能性があり、マルチ Ractor 環境で CookieStore を利用できないという制約が残っていました。
この制約を解消することが、本変更の主目的となります。
技術的な変更
actionpack/lib/action_dispatch/middleware/session/cookie_store.rb における DEFAULT_SAME_SITE の定義が次のように置き換えられました。
-DEFAULT_SAME_SITE = proc { |request| request.cookies_same_site_protection } # :nodoc:
+DEFAULT_SAME_SITE = ActiveSupport::Ractors.shareable_proc { |request| request.cookies_same_site_protection } # :nodoc:
ActiveSupport::Ractors.shareable_proc は渡されたブロックを不変オブジェクトに変換し、Ractor 間で安全に共有できる形にします。このラップにより、DEFAULT_SAME_SITE が保持するロジックは変わらず、options[:same_site] が未指定の場合でも同一の判定が利用可能です。
initialize メソッド内では依然として options[:same_site] = DEFAULT_SAME_SITE が実行され、他のコードパスへの影響はありません。
設計判断
本改修は 既存定数のラップ という最小限の手法を選択しています。新たな設定キーや API を導入せず、shareable_proc を用いるだけで Ractor 安全性を確保することで、既存コードとの互換性を保ちました。
DEFAULT_SAME_SITE が外部状態を捕捉しない(request だけを引数に取る)という前提があるため、shareable_proc の使用は副作用を生むことなく安全に適用できることが設計上の根拠となります。
このアプローチは、同様のプロックを保持する他のミドルウェアでも同様の手法で Ractor 対応を行える指針を示しています。
まとめ
CookieStore::DEFAULT_SAME_SITE を ActiveSupport::Ractors.shareable_proc でラップしたことで、Ractor 環境下でも SameSite 判定ロジックを安全に共有できるようになりました。動作は変更されず、既存の API もそのまま利用可能です。この変更は Rails の Ractor 移行に伴う後方互換性を維持しつつ、実装上の安全性を高めた重要なステップです。