Retry joinRoom up to 5 times in the case of a 504 GATEWAY TIMEOUT
parent
c68a980c59
commit
229967aa33
|
@ -18,6 +18,7 @@ limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Store} from 'flux/utils';
|
import {Store} from 'flux/utils';
|
||||||
|
import {MatrixError} from "matrix-js-sdk/src/http-api";
|
||||||
|
|
||||||
import dis from '../dispatcher/dispatcher';
|
import dis from '../dispatcher/dispatcher';
|
||||||
import {MatrixClientPeg} from '../MatrixClientPeg';
|
import {MatrixClientPeg} from '../MatrixClientPeg';
|
||||||
|
@ -26,6 +27,9 @@ import Modal from '../Modal';
|
||||||
import { _t } from '../languageHandler';
|
import { _t } from '../languageHandler';
|
||||||
import { getCachedRoomIDForAlias, storeRoomAliasInCache } from '../RoomAliasCache';
|
import { getCachedRoomIDForAlias, storeRoomAliasInCache } from '../RoomAliasCache';
|
||||||
import {ActionPayload} from "../dispatcher/payloads";
|
import {ActionPayload} from "../dispatcher/payloads";
|
||||||
|
import {retry} from "../utils/promise";
|
||||||
|
|
||||||
|
const NUM_JOIN_RETRY = 5;
|
||||||
|
|
||||||
const INITIAL_STATE = {
|
const INITIAL_STATE = {
|
||||||
// Whether we're joining the currently viewed room (see isJoining())
|
// Whether we're joining the currently viewed room (see isJoining())
|
||||||
|
@ -259,24 +263,32 @@ class RoomViewStore extends Store<ActionPayload> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private joinRoom(payload: ActionPayload) {
|
private async joinRoom(payload: ActionPayload) {
|
||||||
this.setState({
|
this.setState({
|
||||||
joining: true,
|
joining: true,
|
||||||
});
|
});
|
||||||
MatrixClientPeg.get().joinRoom(
|
|
||||||
this.state.roomAlias || this.state.roomId, payload.opts,
|
const cli = MatrixClientPeg.get();
|
||||||
).then(() => {
|
const address = this.state.roomAlias || this.state.roomId;
|
||||||
|
try {
|
||||||
|
await retry<void, MatrixError>(() => cli.joinRoom(address, payload.opts), NUM_JOIN_RETRY, (err) => {
|
||||||
|
// if we received a Gateway timeout then retry
|
||||||
|
return err.httpStatus === 504;
|
||||||
|
});
|
||||||
|
|
||||||
// We do *not* clear the 'joining' flag because the Room object and/or our 'joined' member event may not
|
// We do *not* clear the 'joining' flag because the Room object and/or our 'joined' member event may not
|
||||||
// have come down the sync stream yet, and that's the point at which we'd consider the user joined to the
|
// have come down the sync stream yet, and that's the point at which we'd consider the user joined to the
|
||||||
// room.
|
// room.
|
||||||
dis.dispatch({ action: 'join_room_ready' });
|
dis.dispatch({ action: 'join_room_ready' });
|
||||||
}, (err) => {
|
} catch (err) {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'join_room_error',
|
action: 'join_room_error',
|
||||||
err: err,
|
err: err,
|
||||||
});
|
});
|
||||||
|
|
||||||
let msg = err.message ? err.message : JSON.stringify(err);
|
let msg = err.message ? err.message : JSON.stringify(err);
|
||||||
console.log("Failed to join room:", msg);
|
console.log("Failed to join room:", msg);
|
||||||
|
|
||||||
if (err.name === "ConnectionError") {
|
if (err.name === "ConnectionError") {
|
||||||
msg = _t("There was an error joining the room");
|
msg = _t("There was an error joining the room");
|
||||||
} else if (err.errcode === 'M_INCOMPATIBLE_ROOM_VERSION') {
|
} else if (err.errcode === 'M_INCOMPATIBLE_ROOM_VERSION') {
|
||||||
|
@ -296,12 +308,13 @@ class RoomViewStore extends Store<ActionPayload> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createTrackedDialog('Failed to join room', '', ErrorDialog, {
|
Modal.createTrackedDialog('Failed to join room', '', ErrorDialog, {
|
||||||
title: _t("Failed to join room"),
|
title: _t("Failed to join room"),
|
||||||
description: msg,
|
description: msg,
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getInvitingUserId(roomId: string): string {
|
private getInvitingUserId(roomId: string): string {
|
||||||
|
|
|
@ -68,3 +68,21 @@ export function allSettled<T>(promises: Promise<T>[]): Promise<Array<ISettledFul
|
||||||
}));
|
}));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper method to retry a Promise a given number of times or until a predicate fails
|
||||||
|
export async function retry<T, E extends Error>(fn: () => Promise<T>, num: number, predicate?: (e: E) => boolean) {
|
||||||
|
let lastErr: E;
|
||||||
|
for (let i = 0; i < num; i++) {
|
||||||
|
try {
|
||||||
|
const v = await fn();
|
||||||
|
// If `await fn()` throws then we won't reach here
|
||||||
|
return v;
|
||||||
|
} catch (err) {
|
||||||
|
if (predicate && !predicate(err)) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
lastErr = err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw lastErr;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue