      ## <img src="https://mojiemoji.jozo.beer/emoji/%E5%95%8F%E9%A1%8C?font=chikara&color=10b981&animation=kage_kaiten&speed=slow&background=transparent&outline=8110b9&outline_width=2" alt="問題" height="20" align="absmiddle"> `CustomScriptLyricsDataSourceImplTests` の実サブプロセス<img src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=hachimaru&color=f43f5e&animation=yoko_scroll&background=transparent&outline=5ef43f&outline_width=2" alt="テスト" height="20" align="absmiddle"> 2 件が <img src="https://mojiemoji.jozo.beer/emoji/CI?font=rampart&color=c084fc&animation=gatagata&background=transparent&outline=fcc084&outline_width=2" alt="CI" height="20" align="absmiddle"> で間欠的に落ちる。原因は<img src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=hachimaru&color=f43f5e&animation=yoko_scroll&background=transparent&outline=5ef43f&outline_width=2" alt="テスト" height="20" align="absmiddle">の **oracle(合否を決める判定要素)が非<img src="https://mojiemoji.jozo.beer/emoji/%E6%B1%BA%E5%AE%9A?font=zero&color=10b981&animation=mozaiku&background=transparent&outline=8110b9&outline_width=2" alt="決定" height="20" align="absmiddle">的な <img src="https://mojiemoji.jozo.beer/emoji/OS?font=gothic-bold&color=22d3ee&animation=gatagata&background=transparent&outline=b20891&outline_width=2" alt="OS" height="20" align="absmiddle"> 依存に直結している**こと。<img src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=hachimaru&color=f43f5e&animation=yoko_scroll&background=transparent&outline=5ef43f&outline_width=2" alt="テスト" height="20" align="absmiddle">側の小細工では直らず、<img src="https://mojiemoji.jozo.beer/emoji/%E5%AE%9F%E8%A3%85?font=gothic-bold&color=f472b6&animation=kira&background=transparent&outline_width=0" alt="実装" height="20" align="absmiddle">側で oracle 要素を<img src="https://mojiemoji.jozo.beer/emoji/%E6%8A%BD%E8%B1%A1?font=maru&color=4ade80&animation=kaiten&speed=slow&background=transparent&outline=4a16a3&outline_width=2" alt="抽象" height="20" align="absmiddle">化しない限り<img src="https://mojiemoji.jozo.beer/emoji/%E5%86%8D%E7%99%BA?font=akzk&color=a855f7&animation=kage_neon&background=transparent&outline=f7a855&outline_width=2" alt="再発" height="20" align="absmiddle">し続ける。 フレークの個別対処はこれまで複数回行われている(#146 TrackInteractor、#213 DecodeEffectState)。<img src="https://mojiemoji.jozo.beer/emoji/%E5%90%8C%E3%81%98?font=mincho&color=a78bfa&animation=yatta&background=transparent&outline=ed7c3a&outline_width=2" alt="同じ" height="20" align="absmiddle">クラスの<img src="https://mojiemoji.jozo.beer/emoji/%E5%95%8F%E9%A1%8C?font=chikara&color=10b981&animation=kage_kaiten&speed=slow&background=transparent&outline=8110b9&outline_width=2" alt="問題" height="20" align="absmiddle">が場所を変えて<img src="https://mojiemoji.jozo.beer/emoji/%E5%86%8D%E7%99%BA?font=gothic&color=f472b6&animation=nami&background=transparent&outline=77db27&outline_width=2" alt="再発" height="20" align="absmiddle">しているので、対症療法ではなく<img src="https://mojiemoji.jozo.beer/emoji/%E6%A7%8B%E9%80%A0?font=kurobara&color=22c55e&animation=mabataki&background=transparent&outline=5e22c5&outline_width=2" alt="構造" height="20" align="absmiddle">で断ちたい。 ## 実測(<img src="https://mojiemoji.jozo.beer/emoji/PR?font=hachimaru&color=ef4444&animation=bure&background=transparent&outline=44ef44&outline_width=2" alt="PR" height="20" align="absmiddle"> #339 の <img src="https://mojiemoji.jozo.beer/emoji/CI?font=kurobara&color=22c55e&animation=tatemoya&background=transparent&outline=5e22c5&outline_width=2" alt="CI" height="20" align="absmiddle">) <img src="https://mojiemoji.jozo.beer/emoji/%E5%90%8C%E4%B8%80?font=maru&color=fb923c&animation=neruneru&background=transparent&outline=0cea58&outline_width=2" alt="同一" height="20" align="absmiddle"> SHA の再実行で success したためフレーク確定。落ち方は次のとおり。 | <img src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=zero&color=a78bfa&animation=chirichiri&background=transparent&outline=ed7c3a&outline_width=2" alt="テスト" height="20" align="absmiddle"> | 期待 | 実測 | |---|---|---| | `executeProcessRealSubprocessDoesNotHang` | `/bin/echo` が status 0 | **status -1**(= 3000ms timeout 発火)、stdout 空 | | `executeProcessTimeoutReturnsPromptly` | 100ms timeout が 5s 以内に返る | **19.86s** | `/bin/echo` が 3 秒で timeout するのは lyra のコードの性質ではなく、走らせた runner の性質。 ## なぜフレークするのか — Oracle が<img src="https://mojiemoji.jozo.beer/emoji/%E6%8A%BD%E8%B1%A1?font=kurobara&color=c084fc&animation=tate_scroll&background=transparent&outline=fcc084&outline_width=2" alt="抽象" height="20" align="absmiddle">化されていない `processRunner` という seam は既にあり、**呼び出し側**の<img src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=hachimaru&color=f43f5e&animation=yoko_scroll&background=transparent&outline=5ef43f&outline_width=2" alt="テスト" height="20" align="absmiddle">はこれを stub して<img src="https://mojiemoji.jozo.beer/emoji/%E6%B1%BA%E5%AE%9A?font=dela&color=fb7185&animation=gatagata&background=transparent&outline=85fb71&outline_width=2" alt="決定" height="20" align="absmiddle">的になっている。しかし `executeProcess` は**その seam の live <img src="https://mojiemoji.jozo.beer/emoji/%E5%AE%9F%E8%A3%85?font=chikara&color=ef4444&animation=zanzo&background=transparent&outline=44ef44&outline_width=2" alt="実装" height="20" align="absmiddle">そのもの**で、`static func` のため `@Dependency` を持てず、次の 4 つを直接ハードワイヤしている。 1. **実クロック** — timeout 発火が `asyncAfter(deadline: .now() + ...)`。SIGKILL エスカレーションの +500ms も<img src="https://mojiemoji.jozo.beer/emoji/%E5%90%8C%E6%A7%98?font=chikara&color=f472b6&animation=ekken&background=transparent&outline=77db27&outline_width=2" alt="同様" height="20" align="absmiddle"> 2. **実プロセス** — `Process()` / `process.run()` 3. **実 global queue のスレッドプール** — stdout/stderr の drain が `readDataToEndOfFile()` で**ブロッキング**。1 呼び出しにつきプールのスレッドを 2 本、子プロセスの生存中ずっと占有する 4. **実パイプ** <img src="https://mojiemoji.jozo.beer/emoji/%E7%B5%90%E6%9E%9C?font=akzk&color=60a5fa&animation=norinori&background=transparent&outline=eb2563&outline_width=2" alt="結果" height="20" align="absmiddle">、`executeProcess` を<img src="https://mojiemoji.jozo.beer/emoji/%E6%A4%9C%E8%A8%BC?font=tamanegi&color=06b6d4&animation=yoko_scroll&background=transparent&outline=d406b6&outline_width=2" alt="検証" height="20" align="absmiddle">する手段が「実物を回して実時間を測る」しか無くなり、<img src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=hachimaru&color=f43f5e&animation=yoko_scroll&background=transparent&outline=5ef43f&outline_width=2" alt="テスト" height="20" align="absmiddle">の oracle が次を測ってしまう。 ```swift #expect(elapsed < .seconds(30)) // 50 個の実サブプロセスを runner が十分速く捌けたか #expect(elapsed < .seconds(5)) // 100ms の timer が実時間で発火できたか ``` `#expect(result.status == 0)` すら実スケジューリング依存になる(timeout が先に発火すれば -1)。 なお 3 は本番側の<img src="https://mojiemoji.jozo.beer/emoji/%E8%A8%AD%E8%A8%88?font=gothic-bold&color=06b6d4&animation=kirari&background=transparent&outline=d406b6&outline_width=2" alt="設計" height="20" align="absmiddle"><img src="https://mojiemoji.jozo.beer/emoji/%E5%95%8F%E9%A1%8C?font=mincho&color=facc15&animation=zairu&background=transparent&outline=04ca8a&outline_width=2" alt="問題" height="20" align="absmiddle">でもある。Swift Testing は suite を並列実行するため、並列<img src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=zero&color=a78bfa&animation=chirichiri&background=transparent&outline=ed7c3a&outline_width=2" alt="テスト" height="20" align="absmiddle">の drain がプールを圧迫すると timeout work item も drain 自身も<img src="https://mojiemoji.jozo.beer/emoji/%E9%81%85%E5%BB%B6?font=toge&color=f97316&animation=bane&background=transparent&outline=16f973&outline_width=2" alt="遅延" height="20" align="absmiddle">する — <img src="https://mojiemoji.jozo.beer/emoji/%E8%A6%B3%E6%B8%AC?font=gothic-bold&color=fb923c&animation=zanzo&background=transparent&outline=0cea58&outline_width=2" alt="観測" height="20" align="absmiddle">された症状と整合する。これは #308 で潰した `waitUntilExit()` hang と同系統の話。 ## 該当箇所 - `Sources/LyricsDataSource/CustomScriptLyricsDataSourceImpl.swift:119-204` — `executeProcess` static - `:186-187` timeout の実クロック / `:181` SIGKILL の +500ms - `:157-165` `.global()` 上のブロッキング drain ×2 - `Tests/LyricsDataSourceTests/CustomScriptLyricsDataSourceImplTests.swift:249-287` — 実時間 oracle の 2 件(`:269`, `:286`) - `Sources/Domain/Misc/ProcessGateway.swift:29-36` — <img src="https://mojiemoji.jozo.beer/emoji/%E5%BE%8C?font=hachimaru&color=f472b6&animation=nami&background=transparent&outline=b6f472&outline_width=2" alt="後" height="20" align="absmiddle">述 ## <img src="https://mojiemoji.jozo.beer/emoji/%E6%97%A2%E5%AD%98?font=dela&color=f472b6&animation=kira&background=transparent&outline_width=0" alt="既存" height="20" align="absmiddle">の<img src="https://mojiemoji.jozo.beer/emoji/%E6%8A%BD%E8%B1%A1?font=gothic&color=fdba74&animation=yurayura&background=transparent&outline=74fdba&outline_width=2" alt="抽象" height="20" align="absmiddle">化との関係 `ProcessGateway`(Domain)+ `DarwinGateway` は既にあり、<img src="https://mojiemoji.jozo.beer/emoji/OS?font=dela&color=8b5cf6&animation=bure&background=transparent&outline=f68b5c&outline_width=2" alt="OS" height="20" align="absmiddle"> <img src="https://mojiemoji.jozo.beer/emoji/%E5%A2%83%E7%95%8C?font=maru-bold&color=8b5cf6&animation=kage_neon&background=transparent&outline=f68b5c&outline_width=2" alt="境界" height="20" align="absmiddle">を DataSource 層で消費するのは `.claude/rules/architecture-boundaries.md` の文書化された型(<img src="https://mojiemoji.jozo.beer/emoji/%E5%89%8D?font=dela&color=f87171&animation=ekken&background=transparent&outline=26dc26&outline_width=2" alt="前" height="20" align="absmiddle">例: `AudioTapGateway`、`ConfigWatchGateway`)。**現在の static はその型からの<img src="https://mojiemoji.jozo.beer/emoji/%E9%80%B8%E8%84%B1?font=tamanegi&color=ec4899&animation=yokomoya&background=transparent&outline=99ec48&outline_width=2" alt="逸脱" height="20" align="absmiddle">**。 ただし gateway 側にも穴がある。<img src="https://mojiemoji.jozo.beer/emoji/%E6%97%A2%E5%AD%98?font=maru-bold&color=c084fc&animation=ekken&background=transparent&outline=fcc084&outline_width=2" alt="既存" height="20" align="absmiddle">の操作は - `run(executable:arguments:) -> Int32` — <img src="https://mojiemoji.jozo.beer/emoji/%E5%90%8C%E6%9C%9F?font=rampart&color=fb7185&animation=kaiten&speed=slow&background=transparent&outline=85fb71&outline_width=2" alt="同期" height="20" align="absmiddle">・<img src="https://mojiemoji.jozo.beer/emoji/%E5%87%BA%E5%8A%9B?font=akzk&color=f87171&animation=nami&background=transparent&outline=26dc26&outline_width=2" alt="出力" height="20" align="absmiddle">なし - `runCapturingOutput(executable:arguments:) -> String?` — <img src="https://mojiemoji.jozo.beer/emoji/%E5%90%8C%E6%9C%9F?font=gothic&color=f87171&animation=nami&background=transparent&outline=26dc26&outline_width=2" alt="同期" height="20" align="absmiddle">・timeout なし・stderr なし・environment なし で、**async + timeout + stdout/stderr capture を持つ操作が無い**。各 DataSource が独自 static を抱えているのはこの穴が<img src="https://mojiemoji.jozo.beer/emoji/%E7%90%86%E7%94%B1?font=rampart&color=f87171&animation=disco&background=transparent&outline_width=0" alt="理由" height="20" align="absmiddle">で、つまり<img src="https://mojiemoji.jozo.beer/emoji/%E6%8A%BD%E8%B1%A1?font=gothic&color=fdba74&animation=yurayura&background=transparent&outline=74fdba&outline_width=2" alt="抽象" height="20" align="absmiddle">化の<img src="https://mojiemoji.jozo.beer/emoji/%E4%B8%8D%E8%B6%B3?font=maru-bold&color=a78bfa&animation=kaiten&speed=slow&background=transparent&outline=ed7c3a&outline_width=2" alt="不足" height="20" align="absmiddle">が<img src="https://mojiemoji.jozo.beer/emoji/%E9%87%8D%E8%A4%87?font=pixel&color=d946ef&animation=mabataki&background=transparent&outline=efd946&outline_width=2" alt="重複" height="20" align="absmiddle">と非<img src="https://mojiemoji.jozo.beer/emoji/%E6%B1%BA%E5%AE%9A?font=noto&color=fb923c&animation=zairu&background=transparent&outline=0cea58&outline_width=2" alt="決定" height="20" align="absmiddle">性を同時に生んでいる。 ## <img src="https://mojiemoji.jozo.beer/emoji/%E5%AF%BE%E5%BF%9C?font=pixel&color=fbbf24&animation=tatemoya&background=transparent&outline=06d977&outline_width=2" alt="対応" height="20" align="absmiddle">案 1. `ProcessGateway` に async + timeout + stdout/stderr capture の操作を<img src="https://mojiemoji.jozo.beer/emoji/%E8%BF%BD%E5%8A%A0?font=maru&color=3b82f6&animation=chirichiri&background=transparent&outline=f63b82&outline_width=2" alt="追加" height="20" align="absmiddle">し、`DarwinGateway` に live <img src="https://mojiemoji.jozo.beer/emoji/%E5%AE%9F%E8%A3%85?font=chikara&color=ef4444&animation=zanzo&background=transparent&outline=44ef44&outline_width=2" alt="実装" height="20" align="absmiddle">を置く 2. 2 つの `executeProcess` static をそこへ移送して<img src="https://mojiemoji.jozo.beer/emoji/%E9%87%8D%E8%A4%87?font=pixel&color=d946ef&animation=mabataki&background=transparent&outline=efd946&outline_width=2" alt="重複" height="20" align="absmiddle">を解消 3. timeout をクロック注入で駆動する(`@Dependency(\.continuousClock)`。<img src="https://mojiemoji.jozo.beer/emoji/%E5%89%8D?font=dela&color=f87171&animation=ekken&background=transparent&outline=26dc26&outline_width=2" alt="前" height="20" align="absmiddle">例: #186 BenchmarkHandler への Clock/ProcessSnapshot 注入)。`static` を外す<img src="https://mojiemoji.jozo.beer/emoji/%E5%BF%85%E8%A6%81?font=chikara&color=facc15&animation=tate_scroll&background=transparent&outline=04ca8a&outline_width=2" alt="必要" height="20" align="absmiddle">がある 4. ブロッキング drain をやめる(`readabilityHandler` か専用 queue)。プール枯渇そのものを消す — <img src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=hachimaru&color=f43f5e&animation=yoko_scroll&background=transparent&outline=5ef43f&outline_width=2" alt="テスト" height="20" align="absmiddle">だけでなく本番の話 5. oracle を<img src="https://mojiemoji.jozo.beer/emoji/%E5%B7%AE%E3%81%97%E6%9B%BF%E3%81%88?font=maru&color=c084fc&animation=kage_neon&background=transparent&outline=fcc084&outline_width=2" alt="差し替え" height="20" align="absmiddle">る。#308 の hang 退行ガードは「**<img src="https://mojiemoji.jozo.beer/emoji/%E7%B5%82%E4%BA%86?font=hachimaru&color=fb923c&animation=mabataki&background=transparent&outline=0cea58&outline_width=2" alt="終了" height="20" align="absmiddle">しない fake process + TestClock で timeout が論理的に発火するか**」を実時間待ちゼロで<img src="https://mojiemoji.jozo.beer/emoji/%E6%A4%9C%E8%A8%BC?font=tamanegi&color=06b6d4&animation=yoko_scroll&background=transparent&outline=d406b6&outline_width=2" alt="検証" height="20" align="absmiddle">する形にできる。「50 個の実 echo が 30 秒以内に終わったか」より<img src="https://mojiemoji.jozo.beer/emoji/%E6%A4%9C%E5%87%BA?font=tamanegi&color=ef4444&animation=bane&background=transparent&outline=44ef44&outline_width=2" alt="検出" height="20" align="absmiddle">力が高く、かつ<img src="https://mojiemoji.jozo.beer/emoji/%E6%B1%BA%E5%AE%9A?font=noto&color=fb923c&animation=zairu&background=transparent&outline=0cea58&outline_width=2" alt="決定" height="20" align="absmiddle">的 6. 残す実サブプロセス<img src="https://mojiemoji.jozo.beer/emoji/%E6%A4%9C%E8%A8%BC?font=tamanegi&color=06b6d4&animation=yoko_scroll&background=transparent&outline=d406b6&outline_width=2" alt="検証" height="20" align="absmiddle">は timing oracle を持たない薄いスモークに縮小(status/stdout のみ、elapsed <img src="https://mojiemoji.jozo.beer/emoji/%E5%A2%83%E7%95%8C?font=gothic-bold&color=ec4899&animation=tate_scroll&background=transparent&outline=99ec48&outline_width=2" alt="境界" height="20" align="absmiddle">なし) 当面の緩和として `@Suite(.serialized)`(実プロセスは global な <img src="https://mojiemoji.jozo.beer/emoji/OS?font=gothic-bold&color=22d3ee&animation=gatagata&background=transparent&outline=b20891&outline_width=2" alt="OS" height="20" align="absmiddle"> 状態。#315 の CoreAudioTapGateway スモークと<img src="https://mojiemoji.jozo.beer/emoji/%E5%90%8C%E3%81%98?font=dela&color=60a5fa&animation=mochimochi&background=transparent&outline=fa60a5&outline_width=2" alt="同じ" height="20" align="absmiddle">考え方)も<img src="https://mojiemoji.jozo.beer/emoji/%E6%9C%89%E5%8A%B9?font=noto&color=60a5fa&animation=disco&background=transparent&outline_width=0" alt="有効" height="20" align="absmiddle">だが、これは緩和であって解決ではない。 ## <img src="https://mojiemoji.jozo.beer/emoji/%E4%BB%98%E9%9A%8F?font=gothic-bold&color=f472b6&animation=tenmetsu&background=transparent&outline=b6f472&outline_width=2" alt="付随" height="20" align="absmiddle">して見つかったこと `YouTubeWallpaperDataSourceImpl.executeProcess`(`:228-274`)は<img src="https://mojiemoji.jozo.beer/emoji/%E5%90%8C%E3%81%98?font=mincho&color=a78bfa&animation=yatta&background=transparent&outline=ed7c3a&outline_width=2" alt="同じ" height="20" align="absmiddle">配管の<img src="https://mojiemoji.jozo.beer/emoji/%E9%87%8D%E8%A4%87?font=toge&color=fdba74&animation=ekken&background=transparent&outline=74fdba&outline_width=2" alt="重複" height="20" align="absmiddle">で、しかも **#308 で lyrics 側から<img src="https://mojiemoji.jozo.beer/emoji/%E9%99%A4%E5%8E%BB?font=gothic&color=facc15&animation=yokomoya&background=transparent&outline=04ca8a&outline_width=2" alt="除去" height="20" align="absmiddle">された `waitUntilExit()` が `:269` に残っている**。timeout も無い。 ただし #308 の hang トリガは「短命プロセスの反復呼び出し」で、こちらは yt-dlp/ffmpeg(長寿命・低頻度)なので条件が違う。**現に<img src="https://mojiemoji.jozo.beer/emoji/%E5%95%8F%E9%A1%8C?font=akzk&color=ef4444&animation=nami&background=transparent&outline=44ef44&outline_width=2" alt="問題" height="20" align="absmiddle">が出ているという主張ではない**が、<img src="https://mojiemoji.jozo.beer/emoji/%E5%AF%BE%E5%BF%9C?font=maru&color=fdba74&animation=chirichiri&background=transparent&outline=74fdba&outline_width=2" alt="対応" height="20" align="absmiddle">案 2 で 1 箇所に集約すれば自然に消える。 ## スコープ config watch(#338 / #339)のスコープ外の follow-up。フレーク自体は #339 のマージをブロックしていない(<img src="https://mojiemoji.jozo.beer/emoji/%E5%90%8C%E4%B8%80?font=dela&color=34d399&animation=ekken&background=transparent&outline=9934d3&outline_width=2" alt="同一" height="20" align="absmiddle"> SHA の再実行で green、マージ済み)。
CustomScriptLyricsDataSourceImplTestsの実サブプロセスフレークの個別対処はこれまで複数回行われている(#146 TrackInteractor、#213 DecodeEffectState)。
クラスの
が場所を変えて
しているので、対症療法ではなく
で断ちたい。
実測(
#339 の
)
executeProcessRealSubprocessDoesNotHang/bin/echoが status 0executeProcessTimeoutReturnsPromptly/bin/echoが 3 秒で timeout するのは lyra のコードの性質ではなく、走らせた runner の性質。なぜフレークするのか — Oracle が
化されていない
processRunnerという seam は既にあり、呼び出し側のexecuteProcessはその seam の livestatic funcのため@Dependencyを持てず、次の 4 つを直接ハードワイヤしている。asyncAfter(deadline: .now() + ...)。SIGKILL エスカレーションの +500ms もProcess()/process.run()readDataToEndOfFile()でブロッキング。1 呼び出しにつきプールのスレッドを 2 本、子プロセスの生存中ずっと占有するexecuteProcessを#expect(result.status == 0)すら実スケジューリング依存になる(timeout が先に発火すれば -1)。なお 3 は本番側の
でもある。Swift Testing は suite を並列実行するため、並列
の drain がプールを圧迫すると timeout work item も drain 自身も
する —
された症状と整合する。これは #308 で潰した
waitUntilExit()hang と同系統の話。該当箇所
Sources/LyricsDataSource/CustomScriptLyricsDataSourceImpl.swift:119-204—executeProcessstatic:186-187timeout の実クロック /:181SIGKILL の +500ms:157-165.global()上のブロッキング drain ×2Tests/LyricsDataSourceTests/CustomScriptLyricsDataSourceImplTests.swift:249-287— 実時間 oracle の 2 件(:269,:286)Sources/Domain/Misc/ProcessGateway.swift:29-36—ProcessGateway(Domain)+DarwinGatewayは既にあり、.claude/rules/architecture-boundaries.mdの文書化された型(AudioTapGateway、ConfigWatchGateway)。現在の static はその型からのただし gateway 側にも穴がある。
の操作は
run(executable:arguments:) -> Int32—runCapturingOutput(executable:arguments:) -> String?—で、async + timeout + stdout/stderr capture を持つ操作が無い。各 DataSource が独自 static を抱えているのはこの穴が
で、つまり
化の
が
と非
性を同時に生んでいる。
ProcessGatewayに async + timeout + stdout/stderr capture の操作をDarwinGatewayに liveexecuteProcessstatic をそこへ移送して@Dependency(\.continuousClock)。staticを外すreadabilityHandlerか専用 queue)。プール枯渇そのものを消す —当面の緩和として
状態。#315 の CoreAudioTapGateway スモークと
考え方)も
だが、これは緩和であって解決ではない。
@Suite(.serialized)(実プロセスは global なYouTubeWallpaperDataSourceImpl.executeProcess(:228-274)はwaitUntilExit()が:269に残っている。timeout も無い。ただし #308 の hang トリガは「短命プロセスの反復呼び出し」で、こちらは yt-dlp/ffmpeg(長寿命・低頻度)なので条件が違う。現に
が出ているという主張ではないが、
案 2 で 1 箇所に集約すれば自然に消える。
スコープ
config watch(#338 / #339)のスコープ外の follow-up。フレーク自体は #339 のマージをブロックしていない(
SHA の再実行で green、マージ済み)。