Skip to content

Commit 05d2eb6

Browse files
mydeaJPeer264
andauthored
test(cloudflare): Reduce flakiness for cloudflare with sub workers (#20632)
Fixes #20626 It seems that cloudflare integration tests can be flaky. After some digging into this with some clanker help, the idea came up that this is due to sub workers not being ready when DEV_SERVER_READY is emitted. To accomodate this, in the case of a sub worker existing this just adds a little delay (100ms, random number) to wait for before we continue, hopefully reducing flakes. AI wanted to look at more complex things like retrying requests etc. but this felt a bit overkill, I _think_ this is likely good enough if that is indeed the problem...? --------- Co-authored-by: JPeer264 <[email protected]>
1 parent fe5cad5 commit 05d2eb6

1 file changed

Lines changed: 32 additions & 20 deletions

File tree

  • dev-packages/cloudflare-integration-tests

dev-packages/cloudflare-integration-tests/runner.ts

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -208,22 +208,33 @@ export function createRunner(...paths: string[]) {
208208

209209
if (process.env.DEBUG) log('Starting scenario', testPath);
210210

211-
const stdio: ('inherit' | 'ipc' | 'ignore')[] = process.env.DEBUG
212-
? ['inherit', 'inherit', 'inherit', 'ipc']
213-
: ['ignore', 'ignore', 'ignore', 'ipc'];
214-
215211
const onChildError = (e: Error) => {
216212
// eslint-disable-next-line no-console
217213
console.error('Error starting child process:', e);
218214
reject(e);
219215
};
220216

221-
function onChildMessage(message: string, onReady?: (port: number) => void): void {
222-
const msg = JSON.parse(message) as { event: string; port?: number };
223-
if (msg.event === 'DEV_SERVER_READY' && typeof msg.port === 'number') {
224-
if (process.env.DEBUG) log('worker ready on port', msg.port);
225-
onReady?.(msg.port);
226-
}
217+
// Inspired by workers-sdk: https://github.com/cloudflare/workers-sdk/blob/main/packages/wrangler/e2e/helpers/wrangler.ts
218+
function waitForReady(childProcess: ReturnType<typeof spawn>): Promise<number> {
219+
return new Promise((resolve, reject) => {
220+
const stdout = childProcess.stdout;
221+
if (!stdout) {
222+
reject(new Error('No stdout available'));
223+
return;
224+
}
225+
226+
let output = '';
227+
stdout.on('data', (chunk: Buffer) => {
228+
const text = chunk.toString();
229+
if (process.env.DEBUG) process.stdout.write(text);
230+
output += text;
231+
232+
const match = output.match(/Ready on (https?:\/\/[^\s]+)/);
233+
if (match?.[1]) {
234+
resolve(parseInt(new URL(match[1]).port, 10));
235+
}
236+
});
237+
});
227238
}
228239

229240
if (existsSync(join(testPath, 'wrangler-sub-worker.jsonc'))) {
@@ -242,17 +253,15 @@ export function createRunner(...paths: string[]) {
242253
'--inspector-port',
243254
'0',
244255
],
245-
{ stdio, signal },
256+
{ stdio: ['ignore', 'pipe', 'inherit'], signal },
246257
);
247258

248-
// Wait for the sub-worker to be ready before starting the main worker
249-
await new Promise<void>((resolveSubWorker, rejectSubWorker) => {
250-
childSubWorker!.on('message', (msg: string) => onChildMessage(msg, () => resolveSubWorker()));
251-
childSubWorker!.on('error', rejectSubWorker);
252-
childSubWorker!.on('exit', code => {
253-
rejectSubWorker(new Error(`Sub-worker exited with code ${code}`));
254-
});
259+
childSubWorker.on('error', onChildError);
260+
childSubWorker.on('exit', code => {
261+
onChildError(new Error(`Sub-worker exited with code ${code}`));
255262
});
263+
264+
await waitForReady(childSubWorker);
256265
}
257266

258267
child = spawn(
@@ -273,7 +282,7 @@ export function createRunner(...paths: string[]) {
273282
'0',
274283
...extraWranglerArgs,
275284
],
276-
{ stdio, signal },
285+
{ stdio: ['ignore', 'pipe', 'inherit'], signal },
277286
);
278287

279288
CLEANUP_STEPS.add(() => {
@@ -283,7 +292,10 @@ export function createRunner(...paths: string[]) {
283292

284293
childSubWorker?.on('error', onChildError);
285294
child.on('error', onChildError);
286-
child.on('message', (msg: string) => onChildMessage(msg, setWorkerPort));
295+
296+
const workerPort = await waitForReady(child);
297+
298+
setWorkerPort(workerPort);
287299
})
288300
.catch(e => reject(e));
289301

0 commit comments

Comments
 (0)