Flaky test_update_thread_pool_min_max の安定化

puma/puma

test_update_thread_pool_min_maxExpected: 3, Actual: 2 で失敗するフレークが解消されました。テスト内部のスリープ時間を 0.001 秒から 0.1 秒に延長し、リクエストがスレッドプールに十分にキューイングされるようにしただけで、期待通りにスレッドが生成されます。

背景

このテストは スレッドプールの最小・最大スレッド数 が正しく適用されるかを検証する重要なものです。元の実装では sleep 0.001(1ミリ秒)の遅延が設定されており、TCP 接続やスレッドスケジューリングのオーバーヘッドと同程度の時間でした。その結果、既存スレッドが次のリクエストを処理し終える前に新しいリクエストが到着し、race condition が発生してスレッドが再利用され、期待した 3 スレッドが生成されませんでした。

テストが不安定になると CI の信頼性が低下し、実装変更の検証に余計なノイズが入ります。そこで、タイミング依存を解消し、テストが決定的に成功するように調整が必要となりました。

技術的な変更

テストコードの遅延量を拡大するだけのシンプルな修正です。test/test_puma_server.rb の該当メソッド内で sleep 0.001sleep 0.1 に置き換えました。

@@ -2189,9 +2189,10 @@ def test_stats_ok_before_run
   end

   def test_update_thread_pool_min_max
-    # add a small delay so requests back up
+    # delay enough that 5 requests back up faster than threads finish them,
+    # so the pool spawns up to max rather than reusing the existing thread
     @app = ->(env) do
-      sleep 0.001
+      sleep 0.1
       [200, {}, [env['rack.url_scheme']]]
     end

変更前は 1 ミリ秒の遅延で、リクエストがスレッド完了とほぼ同時に到着し、プールが新規スレッドを生成しないケースが頻発していました。変更後は 100 ミリ秒の遅延が確実にリクエストをキューに貯め、プールが最大数までスレッドを生成できるようになり、assert_equal 3, @pool.spawned が常に成功します。

この修正はテストロジックのみに影響し、実際の Puma 本体の挙動やパフォーマンスには一切変更を加えていません。

設計判断

テストのタイミング感度を減らす という方針が採用されました。スレッドプールのロジックそのものは正しいにも関わらず、テスト環境の微小遅延が不確実性を招いていたため、最小限の侵襲で確実性を確保する選択が行われました。

代替案としてはテストコードをリトライロジックで包む、あるいはモックでスレッド生成を強制するなどがありますが、追加のテスト補助コードはテストの可読性を下げ、将来的なメンテナンスコストを増大させる恐れがあります。単にスリープ時間を調整するだけで、テストの意図は変わらず、コードベースへの副作用も最小限です。

この判断により、テストの信頼性が向上し、CI の安定運用が継続できるだけでなく、将来的に同様のレースコンディションを伴うテストへの指針としても有用です。

まとめ

test_update_thread_pool_min_max のフレークは、スリープ遅延を 0.001 秒から 0.1 秒に増やすだけで解消されました。タイミング依存のテストに対しては、最小限の環境調整で決定的な結果を得ることが最も効果的であるという設計判断が示されています。これにより Puma のスレッドプール機能の検証が安定し、継続的インテグレーションの品質が保たれます。

記事メタデータ

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

この記事は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リンクは「PR #3953」と記載されており、完全に「[#3953](URL)」の形式ではありませんが、内容の理解には支障ありません。

対象読者への適合性 ✓ PASS

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

対象はエンジニア向けで、専門用語が適切に使用されており、初心者向けの過剰説明はありません。

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

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

各セクションは総論・各論・結論の段落構成になっており、トピックセンテンスで始まり、1段落1トピック・6文未満に保たれています。段落間は空行で区切られています。

Diff内容との照合 ✓ PASS

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

記事中のコードブロックは提供されたDiffと完全に一致し、ファイル名・変更内容ともに正確です。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「race condition」や「スレッドプール」などの用語はPRと一致しており、誤用はありません。

説明の技術的正確性 ✓ PASS

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

技術的な説明はPRの要旨と合致し、変更がテストコードのみに限定される点も正確に記述されています。

事実の突合 ✓ PASS

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

記事の主張は全てPRの内容(背景、変更点、影響)で裏付けられており、推測や根拠の無い記述は見当たりません。

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

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

期待値「3」や実際の「2」などの数値はPRと一致し、他の数値的誤りはありません。

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

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

記事タイトルはPRの目的(flakyテストの修正)を適切に表現しています。

外部知識の正確性 ✓ PASS

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

記事内にPR外のバージョン情報やリリーススケジュール等の外部知識は含まれていません。

時間表現の正確性 ✓ PASS

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

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