Interrupt live traffic retry delays on stop
Build and Deploy Gateway / build-and-push (push) Successful in 1m58s
Build and Deploy Gateway / deploy (push) Successful in 19s

This commit is contained in:
2026-08-31 05:34:56 +03:00
parent bdf3f22b12
commit 79e00a2390
4 changed files with 53 additions and 21 deletions
+13 -4
View File
@@ -639,10 +639,17 @@ function defaultClientFactory(port: number): NativeTrafficClient {
}));
}
function delay(milliseconds: number) {
function delay(milliseconds: number, signal: AbortSignal) {
return new Promise<void>((resolve) => {
const timer = setTimeout(resolve, milliseconds);
const finish = () => {
clearTimeout(timer);
signal.removeEventListener('abort', finish);
resolve();
};
const timer = setTimeout(finish, milliseconds);
timer.unref();
signal.addEventListener('abort', finish, { once: true });
if (signal.aborted) finish();
});
}
@@ -660,6 +667,7 @@ export function createLiveTrafficService({
const ledger = createLiveTrafficLedger({ enabled, gateway, resolveOrigin });
if (!enabled && unavailableError) ledger.markUnavailable(unavailableError);
let stopped = false;
const stopController = new AbortController();
let controller: AbortController | null = null;
let running: Promise<void> | null = null;
let failedProjection: NativeTrafficProjectionBatch | null = null;
@@ -742,7 +750,7 @@ export function createLiveTrafficService({
while (!stopped) {
if (!isRuntimeRunning()) {
ledger.markStopped();
await delay(RETRY_MS);
await delay(RETRY_MS, stopController.signal);
continue;
}
controller = new AbortController();
@@ -756,7 +764,7 @@ export function createLiveTrafficService({
} finally {
controller = null;
}
if (!stopped) await delay(RETRY_MS);
if (!stopped) await delay(RETRY_MS, stopController.signal);
}
};
@@ -767,6 +775,7 @@ export function createLiveTrafficService({
},
async stop() {
stopped = true;
stopController.abort();
controller?.abort();
await running;
},
+3 -3
View File
@@ -1,7 +1,7 @@
export const HARBOR_VERSIONS = Object.freeze({
macClient: '0.34.0',
gatewayClient: '0.36.0',
gatewayBackend: '0.36.0',
macClient: '0.34.1',
gatewayClient: '0.36.1',
gatewayBackend: '0.36.1',
});
export interface ParsedVersion {
+23
View File
@@ -223,6 +223,29 @@ for (const incompatible of [
});
}
test('collector stop interrupts an active retry delay', async () => {
const service = createLiveTrafficService({
port: 19091,
enabled: true,
isRuntimeRunning: () => true,
clientFactory: () => ({
async getVersion() { return { version: '1.13.18', apiVersion: 4 }; },
async getStartedAt() { throw new Error('must not start'); },
subscribeConnections() { throw new Error('must not subscribe'); },
subscribeStatus() { throw new Error('must not subscribe'); },
}),
});
service.start();
await waitFor(() => service.snapshot().source.state === 'incompatible');
await new Promise((resolve) => setImmediate(resolve));
const stoppedBeforeNextTurn = await Promise.race([
service.stop().then(() => true),
new Promise((resolve) => setImmediate(() => resolve(false))),
]);
assert.equal(stoppedBeforeNextTurn, true);
});
test('collector reconnects when either RC5 stream ends and cancels its sibling', async () => {
let factoryCalls = 0;
let authorizationCalls = 0;
+14 -14
View File
@@ -40,26 +40,26 @@ const expectedImports = [
const sha256 = (value) => crypto.createHash('sha256').update(value).digest('hex');
const acceptedLedger = {
counts: {
cascadeEdges: 1126,
cascadeEdges: 1153,
customProperties: 115,
declarations: 4676,
declarations: 4698,
important: 0,
keyframes: 55,
media: 22,
rules: 1262,
variableReferences: 1214,
rules: 1267,
variableReferences: 1222,
},
hashes: {
cascadeEdges: '1f3c75839bd37bb312b9aed2987ed61571e5148f8b23c8288424cb193c7a8dda',
cascadeEdges: 'b92a7365b40a48b7c1e9a026b08170c35519567132036a86049b37eebdcd5b76',
customProperties: '81d1e70737ae5a8e4b20d4c1be1b24685975a404863444da4a8821be1f0d5097',
declarations: '616fc7cb72a9db509f6b41e1808118c2e2be7da6ce4c078dfa2eb4a963f0dbb1',
declarations: '0e994db1d4ac16eb91d1dd0d74027fa132bad1344cf114db3641d83262116d07',
duplicateKeyframes: '4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945',
duplicateSelectors: '8982145dba05b33bf1c93b2d54cfbe76305b276ff3c657aa020144016ada5848',
keyframes: 'b9b0bf3fad92e69b93ec0c24f01da15e78bbe89a095597d64ce4f7ef5e272fdd',
ruleDeclarationSequences: '3a65866ea25506c6fd79b68bfbbdeddd495f6957dbd99dec6a814b816ba4cca2',
selectors: '56e1c67b35230649a3c69b2aea67c1929580700f1b4357ee05dfb11012d72655',
variableReferences: '71722a81fa16b3586ae9ee5890f79176729dfdf7fe58c4d4994755f8059aa034',
witnesses: '2272ed9b07e02edd232c33a971c4cc5171f6a612ccaa36418933f0fd6bb465c1',
ruleDeclarationSequences: '6226141f0ff66b775008149ccf7d7a55e952c3f5d75961e275f0509ee352a4d6',
selectors: '3a165769801a80e9bee5082728a58f38bb427a19ac2c764de8586a5831c9ec87',
variableReferences: 'bdae48e482697d7cff6fdc434860cdacf19c8e3cee24b35574e461c3cff73a51',
witnesses: 'aa6334ad87124e5c0dc56af0f8927523aad3002444395adb1c50c0b8a36601bb',
},
};
@@ -212,7 +212,7 @@ test('client typography uses the shared semantic scale outside the token owner',
test('accepted stylesheet has pinned declaration, selector, keyframe, variable, and cascade ledgers', () => {
const witnesses = readStyleWitnesses(root);
assert.equal(witnesses.length, 1292);
assert.equal(witnesses.length, 1281);
assert.equal(witnesses.filter((witness) => witness.unknown || witness.ancestorUnknown).length, 0);
const ledger = createStyleLedger(readStyleSource(root), { witnesses });
assert.deepEqual(ledger.counts, acceptedLedger.counts);
@@ -409,8 +409,8 @@ test('main owns one public stylesheet and the regrouped production CSS is determ
assert.equal((main.match(/import ['"][^'"]+\.css['"]/g) || []).length, 1);
const assets = fs.readdirSync(path.join(root, 'dist/assets')).filter((file) => file.endsWith('.css'));
assert.deepEqual(assets, ['index-tJmxnB8a.css']);
assert.deepEqual(assets, ['index-Djad1gX3.css']);
const built = fs.readFileSync(path.join(root, 'dist/assets', assets[0]));
assert.equal(built.byteLength, 176543);
assert.equal(sha256(built), '38a283204c656164c38c17aa03f41c931544e05b5732248807d911b2645bf970');
assert.equal(built.byteLength, 178147);
assert.equal(sha256(built), 'bc1e317d3da0840d6f88a764c52385d70b97ff0bcb51d3911059a34444c14b09');
});