mirror of
https://github.com/vector-im/element-call.git
synced 2026-09-07 21:45:18 +00:00
Log remote member participant matching and tile waiting state
A tile shows "Waiting for media" for as long as its MatrixRTC member cannot be matched to a LiveKit participant. Log each transition of that match and of the tile's waitingForMedia state so rageshakes can tie a stuck tile to the LiveKit participant and track events.
This commit is contained in:
@@ -5,7 +5,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|||||||
Please see LICENSE in the repository root for full details.
|
Please see LICENSE in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
import { describe, test, expect, beforeEach, afterEach, vi } from "vitest";
|
||||||
|
import { logger } from "matrix-js-sdk/lib/logger";
|
||||||
import {
|
import {
|
||||||
type CallMembership,
|
type CallMembership,
|
||||||
type LivekitTransport,
|
type LivekitTransport,
|
||||||
@@ -77,6 +78,7 @@ function epochMeWith$<T, U>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("should signal participant not yet connected to livekit", async () => {
|
test("should signal participant not yet connected to livekit", async () => {
|
||||||
|
const info = vi.spyOn(logger, "info");
|
||||||
const mockedMemberships$ = new BehaviorSubject([bobMembership]);
|
const mockedMemberships$ = new BehaviorSubject([bobMembership]);
|
||||||
const mockConnectionManagerData$ = new BehaviorSubject(
|
const mockConnectionManagerData$ = new BehaviorSubject(
|
||||||
new ConnectionManagerData(),
|
new ConnectionManagerData(),
|
||||||
@@ -108,6 +110,9 @@ test("should signal participant not yet connected to livekit", async () => {
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
expect(info).toHaveBeenCalledWith(
|
||||||
|
"[RemoteMatrixLivekitMembers] @bob:example.org:DEV000: LiveKit participant missing",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Helper to create epoch'ed memberships$ and membershipsWithTransport$ from memberships observable.
|
// Helper to create epoch'ed memberships$ and membershipsWithTransport$ from memberships observable.
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
type LivekitTransportConfig,
|
type LivekitTransportConfig,
|
||||||
} from "matrix-js-sdk/lib/matrixrtc";
|
} from "matrix-js-sdk/lib/matrixrtc";
|
||||||
import { combineLatest, filter, map } from "rxjs";
|
import { combineLatest, filter, map } from "rxjs";
|
||||||
|
import { logger } from "matrix-js-sdk/lib/logger";
|
||||||
|
|
||||||
import { type Behavior } from "../../Behavior";
|
import { type Behavior } from "../../Behavior";
|
||||||
import { type IConnectionManager } from "./ConnectionManager";
|
import { type IConnectionManager } from "./ConnectionManager";
|
||||||
@@ -133,8 +134,15 @@ export function createRemoteMatrixLivekitMembers$({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Each update where the key of the generator array do not change will result in updates to the `data$` behavior.
|
// Each update where the key of the generator array do not change will result in updates to the `data$` behavior.
|
||||||
(scope, data$, userId, _deviceId, _memberId, _rtcBackendIdentity) => {
|
(scope, data$, userId, _deviceId, _memberId, rtcBackendIdentity) => {
|
||||||
const { participant$, ...rest } = scope.splitBehavior(data$);
|
const { participant$, ...rest } = scope.splitBehavior(data$);
|
||||||
|
// Log whether the member could be matched to a LiveKit participant,
|
||||||
|
// since a tile shows "waiting for media" for as long as it cannot.
|
||||||
|
participant$.pipe(scope.bind()).subscribe((p) => {
|
||||||
|
logger.info(
|
||||||
|
`[RemoteMatrixLivekitMembers] ${rtcBackendIdentity}: LiveKit participant ${p ? `matched (${p.sid})` : "missing"}`,
|
||||||
|
);
|
||||||
|
});
|
||||||
// will only get called once per backend identity.
|
// will only get called once per backend identity.
|
||||||
// updates to data$ and as a result to displayName$ and mxcAvatarUrl$ are more frequent.
|
// updates to data$ and as a result to displayName$ and mxcAvatarUrl$ are more frequent.
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Please see LICENSE in the repository root for full details.
|
|||||||
|
|
||||||
import { type RemoteParticipant } from "livekit-client";
|
import { type RemoteParticipant } from "livekit-client";
|
||||||
import { combineLatest, map, of, switchMap } from "rxjs";
|
import { combineLatest, map, of, switchMap } from "rxjs";
|
||||||
|
import { logger } from "matrix-js-sdk/lib/logger";
|
||||||
|
|
||||||
import { type Behavior } from "../Behavior";
|
import { type Behavior } from "../Behavior";
|
||||||
import { createVolumeControls, type VolumeControls } from "../VolumeControls";
|
import { createVolumeControls, type VolumeControls } from "../VolumeControls";
|
||||||
@@ -45,6 +46,20 @@ export function createRemoteUserMedia(
|
|||||||
statsType: "inbound-rtp",
|
statsType: "inbound-rtp",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const waitingForMedia$ = scope.behavior(
|
||||||
|
combineLatest(
|
||||||
|
[inputs.livekitRoom$, inputs.participant$],
|
||||||
|
(livekitRoom, participant) =>
|
||||||
|
// If livekitRoom is undefined, the user is not attempting to publish on
|
||||||
|
// any transport and so we shouldn't expect a participant. (They might
|
||||||
|
// be a subscribe-only bot for example.)
|
||||||
|
livekitRoom !== undefined && participant === null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
waitingForMedia$.pipe(scope.bind()).subscribe((waiting) => {
|
||||||
|
logger.info(`[RemoteUserMedia ${inputs.id}] waitingForMedia=${waiting}`);
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...baseUserMedia,
|
...baseUserMedia,
|
||||||
...createVolumeControls(scope, {
|
...createVolumeControls(scope, {
|
||||||
@@ -68,15 +83,6 @@ export function createRemoteUserMedia(
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
waitingForMedia$: scope.behavior(
|
waitingForMedia$,
|
||||||
combineLatest(
|
|
||||||
[inputs.livekitRoom$, inputs.participant$],
|
|
||||||
(livekitRoom, participant) =>
|
|
||||||
// If livekitRoom is undefined, the user is not attempting to publish on
|
|
||||||
// any transport and so we shouldn't expect a participant. (They might
|
|
||||||
// be a subscribe-only bot for example.)
|
|
||||||
livekitRoom !== undefined && participant === null,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user