Skip to content

Test koşumundaki keep-alive soket flake'ini kapat - #61

Merged
sametbasbug merged 2 commits into
mainfrom
test-kosumu-keepalive-flake
Aug 24, 2026
Merged

Test koşumundaki keep-alive soket flake'ini kapat#61
sametbasbug merged 2 commits into
mainfrom
test-kosumu-keepalive-flake

Conversation

@sametbasbug

Copy link
Copy Markdown
Owner

CI'da ara sıra düşen orbit-slice3-tests.ts feed testinin kök nedenini kapatır.

Belirti

Test ilk fetch'te, hiçbir iddiaya varmadan 3-4 ms içinde düşüyordu:

TypeError: fetch failed
  cause: SocketError: other side closed  (UND_ERR_SOCKET)
  socket: { bytesWritten: 370, bytesRead: 1631 }

Kök neden

Sunucunun ayakta olmamasıyla ilgili değil. bytesRead sıfır değil, yani o soket
daha ö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 spawnSync
ile ikinci wrangler süreçleri koşturuyor. spawnSync olay döngüsünü saniyelerce
tamamen 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 fetch aynı
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: 0 undici'de
keep-alive'ı kapatır; undici dokümanında belgeli yol, tip tanımları da
keepAlive yerine bunu öneriyor.

Yerel worker'a HTTP yapan dokuz dosyada import + tek satır çağrı. undici
devDependencies'e eklendi (zaten overridesta pinliydi ve ağaçtaydı; artık
doğrudan içe aktarıldığı için açıkça duruyor).

İkinci commit bir bekçi ekliyor: setGlobalDispatcher global bir sembole yazıp
Node'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, skip yok, süre uzatılmadı, retry yok. 126 ekleme,
sıfır silme.

Ölçüm

orbit-slice3-tests, diagnostics_channel ile aynı 63 istek üzerinden:

bağlantı istek yeniden kullanım
önce 2 57 55
sonra 57 57 0

Bekçi mutasyonla sınandı: setGlobalDispatcher devre dışı bırakıldığında
ateş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: 0 ile 0/8), ama asıl dosyada yarış penceresi
zamanlanamayacak 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 dizinine
    ikinci 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.
  • waitForWorker ilk 200'ü hazır sayıyor; sonradan bir yeniden başlatma olursa
    fark edilmez.
  • Altı test dosyası ortak dev registry'ye aynı worker adıyla yazıyor.

🤖 Generated with Claude Code

sametbasbug and others added 2 commits August 25, 2026 01:07
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>
@sametbasbug
sametbasbug merged commit 9cd7219 into main Aug 24, 2026
4 checks passed
@sametbasbug
sametbasbug deleted the test-kosumu-keepalive-flake branch August 24, 2026 22:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant