テストスイートの安定化とコネクションプールのリファクタリングをバックポート
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.rb に reset_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 にバックポートしました。これらの変更はアプリケーション本体の振る舞いを変えず、テストの安定性とリソース管理を向上させることを目的としています。