fix(ui): keep route diagnostic labels stable (#318)
This commit is contained in:
1 parent
27421f458c
commit
b129b3dbc0
4 files changed
+160
-14
No files matched your search
@@ -88,8 +88,6 @@ interface RoomRuntime {
|
||||
pump?: Promise<void>;
|
||||
deadlineTimer?: NodeJS.Timeout;
|
||||
sfuRefreshesInFlight: Set<string>;
|
||||
debugOrdinalByPeerId: Map<string, number>;
|
||||
nextDebugOrdinal: number;
|
||||
}
|
||||
|
||||
interface PreparedCandidate {
|
||||
@@ -201,7 +199,6 @@ export class HybridMediaRouter {
|
||||
room.advertisedCapacityByViewer.get(input.peerId) ?? 0,
|
||||
);
|
||||
}
|
||||
this.debugPeer(input.roomId, input.peerId);
|
||||
if (room.controller) {
|
||||
this.releaseResources(
|
||||
room.controller.upsertParticipant({
|
||||
@@ -932,7 +929,6 @@ export class HybridMediaRouter {
|
||||
removeViewer(roomId: string, peerId: string): void {
|
||||
const room = this.rooms.get(roomId);
|
||||
room?.advertisedCapacityByViewer.delete(peerId);
|
||||
room?.debugOrdinalByPeerId.delete(peerId);
|
||||
this.options.deleteConnectionId(roomId, peerId);
|
||||
if (room?.controller?.confirmDeparture(peerId, this.now())) {
|
||||
this.requestPump(roomId);
|
||||
@@ -965,8 +961,6 @@ export class HybridMediaRouter {
|
||||
advertisedCapacityByViewer: new Map(),
|
||||
requested: false,
|
||||
sfuRefreshesInFlight: new Set(),
|
||||
debugOrdinalByPeerId: new Map(),
|
||||
nextDebugOrdinal: 1,
|
||||
};
|
||||
this.rooms.set(roomId, room);
|
||||
}
|
||||
@@ -1952,14 +1946,9 @@ export class HybridMediaRouter {
|
||||
private debugPeer(roomId: string, peerId: string): string {
|
||||
const room = this.rooms.get(roomId);
|
||||
if (peerId === room?.hostPeerId) return "host";
|
||||
if (!room) return "viewer-unknown";
|
||||
let ordinal = room.debugOrdinalByPeerId.get(peerId);
|
||||
if (ordinal === undefined) {
|
||||
ordinal = room.nextDebugOrdinal;
|
||||
room.nextDebugOrdinal += 1;
|
||||
room.debugOrdinalByPeerId.set(peerId, ordinal);
|
||||
}
|
||||
return `viewer-${ordinal}`;
|
||||
return (
|
||||
room?.controller?.diagnosticParticipantLabel(peerId) ?? "viewer-unknown"
|
||||
);
|
||||
}
|
||||
|
||||
private debugTuple(roomId: string, tuple: CandidateTuple): string {
|
||||
|
||||
@@ -375,6 +375,10 @@ export class RoomRouteController<Resource = unknown> {
|
||||
});
|
||||
}
|
||||
|
||||
diagnosticParticipantLabel(peerId: string): string {
|
||||
return this.debugPeer(peerId);
|
||||
}
|
||||
|
||||
snapshot(): RouteSnapshot<Resource> {
|
||||
return {
|
||||
revision: this.revision,
|
||||
|
||||
@@ -234,6 +234,124 @@ async function establishSfuRoom(
|
||||
}
|
||||
|
||||
describe("HybridMediaRouter v9 runtime", () => {
|
||||
it("keeps the controller diagnostic label until a departed relay is pruned", async () => {
|
||||
const { store, sent, router } = harness(2);
|
||||
try {
|
||||
const room = await store.createRoom();
|
||||
const host = connectHost(store, room);
|
||||
complete(router, host);
|
||||
const parent = connectViewer(store, room, "diagnostic-label-parent");
|
||||
complete(router, parent);
|
||||
const parentPrepare = await vi.waitFor(() => {
|
||||
const prepared = preparedFor(sent, parent.sessionId);
|
||||
expect(prepared).toBeDefined();
|
||||
return prepared!;
|
||||
});
|
||||
router.handleRouteReady(parent, {
|
||||
type: "route-ready",
|
||||
revision: parentPrepare.revision,
|
||||
phase: "prepare",
|
||||
});
|
||||
router.setViewerRelayCapacity(parent, 1);
|
||||
|
||||
const temporaryRoot = connectViewer(
|
||||
store,
|
||||
room,
|
||||
"diagnostic-label-temporary-root",
|
||||
);
|
||||
complete(router, temporaryRoot);
|
||||
const temporaryPrepare = await vi.waitFor(() => {
|
||||
const prepared = preparedFor(sent, temporaryRoot.sessionId);
|
||||
expect(prepared?.assignment.upstream).toEqual({
|
||||
kind: "peer",
|
||||
peerId: host.peerId,
|
||||
});
|
||||
return prepared!;
|
||||
});
|
||||
router.handleRouteReady(temporaryRoot, {
|
||||
type: "route-ready",
|
||||
revision: temporaryPrepare.revision,
|
||||
phase: "prepare",
|
||||
});
|
||||
|
||||
const child = connectViewer(store, room, "diagnostic-label-child");
|
||||
complete(router, child);
|
||||
const childPrepare = await vi.waitFor(() => {
|
||||
const prepared = preparedFor(sent, child.sessionId);
|
||||
expect(prepared?.assignment.upstream).toEqual({
|
||||
kind: "peer",
|
||||
peerId: parent.peerId,
|
||||
});
|
||||
return prepared!;
|
||||
});
|
||||
router.handleRouteReady(child, {
|
||||
type: "route-ready",
|
||||
revision: childPrepare.revision,
|
||||
phase: "prepare",
|
||||
});
|
||||
|
||||
store.disconnectParticipant(
|
||||
room.roomId,
|
||||
temporaryRoot.peerId,
|
||||
temporaryRoot.sessionId,
|
||||
);
|
||||
router.disconnectParticipant(
|
||||
room.roomId,
|
||||
temporaryRoot.peerId,
|
||||
temporaryRoot.sessionId,
|
||||
);
|
||||
router.removeViewer(room.roomId, temporaryRoot.peerId);
|
||||
await vi.waitFor(() =>
|
||||
expect(
|
||||
router.resolveActiveViewerMediaEdge(
|
||||
room.roomId,
|
||||
temporaryRoot.peerId,
|
||||
),
|
||||
).toBeUndefined(),
|
||||
);
|
||||
|
||||
const internal = router as unknown as {
|
||||
debugPeer(roomId: string, peerId: string): string;
|
||||
};
|
||||
const label = internal.debugPeer(room.roomId, parent.peerId);
|
||||
|
||||
store.disconnectParticipant(
|
||||
room.roomId,
|
||||
parent.peerId,
|
||||
parent.sessionId,
|
||||
);
|
||||
router.disconnectParticipant(
|
||||
room.roomId,
|
||||
parent.peerId,
|
||||
parent.sessionId,
|
||||
);
|
||||
router.removeViewer(room.roomId, parent.peerId);
|
||||
expect(internal.debugPeer(room.roomId, parent.peerId)).toBe(label);
|
||||
|
||||
const recovery = await vi.waitFor(() => {
|
||||
const prepared = preparedFor(sent, child.sessionId);
|
||||
expect(prepared?.revision).toBeGreaterThan(childPrepare.revision);
|
||||
expect(prepared?.assignment.upstream).toEqual({
|
||||
kind: "peer",
|
||||
peerId: host.peerId,
|
||||
});
|
||||
return prepared!;
|
||||
});
|
||||
router.handleRouteReady(child, {
|
||||
type: "route-ready",
|
||||
revision: recovery.revision,
|
||||
phase: "prepare",
|
||||
});
|
||||
await vi.waitFor(() =>
|
||||
expect(internal.debugPeer(room.roomId, parent.peerId)).toBe(
|
||||
"viewer-unknown",
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
await router.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("maps an exact Host active failure to its committed direct edge", async () => {
|
||||
const { store, sent, router } = harness(2);
|
||||
try {
|
||||
|
||||
@@ -353,6 +353,41 @@ function qualityMetrics(
|
||||
}
|
||||
|
||||
describe("RoomRouteController", () => {
|
||||
it("keeps one diagnostic label until a departed relay is finally pruned", () => {
|
||||
const routes = controller(2);
|
||||
addViewer(routes, A, 1);
|
||||
addViewer(routes, B, 0);
|
||||
routes.hydrateEdge(A, peerEdge(HOST, "a_from_host"));
|
||||
routes.hydrateEdge(B, peerEdge(A, "b_from_a"));
|
||||
const label = routes.diagnosticParticipantLabel(A);
|
||||
expect(label).toMatch(/^viewer-\d+$/);
|
||||
|
||||
routes.upsertParticipant({
|
||||
peerId: A,
|
||||
role: "viewer",
|
||||
sessionId: "a_replacement_session",
|
||||
effectiveDownstreamCapacity: 1,
|
||||
});
|
||||
expect(routes.diagnosticParticipantLabel(A)).toBe(label);
|
||||
expect(routes.disconnectSession(A, "a_replacement_session")).toBe(true);
|
||||
expect(routes.diagnosticParticipantLabel(A)).toBe(label);
|
||||
expect(routes.confirmDeparture(A, 0)).toBe(true);
|
||||
expect(routes.diagnosticParticipantLabel(A)).toBe(label);
|
||||
|
||||
const repair = routes.reconcile(1).operation!;
|
||||
expect(repair).toMatchObject({
|
||||
childPeerId: B,
|
||||
reason: "parent-departed",
|
||||
});
|
||||
commitCurrent(routes, 2, "b_from_host");
|
||||
const pruned = routes.reconcile(4);
|
||||
expect(pruned.removedPeerIds).toContain(A);
|
||||
expect(routes.diagnosticParticipantLabel(A)).toBe("viewer-unknown");
|
||||
|
||||
addViewer(routes, C, 0);
|
||||
expect(routes.diagnosticParticipantLabel(C)).not.toBe(label);
|
||||
});
|
||||
|
||||
it("keeps isolated limitation windows diagnostic", () => {
|
||||
const routes = controller(2, { qualityConvergenceEnabled: true });
|
||||
addViewer(routes, A, 2);
|
||||
|
||||
Reference in new issue
Block a user