Test koşumundaki keep-alive soket flake'ini kapat - #61
Merged
Conversation
CI'da ara sıra slice3'ün akış testi hiçbir iddiaya varmadan 3-4 ms içinde
düşüyordu: UND_ERR_SOCKET "other side closed", bytesRead 1631. Sıfır olmayan
bytesRead soketin daha önce bir yanıt taşıdığını söylüyor — yani hata yeni
kurulan bir bağlantıda değil, undici'nin havuzundan gelen keep-alive
bağlantısında. Sunucu onu kapatmış, istemci ölü sokete yazmış.
İstemcinin kapanmayı görememesinin sebebi bu dosyaların çalışma biçimi:
worker ayaktayken spawnSync ile ikinci wrangler süreçleri koşuyor ve
spawnSync olay döngüsünü saniyelerce tamamen durduruyor. O sürede undici ne
FIN'i işleyebiliyor ne de kendi 4 saniyelik boşta kalma zamanlayıcısını
çalıştırıp soketi havuzdan atabiliyor. Sunucu tarafında da güvence yok:
workerd yanıtta Keep-Alive başlığı göndermiyor, boşta bir bağlantıyı ne
zaman kapatacağını hiç söylemiyor.
HTTP/1.1'de yazmadan önce bağlantının açık olup olmadığını bilmenin yolu
yok. Normal istemciler bunu tekrar denemeyle örter; testte hatayı örtmek
istemiyoruz. Kalan sağlam seçenek bağlantıyı hiç yeniden kullanmamak.
Agent({ pipelining: 0 }) keep-alive'ı kapatıyor, her istek kendi
bağlantısını açıyor.
Ölçüm (orbit-slice3-tests, aynı 63 istek):
- önce: 2 bağlantı, 55 yeniden kullanım
- sonra: 57 bağlantı, 0 yeniden kullanım
Mekanizmanın kendisi ayrı bir deneyle doğrulandı: aynı Node/undici ile,
sunucu boştaki bağlantıyı kapatırken spawnSync ile bloke edilmiş bir döngüde
düz fetch 8 turun 4'ünde düştü, pipelining: 0 ile 8/8 geçti. Gerçek test
dosyasını yerelde istekle düşüremedim; kalan koşul FIN'in son poll ile
yazma arasındaki aralığa denk gelmesi ve bunu zamanlayamıyorum.
undici zaten overrides'ta pinlenmişti; doğrudan içe aktardığımız için artık
devDependencies'te de açıkça duruyor.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
useFreshConnectionPerRequest global bir sembole yazıp Node'un yerleşik fetch'inin onu okumasına güveniyordu. Bugün doğru çalışıyor: Node 26 / undici 7'de undici.globalDispatcher.1 ve .2 aynı nesneyi gösteriyor. Ama bu bağ koparsa çağrı sessizce hiçbir şey yapmaz. Keep-alive geri gelir, UND_ERR_SOCKET yarışı yeniden açılır ve hiçbir test kırılmaz — çünkü geri gelen şey ara sıra düşen bir yarış. Yani düzeltme, kendi bozulduğunu haber veremeyen bir düzeltmeydi. Bekçi ayarın yerleştiğini kurulum anında doğruluyor; yerleşmediyse testler ilk satırda duruyor. Doğrulama: setGlobalDispatcher devre dışı bırakılarak mutasyon sınandı, bekçi ateşledi; mutasyon geri alındıktan sonra sessiz. npm run check (213 dosya, 0 hata) ve npm run test:d1 (341/341) çıkış kodu 0. Bağlantı ölçümü: 57 istek / 57 bağlantı / 0 yeniden kullanım. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CI'da ara sıra düşen
orbit-slice3-tests.tsfeed testinin kök nedenini kapatır.Belirti
Test ilk
fetch'te, hiçbir iddiaya varmadan 3-4 ms içinde düşüyordu:Kök neden
Sunucunun ayakta olmamasıyla ilgili değil.
bytesReadsıfır değil, yani o soketdaha önce bir yanıt taşımış: undici'nin havuzundan gelen bir keep-alive
bağlantısı. Sunucu onu kapatmış, istemci ölü sokete yazmış.
İstemcinin kapanmayı neden kaçırdığı: bu dosyalar worker ayaktayken
spawnSyncile ikinci wrangler süreçleri koşturuyor.
spawnSyncolay döngüsünü saniyelercetamamen durduruyor; o sürede undici ne FIN'i işleyebiliyor ne de soketi havuzdan
atacak zamanlayıcıyı çalıştırabiliyor. Blok biter bitmez gelen
fetchaynısenkron adımda ölü sokete yazıyor.
HTTP/1.1'de yazmadan önce bağlantının açık olduğunu bilmenin yolu yok. Normal
istemciler bunu tekrar denemeyle örter; testte örtmek istemiyoruz. Kalan sağlam
seçenek bağlantıyı hiç yeniden kullanmamak.
Değişiklik
scripts/support/test-http.ts(yeni):useFreshConnectionPerRequest()—setGlobalDispatcher(new Agent({ pipelining: 0 })).pipelining: 0undici'dekeep-alive'ı kapatır; undici dokümanında belgeli yol, tip tanımları da
keepAliveyerine bunu öneriyor.Yerel worker'a HTTP yapan dokuz dosyada import + tek satır çağrı.
undicidevDependencies'e eklendi (zaten
overridesta pinliydi ve ağaçtaydı; artıkdoğrudan içe aktarıldığı için açıkça duruyor).
İkinci commit bir bekçi ekliyor:
setGlobalDispatcherglobal bir sembole yazıpNode'un yerleşik
fetch'inin onu okumasına güveniyor. Bu bağ ileride koparsaçağrı sessizce hiçbir şey yapmaz — keep-alive geri gelir, yarış yeniden açılır ve
hiçbir test kırılmaz, çünkü geri gelen şey ara sıra düşen bir yarış. Bekçi ayarın
yerleştiğini kurulum anında doğruluyor.
Hiçbir iddia gevşetilmedi,
skipyok, süre uzatılmadı, retry yok. 126 ekleme,sıfır silme.
Ölçüm
orbit-slice3-tests,diagnostics_channelile aynı 63 istek üzerinden:Bekçi mutasyonla sınandı:
setGlobalDispatcherdevre dışı bırakıldığındaateşliyor, geri alındığında sessiz.
Çıkış kodu 0 dönenler:
npm run check(213 dosya, 0 hata),npm run test:d1(341/341, birkaç kez).
Dürüstlük notu
Gerçek testi istekle düşüremedik. Mekanizma izole ortamda tetiklendi (düz fetch
8 turun 4'ünde düşüyor,
pipelining: 0ile 0/8), ama asıl dosyada yarış penceresizamanlanamayacak kadar dar. Yani: bütün kanıtlarla tutarlı olan mekanizma
ortadan kaldırıldı; "flake kesin bitti" iddiası bu kadarıyla kanıtlanmış değil.
Ayrıca workerd'in FIN'i tam olarak neden gönderdiği açık kalıyor. Düzeltme
tetikleyiciden bağımsız çalışıyor (yeniden kullanılan soket yoksa yarış da yok),
ama sebep kapatılmış sayılmamalı.
Ayrı iş olarak kalanlar
orbit-slice3-tests.ts:127,134— worker ayaktayken aynı persist dizinineikinci wrangler süreci. Bu kalıp Stabilize Slice 1 local D1 test reads #51'de slice1'den deterministik ECONNRESET
sebebi olarak kaldırılmıştı, burada kalmış; bu flake'in ön koşulu olan
bloklamayı da o yaratıyor.
waitForWorkerilk 200'ü hazır sayıyor; sonradan bir yeniden başlatma olursafark edilmez.
🤖 Generated with Claude Code