first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { spawn } from 'child_process';
|
||||
import os from 'os';
|
||||
|
||||
/**
|
||||
* Wait for the Linux network stack to become quiet (no netlink events).
|
||||
* This monitors actual kernel network events rather than guessing with fixed delays.
|
||||
*
|
||||
* Only runs in CI on Linux. On other platforms or local dev, resolves immediately.
|
||||
*
|
||||
* @param quietDurationMs - How long the network must be quiet before resolving (default: 2000ms)
|
||||
* @param maxWaitMs - Maximum time to wait before giving up (default: 10000ms)
|
||||
*/
|
||||
export async function waitForNetworkQuiet(
|
||||
quietDurationMs = 1000,
|
||||
maxWaitMs = 10000,
|
||||
): Promise<void> {
|
||||
// Only run in CI on Linux
|
||||
if (!process.env.CI || os.platform() !== 'linux') {
|
||||
return;
|
||||
}
|
||||
|
||||
return await new Promise((resolve) => {
|
||||
let lastEventTime = Date.now();
|
||||
let checkInterval: NodeJS.Timeout | null = null;
|
||||
let maxTimeout: NodeJS.Timeout | null = null;
|
||||
let resolved = false;
|
||||
|
||||
const cleanup = () => {
|
||||
if (resolved) return;
|
||||
resolved = true;
|
||||
if (checkInterval) clearInterval(checkInterval);
|
||||
if (maxTimeout) clearTimeout(maxTimeout);
|
||||
monitor.kill();
|
||||
};
|
||||
|
||||
// Monitor network events using `ip monitor`
|
||||
// Watches: link (interfaces), address (IP assignments), route (routing table)
|
||||
const monitor = spawn('ip', ['monitor', 'link', 'address', 'route'], {
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
});
|
||||
|
||||
monitor.on('error', (error: Error) => {
|
||||
// ip command not available - fall back to no-op
|
||||
console.warn(`[network-stabilization] ip monitor not available: ${error.message}`);
|
||||
cleanup();
|
||||
resolve();
|
||||
});
|
||||
|
||||
monitor.stdout.on('data', () => {
|
||||
// Network change detected, reset timer
|
||||
lastEventTime = Date.now();
|
||||
});
|
||||
|
||||
monitor.stderr.on('data', (data) => {
|
||||
console.warn(`[network-stabilization] ip monitor stderr: ${data}`);
|
||||
});
|
||||
|
||||
// Check periodically if network has been quiet long enough
|
||||
checkInterval = setInterval(() => {
|
||||
const quietDuration = Date.now() - lastEventTime;
|
||||
if (quietDuration >= quietDurationMs) {
|
||||
console.log(`[network-stabilization] Network quiet for ${quietDuration}ms, proceeding`);
|
||||
cleanup();
|
||||
resolve();
|
||||
}
|
||||
}, 100);
|
||||
|
||||
// Maximum wait timeout
|
||||
maxTimeout = setTimeout(() => {
|
||||
console.warn(`[network-stabilization] Max wait (${maxWaitMs}ms) exceeded, proceeding anyway`);
|
||||
cleanup();
|
||||
resolve();
|
||||
}, maxWaitMs);
|
||||
|
||||
// Handle process exit
|
||||
monitor.on('close', () => {
|
||||
if (!resolved) {
|
||||
cleanup();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user