Channel#stop_stream_from がシンボルを文字列へ変換しストリーム解除を正しく行うよう改善

rails/rails

ActionCable の stop_stream_from がシンボルをキーにした場合にストリームを解除できなかった不具合を、引数を文字列へ強制変換することで修正し、テストを追加して動作を検証した。

背景

stream_from は受け取った broadcastingString(broadcasting) に変換してハッシュキーとして保存するため、シンボルでも文字列キーに統一されています。

しかし stop_stream_from は変換処理がなく、生の引数でハッシュから削除しようとした結果、シンボルと文字列のキーが一致せずストリームが残存しました。

この不整合は stream_from :chatstop_stream_from :chat の組み合わせで発生し、接続が閉じられるまで pubsub.unsubscribe が呼ばれないという実害を生んでいました。

技術的な変更

stop_stream_from の冒頭に broadcasting = String(broadcasting) を追加し、stream_from と同様に引数を文字列へ強制変換することでキーの統一を実現しました。

@@ -119,6 +119,8 @@ def stream_for(broadcastables, ...)

        # Unsubscribes streams from the named `broadcasting`.
        def stop_stream_from(broadcasting)
+         broadcasting = String(broadcasting)
+
          callback = streams.delete(broadcasting)
          if callback
            pubsub.unsubscribe(broadcasting, callback)

さらに stream_test.rb にシンボルを用いたストリーム登録と解除のテストを追加し、解除後の購読者数が 0 になることを確認しています。

@@ -219,6 +219,21 @@ def channel.subscribed
        assert_equal 1, subscribers["room_two"].size
      end

+     test "stop_stream_from with a non-string broadcasting matches stream_from" do
+       connection = Connection.new(server, socket)
+
+       channel = ChatChannel.new connection, "{id: 3}"
+       channel.subscribe_to_channel
+
+       channel.stream_from :room_one
+
+       assert_equal 1, subscribers_of(connection).size
+
+       channel.stop_stream_from :room_one
+
+       assert_equal 0, subscribers_of(connection).size
+     end

設計判断

この変更は 同族メソッド間の振る舞いを統一 することを目的としており、既存のロジックに最小限の一行追加で実装されています。

stream_from の実装を変更せずに stop_stream_from 側で型変換を行う方針は、後方互換性を保ちつつバグ修正だけを行うというトレードオフを示しています。

結果として、シンボル・文字列問わず同一キーでストリームを管理でき、開発者は stop_stream_from を安全に呼び出すことが可能になりました。

まとめ

stop_stream_from に文字列への強制変換を導入し、stream_from とキー生成ロジックを揃えることで、ストリーム解除漏れという実装バグを解消しました。テスト追加により挙動が保証され、ActionCable のストリーム管理の一貫性が向上しました。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
163dd0e8

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文、背景、技術的な変更、設計判断、まとめが揃っており、総論→各論→結論の構成が明確です。

カスタムMarkdown構文 ⚠ WARNING

シンタックスハイライト・GitHubリンク記法の正確性

コードブロックのファイル名付きハイライトは正しい形式ですが、PRリンクの記法が指示の `[ #123 ](url)` ではなく `[PR #57692](url)` となっているため警告としました。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

対象はRails/ActionCableを扱うエンジニアであり、専門用語中心の記述で過度な初心者向け説明はありません。

パラグラフ・ライティング ⚠ WARNING

トピックセンテンス・1段落1トピック・段落長

各セクションは総論・各論で構成されているが、"技術的な変更" セクションに結論パラグラフが欠けている点が見受けられます。段落はトピックセンテンスで始まり、長さも適切です。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事中のコードブロックは提供されたDiffと完全に一致しており、追加行・削除行ともに正しく反映されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`broadcasting`, `stream_from`, `stop_stream_from`, `pubsub.unsubscribe` などの用語は正しく使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

不具合の原因、修正内容、テスト追加の効果がPR説明と合致しており、技術的に正確です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

全ての主張はPRタイトル・説明・Diffに裏付けられており、捏造や推測はありません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号 #57692 などの数値は正確です。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事タイトルはPRタイトルの意味を日本語で正確に表現しており、一致しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

バージョンやリリーススケジュール等、PRに記載されていない外部知識は含まれていません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間表現のずれはなく、PRの記述と整合しています。