Skip to content

Commit 9cd7219

Browse files
sametbasbugclaude
andauthored
Test koşumundaki keep-alive soket flake'ini kapat (#61)
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 `overrides`ta 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 #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](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 05727ee commit 9cd7219

12 files changed

Lines changed: 126 additions & 0 deletions

‎package-lock.json‎

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
"sharp": "^0.35.3",
7878
"tsx": "4.23.12",
7979
"typescript": "6.0.3",
80+
"undici": "^7.29.0",
8081
"wrangler": "4.125.0"
8182
},
8283
"overrides": {

‎scripts/orbit-mcp-authorization-tests.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,18 @@ import { tmpdir } from 'node:os';
55
import path from 'node:path';
66
import { after, before, describe, test } from 'node:test';
77
import { reserveWorkerPorts } from './orbit-test-ports';
8+
import { useFreshConnectionPerRequest } from './support/test-http';
89
import { BACKUP_SCHEMA_VERSION } from '../src/server/backup/dynamic-backup';
910
import {
1011
createOpaqueToken,
1112
parseOpaqueToken,
1213
verifyOpaqueToken,
1314
} from '../src/server/identity/tokens';
1415

16+
/* Havuzda bekleyen bir keep-alive soketi, bu dosyanın spawnSync
17+
* bloklarından sağ çıkmıyor; gerekçesi support/test-http.ts içinde. */
18+
useFreshConnectionPerRequest();
19+
1520
const ROOT = process.cwd();
1621
const WRANGLER = path.join(ROOT, 'node_modules', 'wrangler', 'bin', 'wrangler.js');
1722
const CONFIG = 'wrangler.test.jsonc';

‎scripts/orbit-site-authorization-tests.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { tmpdir } from 'node:os';
55
import path from 'node:path';
66
import { after, before, describe, test } from 'node:test';
77
import { reserveWorkerPorts } from './orbit-test-ports';
8+
import { useFreshConnectionPerRequest } from './support/test-http';
89
import {
910
normalizeSiteAuthorizationScopes,
1011
parseSiteAuthorizationScopes,
@@ -30,6 +31,10 @@ import {
3031
} from '../src/server/identity/site-authorization-request';
3132
import { siteConsentPage } from '../src/server/http/site-consent-page';
3233

34+
/* Havuzda bekleyen bir keep-alive soketi, bu dosyanın spawnSync
35+
* bloklarından sağ çıkmıyor; gerekçesi support/test-http.ts içinde. */
36+
useFreshConnectionPerRequest();
37+
3338
const ROOT = process.cwd();
3439
const WRANGLER = path.join(ROOT, 'node_modules', 'wrangler', 'bin', 'wrangler.js');
3540
const CONFIG = 'wrangler.test.jsonc';

‎scripts/orbit-site-client-registration-tests.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,13 @@ import path from 'node:path';
2121
import { after, before, describe, test } from 'node:test';
2222

2323
import { reserveWorkerPorts } from './orbit-test-ports';
24+
import { useFreshConnectionPerRequest } from './support/test-http';
2425
import { createOpaqueToken, hmacDigest, randomBase64Url } from '../src/server/identity/tokens';
2526

27+
/* Havuzda bekleyen bir keep-alive soketi, bu dosyanın spawnSync
28+
* bloklarından sağ çıkmıyor; gerekçesi support/test-http.ts içinde. */
29+
useFreshConnectionPerRequest();
30+
2631
const ROOT = process.cwd();
2732
const WRANGLER = path.join(ROOT, 'node_modules', 'wrangler', 'bin', 'wrangler.js');
2833
const CONFIG = 'wrangler.slice1-test.jsonc';

‎scripts/orbit-site-signin-e2e-tests.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,18 @@ import { tmpdir } from 'node:os';
1818
import path from 'node:path';
1919
import { after, before, describe, test } from 'node:test';
2020
import { reserveWorkerPorts } from './orbit-test-ports';
21+
import { useFreshConnectionPerRequest } from './support/test-http';
2122
import {
2223
createOpaqueToken,
2324
hmacDigest,
2425
randomBase64Url,
2526
sha256Base64Url,
2627
} from '../src/server/identity/tokens';
2728

29+
/* Havuzda bekleyen bir keep-alive soketi, bu dosyanın spawnSync
30+
* bloklarından sağ çıkmıyor; gerekçesi support/test-http.ts içinde. */
31+
useFreshConnectionPerRequest();
32+
2833
const ROOT = process.cwd();
2934
const WRANGLER = path.join(ROOT, 'node_modules', 'wrangler', 'bin', 'wrangler.js');
3035
const CONFIG = 'wrangler.slice1-test.jsonc';

‎scripts/orbit-slice1-tests.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { tmpdir } from 'node:os';
55
import path from 'node:path';
66
import { after, before, describe, test } from 'node:test';
77
import { reserveWorkerPorts } from './orbit-test-ports';
8+
import { useFreshConnectionPerRequest } from './support/test-http';
89
import {
910
CSRF_COOKIE,
1011
CSRF_HEADER,
@@ -21,6 +22,10 @@ import {
2122
} from '../src/server/identity/tokens';
2223
import { LEGAL_LAST_UPDATED } from '../src/data/legal';
2324

25+
/* Havuzda bekleyen bir keep-alive soketi, bu dosyanın spawnSync
26+
* bloklarından sağ çıkmıyor; gerekçesi support/test-http.ts içinde. */
27+
useFreshConnectionPerRequest();
28+
2429
const ROOT = process.cwd();
2530
const WRANGLER = path.join(ROOT, 'node_modules', 'wrangler', 'bin', 'wrangler.js');
2631
const CONFIG = 'wrangler.slice1-test.jsonc';

‎scripts/orbit-slice3-tests.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@ import { tmpdir } from 'node:os';
55
import path from 'node:path';
66
import { after, before, describe, test } from 'node:test';
77
import { reserveWorkerPorts } from './orbit-test-ports';
8+
import { useFreshConnectionPerRequest } from './support/test-http';
89
import { loadManifest, verifyManifest } from './orbit-slice3-manifest';
910

11+
/* Havuzda bekleyen bir keep-alive soketi, bu dosyanın spawnSync
12+
* bloklarından sağ çıkmıyor; gerekçesi support/test-http.ts içinde. */
13+
useFreshConnectionPerRequest();
14+
1015
const ROOT = process.cwd();
1116
const WRANGLER = path.join(ROOT, 'node_modules', 'wrangler', 'bin', 'wrangler.js');
1217
const CONFIG = 'wrangler.slice1-test.jsonc';

‎scripts/orbit-slice4-tests.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { mkdtemp, readdir, readFile, rm } from 'node:fs/promises';
55
import { tmpdir } from 'node:os';
66
import { after, before, describe, test } from 'node:test';
77
import { reserveWorkerPorts } from './orbit-test-ports';
8+
import { useFreshConnectionPerRequest } from './support/test-http';
89
import { createEntityId } from '../src/server/foundation/ids';
910
import { createOpaqueToken, hmacDigest, randomBase64Url, sha256Base64Url } from '../src/server/identity/tokens';
1011
import { canonicalJson } from '../src/server/publication/content';
@@ -15,6 +16,10 @@ import {
1516
type DynamicBackup,
1617
} from '../src/server/backup/dynamic-backup';
1718

19+
/* Havuzda bekleyen bir keep-alive soketi, bu dosyanın spawnSync
20+
* bloklarından sağ çıkmıyor; gerekçesi support/test-http.ts içinde. */
21+
useFreshConnectionPerRequest();
22+
1823
const ROOT = process.cwd();
1924
const WRANGLER = path.join(ROOT, 'node_modules', 'wrangler', 'bin', 'wrangler.js');
2025
const TSX = path.join(ROOT, 'node_modules', 'tsx', 'dist', 'cli.mjs');

‎scripts/orbit-slice5-tests.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { mkdtemp, rm } from 'node:fs/promises';
55
import { tmpdir } from 'node:os';
66
import { after, before, describe, test } from 'node:test';
77
import { reserveWorkerPorts } from './orbit-test-ports';
8+
import { useFreshConnectionPerRequest } from './support/test-http';
89
import { createEntityId } from '../src/server/foundation/ids';
910
import { createOpaqueToken, hmacDigest, randomBase64Url, sha256Base64Url } from '../src/server/identity/tokens';
1011
import { canonicalJson } from '../src/server/publication/content';
@@ -17,6 +18,10 @@ import { verifyDynamicBackup } from '../src/server/backup/dynamic-backup';
1718
import { ImageTransformError, inspectImage, transformImage } from '../src/server/media/image-processor';
1819
import sharp from 'sharp';
1920

21+
/* Havuzda bekleyen bir keep-alive soketi, bu dosyanın spawnSync
22+
* bloklarından sağ çıkmıyor; gerekçesi support/test-http.ts içinde. */
23+
useFreshConnectionPerRequest();
24+
2025
const ROOT = process.cwd();
2126
const WRANGLER = path.join(ROOT, 'node_modules', 'wrangler', 'bin', 'wrangler.js');
2227
const TSX = path.join(ROOT, 'node_modules', 'tsx', 'dist', 'cli.mjs');

0 commit comments

Comments
 (0)