Files
iptvnator/apps/electron-backend-e2e/src/performance/xtream-cancellation-evidence-binding.ts
T
4gray a2fafcfc08 test(performance): add end-to-end Xtream benchmark harness (#1300)
* docs(performance): plan Xtream benchmark

* feat(xtream-mock-server): add deterministic 100k fixture

* style(xtream-mock-server): apply repository formatting

* fix(xtream-mock-server): harden performance fixture data

* feat(xtream-mock-server): add performance control plane

* docs(performance): correct Xtream capture plan

* fix(xtream-mock-server): harden performance controls

* fix(xtream-mock-server): harden control lifecycle

* feat(performance): add Xtream preload markers

* feat(performance): trace Xtream main phases

* feat(performance): mark Xtream store publications

* feat(performance): trace Xtream database phases

* feat(performance): trace Xtream delete cancellation

* feat(performance): capture Xtream phase attribution

* feat(performance): mark Sources Xtream refresh

* test(performance): define Xtream benchmark evidence contracts

* test(performance): add Xtream benchmark runner

* test(performance): surface failure evidence writes

* test(performance): align database read clock

* test(performance): preserve capture failure contracts
2026-07-28 08:08:07 +02:00

259 lines
9.1 KiB
TypeScript

import type { DatabaseWorkerCancelTimelineRecord } from './database-worker-cancel-capture';
import { snapshotXtreamCancellationEvidence } from './xtream-cancellation-evidence-snapshot';
import {
isFiniteNonNegative,
isPositiveSafeInteger,
} from './xtream-exact-schema';
import type {
XtreamAttributionPhaseEvent,
XtreamIpcAttributionSpan,
} from './xtream-phase-attribution';
import {
hasDistinctMonotonicXtreamIpcProducerIdentities,
XTREAM_IPC_PRODUCER_NAMESPACE,
xtreamIpcProducerNamespaceForWorkerOperation,
type XtreamIpcProducerIdentity,
} from './xtream-ipc-producer-identity';
import { XTREAM_ATTRIBUTION_PHASE as PHASE } from './xtream-phase-inventory';
import type {
XtreamCancellationMetrics,
XtreamRawIterationResult,
} from './xtream-summary-contract';
type WorkerRequest =
XtreamRawIterationResult['databaseWorker']['requests']['evidence'][number];
const RECORD_TYPES = [
'db-cancel-dispatched',
'db-cancel-received',
'db-cancel-terminal-received',
] as const;
export function assertXtreamCancellationEvidenceBinding(
raw: XtreamRawIterationResult,
events: readonly XtreamAttributionPhaseEvent[],
ipcSpans: readonly XtreamIpcAttributionSpan[],
requests: readonly WorkerRequest[]
): void {
const failed = requests.filter(
({ operation, success }) => operation === 'DB_SAVE_CONTENT' && !success
);
if (raw.scenarioId !== 'xtream-cancel-import') {
if (failed.length !== 0 || raw.cancellationEvidence !== null) invalid();
return;
}
const request = failed[0];
if (
failed.length !== 1 ||
!request ||
typeof request.requestId !== 'string' ||
typeof request.operationId !== 'string' ||
raw.cancellation.failedDatabaseRequestId !== request.requestId ||
raw.cancellation.failedOperationId !== request.operationId
) {
invalid();
}
const timeline = cancellationTimeline(raw, request);
const databasePreload = ipcPair(ipcSpans, 'dbCancelOperation');
assertCancellationProducerIdentity(timeline, databasePreload[0], requests);
assertCancellationTimeline(
raw.cancellation,
request,
timeline,
phaseSpan(
events,
PHASE.SQLITE_CONTENT_WRITE_TRANSACTIONS,
request.requestId
),
phaseSpan(events, PHASE.CANCEL_SESSION),
phaseSpan(events, PHASE.STORE_IMPORT_TERMINAL),
ipcPair(ipcSpans, 'xtreamCancelSession'),
databasePreload,
raw.phaseCapture.uiPaintEpochMs
);
}
interface Span {
readonly endEpochMs: number;
readonly startEpochMs: number;
}
function assertCancellationTimeline(
value: XtreamCancellationMetrics,
request: WorkerRequest,
timeline: readonly DatabaseWorkerCancelTimelineRecord[],
write: Span,
networkCancel: Span,
terminal: Span,
networkPreload: readonly [
XtreamIpcAttributionSpan,
XtreamIpcAttributionSpan,
],
databasePreload: readonly [
XtreamIpcAttributionSpan,
XtreamIpcAttributionSpan,
],
uiPaintEpochMs: number
): void {
const [dispatchRecord, receiptRecord, workerTerminalRecord] = timeline;
if (!dispatchRecord || !receiptRecord || !workerTerminalRecord) invalid();
const click = epoch(value.clickEpochMs);
const preloadStart = epoch(value.preloadStartEpochMs);
const preloadReturn = epoch(value.preloadReturnEpochMs);
const dispatch = epoch(value.databaseDispatchEpochMs);
const receipt = epoch(value.workerReceiptEpochMs);
const authoritative = epoch(value.authoritativeTerminalEpochMs);
const painted = epoch(value.paintedEpochMs);
if (
request.requestReceivedEpochMs === null ||
request.workEndedEpochMs === null ||
click < write.startEpochMs ||
click < request.requestReceivedEpochMs ||
click > write.endEpochMs ||
networkPreload[0].startEpochMs < click ||
networkPreload[0].endEpochMs > networkCancel.startEpochMs ||
networkCancel.endEpochMs > networkPreload[1].startEpochMs ||
networkPreload[1].startEpochMs > databasePreload[0].startEpochMs ||
preloadStart !== databasePreload[0].startEpochMs ||
dispatchRecord.ipcCallId !== databasePreload[0].ipcCallId ||
dispatchRecord.sourceEpochMs !== databasePreload[0].sourceEpochMs ||
databasePreload[0].endEpochMs > dispatch ||
dispatch !== dispatchRecord.epochMs ||
dispatch < request.requestReceivedEpochMs ||
dispatch > write.endEpochMs ||
databasePreload[1].startEpochMs < dispatch ||
preloadReturn !== databasePreload[1].endEpochMs ||
preloadReturn < dispatch ||
receipt !== receiptRecord.epochMs ||
receipt < dispatch ||
receipt > request.workEndedEpochMs ||
receipt > authoritative ||
workerTerminalRecord.epochMs < receipt ||
workerTerminalRecord.epochMs > authoritative ||
authoritative !== request.responseEpochMs ||
terminal.startEpochMs < authoritative ||
terminal.endEpochMs > painted ||
painted !== uiPaintEpochMs
) {
invalid();
}
}
function cancellationTimeline(
raw: XtreamRawIterationResult,
request: WorkerRequest
): readonly DatabaseWorkerCancelTimelineRecord[] {
const evidence = snapshotXtreamCancellationEvidence(
raw.cancellationEvidence
);
if (evidence === null) invalid();
const timeline = evidence.timeline;
if (timeline.length !== RECORD_TYPES.length) invalid();
const first = timeline[0];
if (!first) invalid();
for (let index = 0; index < timeline.length; index += 1) {
const record = timeline[index];
if (
!record ||
record.type !== RECORD_TYPES[index] ||
!isFiniteNonNegative(record.epochMs) ||
!isFiniteNonNegative(record.sourceEpochMs) ||
!isPositiveSafeInteger(record.ipcCallId) ||
typeof record.operationId !== 'string' ||
record.operationId.length === 0 ||
typeof record.requestId !== 'string' ||
record.requestId.length === 0 ||
record.ipcCallId !== first.ipcCallId ||
record.operationId !== first.operationId ||
record.requestId !== first.requestId ||
record.sourceEpochMs !== first.sourceEpochMs
) {
invalid();
}
}
if (
first.requestId !== request.requestId ||
first.operationId !== request.operationId
) {
invalid();
}
return timeline;
}
function assertCancellationProducerIdentity(
timeline: readonly DatabaseWorkerCancelTimelineRecord[],
databasePreload: XtreamIpcAttributionSpan,
requests: readonly WorkerRequest[]
): void {
const dispatch = timeline[0];
if (
!dispatch ||
dispatch.ipcCallId !== databasePreload.ipcCallId ||
dispatch.sourceEpochMs !== databasePreload.sourceEpochMs
) {
invalid();
}
const identities: XtreamIpcProducerIdentity[] = [];
for (const { ipcCallId, operation, sourceEpochMs } of requests) {
if (ipcCallId === null && sourceEpochMs === null) continue;
const namespace = xtreamIpcProducerNamespaceForWorkerOperation(
typeof operation === 'string' ? operation : ''
);
if (
namespace === null ||
!isPositiveSafeInteger(ipcCallId) ||
!isFiniteNonNegative(sourceEpochMs)
) {
invalid();
}
if (namespace === XTREAM_IPC_PRODUCER_NAMESPACE.XTREAM_PRELOAD) {
identities.push({ ipcCallId, namespace, sourceEpochMs });
}
}
identities.push({
ipcCallId: databasePreload.ipcCallId,
namespace: XTREAM_IPC_PRODUCER_NAMESPACE.XTREAM_PRELOAD,
sourceEpochMs: databasePreload.sourceEpochMs,
});
if (!hasDistinctMonotonicXtreamIpcProducerIdentities(identities)) {
invalid();
}
}
function phaseSpan(
events: readonly XtreamAttributionPhaseEvent[],
phase: string,
correlationId?: string
): Span {
const selected = events.filter(
(event) =>
event.phase === phase &&
(correlationId === undefined ||
event.correlationId === correlationId)
);
const start = selected.find(({ boundary }) => boundary === 'start');
const end = selected.find(({ boundary }) => boundary === 'end');
if (selected.length !== 2 || !start || !end) invalid();
return { endEpochMs: end.epochMs, startEpochMs: start.epochMs };
}
function ipcPair(
spans: readonly XtreamIpcAttributionSpan[],
method: string
): readonly [XtreamIpcAttributionSpan, XtreamIpcAttributionSpan] {
const selected = spans.filter((span) => span.method === method);
const request = selected.find(({ boundary }) => boundary === 'request');
const response = selected.find(({ boundary }) => boundary === 'response');
if (selected.length !== 2 || !request || !response) invalid();
return [request, response];
}
function epoch(value: number | null): number {
if (!isFiniteNonNegative(value)) invalid();
return value;
}
function invalid(): never {
throw new Error('invalid Xtream persisted cancellation evidence');
}