mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 09:01:03 -08:00
test(perf): sample both J2 settle captures in one main-process snapshot
The settle sample read J1's capture (pending calls) and J2's capture (call count) in two evaluate calls, so a call starting in between was counted with a stale zero in flight and its completion went unseen. Both states are now read in one synchronous pass, where no ipcMain event can be handled in between. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5ca9c0b4c7
commit
6f0477c3f5
3 files changed
+71
-19
No files matched your search
@@ -7,7 +7,7 @@ import {
|
||||
installJourneyMainIpcCapture,
|
||||
JOURNEY_MAIN_IPC_STATE_KEY,
|
||||
JOURNEY_RENDERER_API_TRACE_CHANNEL,
|
||||
peekJourneyMainIpcCapture,
|
||||
peekJourneyMainIpcCaptures,
|
||||
readJourneyMainIpcCapture,
|
||||
} from '../performance/journey-main-ipc-capture';
|
||||
import type { JourneyMockRequestLedger } from '../performance/journey-mock-request-ledger';
|
||||
@@ -90,10 +90,13 @@ async function waitForQuiet(
|
||||
}> {
|
||||
const armMark = ledger.mark();
|
||||
const sample = async (): Promise<ActivitySample> => {
|
||||
const launchCapture = await peekJourneyMainIpcCapture(
|
||||
electronApp,
|
||||
JOURNEY_MAIN_IPC_STATE_KEY
|
||||
);
|
||||
// Both captures in one snapshot: a call counted by J2's capture is
|
||||
// then also pending in J1's, never counted with a stale in-flight 0.
|
||||
const [launchCapture, openSourceCapture] =
|
||||
await peekJourneyMainIpcCaptures(electronApp, [
|
||||
JOURNEY_MAIN_IPC_STATE_KEY,
|
||||
OPEN_SOURCE_JOURNEY_MAIN_IPC_STATE_KEY,
|
||||
]);
|
||||
if (launchCapture.unmatchedCompletions > 0) {
|
||||
throw new Error('open-source-journey-bridge-completions-unmatched');
|
||||
}
|
||||
@@ -101,12 +104,7 @@ async function waitForQuiet(
|
||||
domMutations: await readPreStartMutations(page, probeStateKey),
|
||||
httpInFlight: ledger.inFlight(),
|
||||
httpRequests: ledger.mark(),
|
||||
ipcCalls: (
|
||||
await peekJourneyMainIpcCapture(
|
||||
electronApp,
|
||||
OPEN_SOURCE_JOURNEY_MAIN_IPC_STATE_KEY
|
||||
)
|
||||
).callsBeforeStart,
|
||||
ipcCalls: openSourceCapture.callsBeforeStart,
|
||||
ipcInFlight: countJourneyMainIpcInFlight(launchCapture),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
installJourneyMainIpcCapture,
|
||||
JOURNEY_RENDERER_API_TRACE_CHANNEL,
|
||||
peekJourneyMainIpcCapture,
|
||||
peekJourneyMainIpcCaptures,
|
||||
type JourneyMainIpcCaptureOptions,
|
||||
type JourneyMainIpcCaptureState,
|
||||
} from './journey-main-ipc-capture';
|
||||
@@ -372,3 +373,39 @@ test('a detached capture stops listening and keeps its last state', async () =>
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('reads several captures in one main-process pass', async () => {
|
||||
const fake = createFakeElectronApp();
|
||||
let evaluations = 0;
|
||||
const counting = {
|
||||
evaluate: (...args: Parameters<ElectronApplication['evaluate']>) => {
|
||||
evaluations += 1;
|
||||
return fake.app.evaluate(...args);
|
||||
},
|
||||
} as unknown as ElectronApplication;
|
||||
const target = globalThis as unknown as Record<string, unknown>;
|
||||
const [first, second] = ['__journeyPeekA', '__journeyPeekB'];
|
||||
target[first] = { callsBeforeStart: 1 };
|
||||
target[second] = { callsBeforeStart: 2 };
|
||||
try {
|
||||
const states = await peekJourneyMainIpcCaptures(counting, [
|
||||
first,
|
||||
second,
|
||||
]);
|
||||
assert.equal(evaluations, 1);
|
||||
assert.deepEqual(
|
||||
states.map((state) => state.callsBeforeStart),
|
||||
[1, 2]
|
||||
);
|
||||
await assert.rejects(
|
||||
peekJourneyMainIpcCaptures(counting, [
|
||||
first,
|
||||
'__journeyPeekMissing',
|
||||
]),
|
||||
/capture-missing/
|
||||
);
|
||||
} finally {
|
||||
delete target[first];
|
||||
delete target[second];
|
||||
}
|
||||
});
|
||||
@@ -213,20 +213,37 @@ export async function peekJourneyMainIpcCapture(
|
||||
electronApp: ElectronApplication,
|
||||
stateKey: string
|
||||
): Promise<JourneyMainIpcCaptureState> {
|
||||
const state = (await electronApp.evaluate(
|
||||
(_electron, key) =>
|
||||
const [state] = await peekJourneyMainIpcCaptures(electronApp, [stateKey]);
|
||||
return state as JourneyMainIpcCaptureState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Several captures read in one synchronous pass in the main process. No
|
||||
* `ipcMain` event can be handled in between, so the states are one coherent
|
||||
* snapshot: a call counted by one capture is also pending in the other.
|
||||
*/
|
||||
export async function peekJourneyMainIpcCaptures(
|
||||
electronApp: ElectronApplication,
|
||||
stateKeys: readonly string[]
|
||||
): Promise<JourneyMainIpcCaptureState[]> {
|
||||
const states = (await electronApp.evaluate(
|
||||
(_electron, keys) =>
|
||||
JSON.parse(
|
||||
JSON.stringify(
|
||||
(globalThis as unknown as Record<string, unknown>)[key] ??
|
||||
null
|
||||
keys.map(
|
||||
(key) =>
|
||||
(globalThis as unknown as Record<string, unknown>)[
|
||||
key
|
||||
] ?? null
|
||||
)
|
||||
)
|
||||
) as unknown,
|
||||
stateKey
|
||||
)) as JourneyMainIpcCaptureState | null;
|
||||
if (!state) {
|
||||
[...stateKeys]
|
||||
)) as (JourneyMainIpcCaptureState | null)[];
|
||||
if (states.some((state) => !state)) {
|
||||
throw new Error('journey-main-ipc-capture-missing');
|
||||
}
|
||||
return state;
|
||||
return states as JourneyMainIpcCaptureState[];
|
||||
}
|
||||
|
||||
export async function readJourneyMainIpcCapture(
|
||||
|
||||
Reference in new issue
Block a user