Fix possible unknown state (With reproducible test) (#4944)
Signed-off-by: Timo K <toger5@hotmail.de>
This commit is contained in:
@@ -511,6 +511,32 @@ describe("MembershipManager", () => {
|
||||
|
||||
expect(client._unstable_updateDelayedEvent).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("updates the UpdateExpiry entry in the action scheduler", async () => {
|
||||
const manager = new MembershipManager({}, room, client, () => undefined);
|
||||
manager.join([focus], focusActive);
|
||||
await jest.advanceTimersByTimeAsync(1);
|
||||
// clearing all mocks before checking what happens when calling: `onRTCSessionMemberUpdate`
|
||||
(client.sendStateEvent as Mock).mockClear();
|
||||
(client._unstable_updateDelayedEvent as Mock).mockClear();
|
||||
(client._unstable_sendDelayedStateEvent as Mock).mockClear();
|
||||
|
||||
(client._unstable_updateDelayedEvent as Mock<any>).mockRejectedValueOnce(
|
||||
new MatrixError({ errcode: "M_NOT_FOUND" }),
|
||||
);
|
||||
|
||||
const { resolve } = createAsyncHandle(client._unstable_sendDelayedStateEvent);
|
||||
await jest.advanceTimersByTimeAsync(10_000);
|
||||
await manager.onRTCSessionMemberUpdate([mockCallMembership(membershipTemplate, room.roomId)]);
|
||||
resolve({ delay_id: "id" });
|
||||
await jest.advanceTimersByTimeAsync(10_000);
|
||||
|
||||
expect(client.sendStateEvent).toHaveBeenCalled();
|
||||
expect(client._unstable_sendDelayedStateEvent).toHaveBeenCalled();
|
||||
|
||||
expect(client._unstable_updateDelayedEvent).toHaveBeenCalled();
|
||||
expect(manager.status).toBe(Status.Connected);
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: Not sure about this name
|
||||
|
||||
@@ -243,7 +243,7 @@ export class MembershipManager
|
||||
this.logger.warn("Missing own membership: force re-join");
|
||||
this.state.hasMemberStateEvent = false;
|
||||
|
||||
if (this.scheduler.actions.find((a) => sendingMembershipActions.includes(a.type as MembershipActionType))) {
|
||||
if (this.scheduler.actions.some((a) => sendingMembershipActions.includes(a.type as MembershipActionType))) {
|
||||
this.logger.error(
|
||||
"tried adding another `SendDelayedEvent` actions even though we already have one in the Queue\nActionQueueOnMemberUpdate:",
|
||||
this.scheduler.actions,
|
||||
@@ -624,8 +624,21 @@ export class MembershipManager
|
||||
this.state.expireUpdateIterations = 1;
|
||||
this.state.hasMemberStateEvent = true;
|
||||
this.resetRateLimitCounter(MembershipActionType.SendJoinEvent);
|
||||
// An UpdateExpiry action might be left over from a previous join event.
|
||||
// We can reach sendJoinEvent when the delayed leave event gets send by the HS.
|
||||
// The branch where we might have a leftover UpdateExpiry action is:
|
||||
// RestartDelayedEvent (cannot find it, server removed it)
|
||||
// -> SendDelayedEvent (send new delayed event)
|
||||
// -> SendJoinEvent (here with a still scheduled UpdateExpiry action)
|
||||
const actionsWithoutUpdateExpiry = this.scheduler.actions.filter(
|
||||
(a) =>
|
||||
a.type !== MembershipActionType.UpdateExpiry && // A new UpdateExpiry action with an updated will be scheduled,
|
||||
a.type !== MembershipActionType.SendJoinEvent, // Manually remove the SendJoinEvent action,
|
||||
);
|
||||
return {
|
||||
insert: [
|
||||
replace: [
|
||||
...actionsWithoutUpdateExpiry,
|
||||
// To check if the delayed event is still there or got removed by inserting the stateEvent, we need to restart it.
|
||||
{ ts: Date.now(), type: MembershipActionType.RestartDelayedEvent },
|
||||
{
|
||||
ts: this.computeNextExpiryActionTs(this.state.expireUpdateIterations),
|
||||
|
||||
Reference in New Issue
Block a user