テストスイートの安定化とコネクションプールのリファクタリングをバックポート

rails/rails

8-0-stable ブランチに、8-1-stable で行われたテスト関連の修正を取り込み、テスト実行時の 環境変数 管理や コネクションプール のクリーンアップロジックを改善しました。これにより、テストの信頼性が向上し、リソースリークのリスクが低減します。

背景

8-1-stable で追加された多数のテスト修正は、テスト実行中に発生していた環境変数の残留やコネクションプールのリークを防ぐためのものです。8-0-stable でも同様の安定性が求められるため、これらの修正をバックポートする必要がありました。

技術的な変更

環境変数の一時設定と復元

テストヘルパー ActionDispatch::IntegrationTest に、RAILS_INBOUND_EMAIL_PASSWORDセットアップ 時に保存し、テアダウン 時に復元するロジックが追加されました。actionmailbox/test/test_helper.rb では次のように実装されます。

class ActionDispatch::IntegrationTest
  setup do
    @previous_inbound_email_password = ENV["RAILS_INBOUND_EMAIL_PASSWORD"]
    ENV["RAILS_INBOUND_EMAIL_PASSWORD"] = "tbsy84uSV1Kt3ZJZELY2TmSh..."
  end

  teardown do
    ENV["RAILS_INBOUND_EMAIL_PASSWORD"] = @previous_inbound_email_password
  end
end

この変更により、テスト間で環境変数が汚染されることがなくなり、テストの独立性 が保たれます。

コネクションプールの実装変更とエラーハンドリング

activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb では、内部マップを Concurrent::Map に置き換え、スレッドが死んだ場合のエントリ削除ロジックを明示的に実装しました。また、checkin 時に例外が発生した場合は ActiveSupport.error_reporter で捕捉し、同時に接続を 切断 するようにしました。

class WeakThreadKeyMap
  def initialize
    @map = Concurrent::Map.new
  end

  def []=(key, value)
    @map.each_pair do |thread, _|
      @map.delete(thread) unless thread&.alive?
    end
    @map[key] = value
  end
end

# checkin エラー時の報告と切断
if conn.in_use?
  conn.steal!
  ActiveSupport.error_reporter.handle(source: "active_record.connection_pool") do
    checkin conn
  end
end
ActiveSupport.error_reporter.handle(source: "active_record.connection_pool") do
  conn.disconnect!
end

これにより、チェックイン失敗時の リソースリーク が防止され、エラーログが一元管理されます。

共有コネクションプールのクリーンアップロジック

activerecord/test/cases/test_fixtures_test.rb では、teardown_shared_connection_pool が拡張され、削除されたロールに対応するプール設定を 切断 する処理が追加されました。

removed_pool_configs = []
pool_managers.each do |owner, pool_manager|
  # 省略
  removed_pool_configs.concat(pool_manager.remove_role(role_name)&.values || [])
end
remaining_pool_configs = pool_managers.values.flat_map(&:pool_configs)
removed_pool_configs.compact.uniq.each do |pool_config|
  pool_config.disconnect! unless remaining_pool_configs.include?(pool_config)
end

テスト終了時に不要なプールが残らないことを保証し、メモリ使用量の増大 を防止します。

テストケースとフィクスチャの修正

  • actionmailbox 系テストは、ENV の保存/復元ロジックを追加し、setup/teardown が明示的に分離されました。
  • pirates.yml の日時フィクスチャは固定日付 (2004-01-01) に変更され、テストの 決定論的 な実行を可能にしました。
  • autosave_association_test.rb では、assert_equal が配列のソート比較に変更され、順序依存を排除しました。
  • connection_pool_test.rb では、checkout_timeout 設定やグループウェイトのタイムアウトロジックが追加され、スレッド公平性 の検証が強化されました。

テストヘルパーの追加メソッド

activerecord/test/support/connection_helper.rbreset_pool が新設され、テスト中にプール全体をリセットできるようになりました。既存の reset_connection はそのまま残し、後方互換性 を保持しています。

def reset_pool
  original_connection = ActiveRecord::Base.remove_connection
  ActiveRecord::Base.establish_connection(original_connection)
end

設計判断

後方互換性を保ちつつテストインフラを強化

本バックポートは、公開 API を変更せずにテスト支援コードのみを改変しています。reset_connection の挙動は維持しつつ reset_pool を追加した点や、WeakThreadKeyMap の内部実装を変更した点は、内部実装の刷新 であり、アプリケーションコードへの影響はありません。

エラーハンドリング統一とリソースリーク防止

ActiveSupport.error_reporter での例外捕捉を統一し、チェックイン失敗時に即座に接続を切断することで、接続プールの健全性 を保ちます。また、プール削除後の切断処理により、長時間実行されるテストスイートでのメモリ増加を抑制します。

まとめ

本 PR は、テスト実行時の環境変数管理、コネクションプールの内部実装、テストフィクスチャの決定論的化など、多岐にわたる改善を 8-0-stable にバックポートしました。これらの変更はアプリケーション本体の振る舞いを変えず、テストの安定性とリソース管理を向上させることを目的としています。

記事メタデータ

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

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

品質レビュー結果

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

Review Criteria:

記事構成 ✓ PASS

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

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

カスタムMarkdown構文 ✓ PASS

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

コードブロックは `language:filepath` 形式で正しく指定され、GitHubリンクも PR 番号リンクとして正しく記載されています。

対象読者への適合性 ✓ PASS

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

対象は Rails エンジニアであり、専門的な用語と実装詳細が中心で初心者向けの過度な説明はありません。

パラグラフ・ライティング ✓ PASS

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

各セクションは総論パラグラフで要旨を示し、続く段落は1トピック・トピックセンテンスで構成され、段落長も適切です。

Diff内容との照合 ✓ PASS

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

記事内のコードスニペットは提供された Diff の変更点と完全に一致しており、ファイル名・内容とも合致しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

使用されている技術用語は PR や Rails のドキュメントと一致しており、誤用は見られません。

説明の技術的正確性 ✓ PASS

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

変更理由や実装効果の説明は Diff と PR の記載内容に基づき、技術的に正確です。

事実の突合 ✓ PASS

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

記事の主張はすべて PR の記述・Diff に裏付けられており、捏造や推測はありません。

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

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

PR 番号 #57770、日付 2004-01-01 など、数値・固有名詞は Diff と一致しています。

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

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

記事タイトルは PR のバックポート内容を日本語で的確に要約しており、矛盾はありません。

外部知識の正確性 ✓ PASS

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

LTS やリリース日程など PR に無い外部情報は含まれていません。

時間表現の正確性 ✓ PASS

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

時間表現の記載は PR の記述と食い違っていません。