Fix 'cannot find room' error

We weren't waiting for rooms to arrive down the sync stream after
joining them but before trying to use them.

More regression details in linked issue.

Fixes https://github.com/vector-im/element-call/issues/477
This commit is contained in:
David Baker 2022-07-20 16:01:29 +01:00
parent 6d7f52d2d6
commit 32b37ed8f0
4 changed files with 42 additions and 8 deletions

View file

@ -47,7 +47,7 @@ export function RegisteredView({ client }) {
setError(undefined);
setLoading(true);
const roomIdOrAlias = await createRoom(client, roomName, ptt);
const [roomIdOrAlias] = await createRoom(client, roomName, ptt);
if (roomIdOrAlias) {
history.push(`/room/${roomIdOrAlias}`);

View file

@ -70,7 +70,7 @@ export function UnauthenticatedView() {
let roomIdOrAlias;
try {
roomIdOrAlias = await createRoom(client, roomName, ptt);
[roomIdOrAlias] = await createRoom(client, roomName, ptt);
} catch (error) {
if (error.errcode === "M_ROOM_IN_USE") {
setOnFinished(() => () => {

View file

@ -220,8 +220,8 @@ export function isLocalRoomId(roomId: string): boolean {
export async function createRoom(
client: MatrixClient,
name: string
): Promise<string> {
await client.createRoom({
): Promise<[string, string]> {
const result = await client.createRoom({
visibility: Visibility.Private,
preset: Preset.PublicChat,
name,
@ -251,7 +251,7 @@ export async function createRoom(
},
});
return fullAliasFromRoomName(name, client);
return [fullAliasFromRoomName(name, client), result.room_id];
}
export function getRoomUrl(roomId: string): string {

View file

@ -21,6 +21,7 @@ import {
GroupCallIntent,
} from "matrix-js-sdk/src/webrtc/groupCall";
import { GroupCallEventHandlerEvent } from "matrix-js-sdk/src/webrtc/groupCallEventHandler";
import { ClientEvent } from "matrix-js-sdk/src/client";
import type { MatrixClient } from "matrix-js-sdk/src/client";
import type { Room } from "matrix-js-sdk/src/models/room";
@ -44,9 +45,38 @@ export const useLoadGroupCall = (
useEffect(() => {
setState({ loading: true });
const waitForRoom = async (roomId: string): Promise<Room> => {
const room = client.getRoom(roomId);
if (room) return room;
console.log(`Room ${roomId} hasn't arrived yet: waiting`);
const waitPromise = new Promise<Room>((resolve) => {
const onRoomEvent = async (room: Room) => {
if (room.roomId === roomId) {
client.removeListener(ClientEvent.Room, onRoomEvent);
resolve(room);
}
};
client.on(ClientEvent.Room, onRoomEvent);
});
// race the promise with a timeout so we don't
// wait forever for the room
const timeoutPromise = new Promise<Room>((_, reject) => {
setTimeout(() => {
reject(new Error("Timed out trying to join room"));
}, 30000);
});
return Promise.race([waitPromise, timeoutPromise]);
};
const fetchOrCreateRoom = async (): Promise<Room> => {
try {
return await client.joinRoom(roomIdOrAlias, { viaServers });
const room = await client.joinRoom(roomIdOrAlias, { viaServers });
// wait for the room to come down the sync stream, otherwise
// client.getRoom() won't return the room.
return waitForRoom(room.roomId);
} catch (error) {
if (
isLocalRoomId(roomIdOrAlias) &&
@ -55,8 +85,12 @@ export const useLoadGroupCall = (
error.message.indexOf("Failed to fetch alias") !== -1))
) {
// The room doesn't exist, but we can create it
await createRoom(client, roomNameFromRoomId(roomIdOrAlias));
return await client.joinRoom(roomIdOrAlias, { viaServers });
const [, roomId] = await createRoom(
client,
roomNameFromRoomId(roomIdOrAlias)
);
// likewise, wait for the room
return await waitForRoom(roomId);
} else {
throw error;
}