Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MatrixRTC: Rename MembershipConfig parameters #4714

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions spec/unit/matrixrtc/MatrixRTCSession.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,10 +406,10 @@ describe("MatrixRTCSession", () => {
jest.useRealTimers();
});

it("uses membershipExpiryTimeout from join config", async () => {
it("uses membershipEventExpiry from join config", async () => {
const realSetTimeout = setTimeout;
jest.useFakeTimers();
sess!.joinRoomSession([mockFocus], mockFocus, { membershipExpiryTimeout: 60000 });
sess!.joinRoomSession([mockFocus], mockFocus, { membershipEventExpiry: 60000 });
await Promise.race([sentStateEvent, new Promise((resolve) => realSetTimeout(resolve, 500))]);
expect(client.sendStateEvent).toHaveBeenCalledWith(
mockRoom!.roomId,
Expand Down Expand Up @@ -483,7 +483,7 @@ describe("MatrixRTCSession", () => {
});

sess!.joinRoomSession([activeFocusConfig], activeFocus, {
membershipServerSideExpiryTimeout: 9000,
delayedLeaveEventDelay: 9000,
});

await sendDelayedStateExceedAttempt.then(); // needed to resolve after the send attempt catches
Expand Down
18 changes: 7 additions & 11 deletions src/matrixrtc/MatrixRTCSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,36 +58,32 @@ export interface MembershipConfig {
/**
* The timeout (in milliseconds) after we joined the call, that our membership should expire
* unless we have explicitly updated it.
*
* This is what goes into the m.rtc.member event expiry field.
*/
membershipExpiryTimeout?: number;

/**
* The period (in milliseconds) with which we check that our membership event still exists on the
* server. If it is not found we create it again.
*/
memberEventCheckPeriod?: number;
membershipEventExpiry?: number;

/**
* The minimum delay (in milliseconds) after which we will retry sending the membership event if it
* failed to send.
*/
callMemberEventRetryDelayMinimum?: number;
membershipEventLocalRateLimit?: number;

/**
* The timeout (in milliseconds) with which the deleayed leave event on the server is configured.
* After this time the server will set the event to the disconnected stat if it has not received a keep-alive from the client.
*/
membershipServerSideExpiryTimeout?: number;
delayedLeaveEventDelay?: number;

/**
* The interval (in milliseconds) in which the client will send membership keep-alives to the server.
*/
membershipKeepAlivePeriod?: number;
delayedLeaveEventRestartPeriod?: number;

/**
* @deprecated It should be possible to make it stable without this.
*/
callMemberEventRetryJitter?: number;
membershipEventJitter?: number;
}
export interface EncryptionConfig {
/**
Expand Down
45 changes: 19 additions & 26 deletions src/matrixrtc/MembershipManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export interface IMembershipManager {
* - send that sate event
* - send the delayed leave event
* - update the delayed leave event while connected
* - update the state event when it times out (for calls longer than membershipExpiryTimeout ~ 4h)
* - update the state event when it times out (for calls longer than membershipEventExpiry ~ 4h)
*
* It is possible to test this class on its own. The api surface (to use for tests) is
* defined in `MembershipManagerInterface`.
Expand All @@ -83,30 +83,26 @@ export class LegacyMembershipManager implements IMembershipManager {
private updateCallMembershipRunning = false;
private needCallMembershipUpdate = false;
/**
* If the server disallows the configured {@link membershipServerSideExpiryTimeout},
* If the server disallows the configured {@link delayedLeaveEventDelay},
* this stores a delay that the server does allow.
*/
private membershipServerSideExpiryTimeoutOverride?: number;
private delayedLeaveEventDelayOverride?: number;
private disconnectDelayId: string | undefined;

private get callMemberEventRetryDelayMinimum(): number {
return this.joinConfig?.callMemberEventRetryDelayMinimum ?? 3_000;
private get membershipEventLocalRateLimit(): number {
return this.joinConfig?.membershipEventLocalRateLimit ?? 3_000;
}
private get membershipExpiryTimeout(): number {
return this.joinConfig?.membershipExpiryTimeout ?? DEFAULT_EXPIRE_DURATION;
private get membershipEventExpiry(): number {
return this.joinConfig?.membershipEventExpiry ?? DEFAULT_EXPIRE_DURATION;
}
private get membershipServerSideExpiryTimeout(): number {
return (
this.membershipServerSideExpiryTimeoutOverride ??
this.joinConfig?.membershipServerSideExpiryTimeout ??
8_000
);
private get delayedLeaveEventDelay(): number {
return this.delayedLeaveEventDelayOverride ?? this.joinConfig?.delayedLeaveEventDelay ?? 8_000;
}
private get membershipKeepAlivePeriod(): number {
return this.joinConfig?.membershipKeepAlivePeriod ?? 5_000;
private get delayedLeaveEventRestartPeriod(): number {
return this.joinConfig?.delayedLeaveEventRestartPeriod ?? 5_000;
}
private get callMemberEventRetryJitter(): number {
return this.joinConfig?.callMemberEventRetryJitter ?? 2_000;
private get membershipEventJitter(): number {
return this.joinConfig?.membershipEventJitter ?? 2_000;
}

public constructor(
Expand All @@ -131,7 +127,7 @@ export class LegacyMembershipManager implements IMembershipManager {
public join(fociPreferred: Focus[], fociActive?: Focus): void {
this.ownFocusActive = fociActive;
this.ownFociPreferred = fociPreferred;
this.relativeExpiry = this.membershipExpiryTimeout;
this.relativeExpiry = this.membershipEventExpiry;
// We don't wait for this, mostly because it may fail and schedule a retry, so this
// function returning doesn't really mean anything at all.
this.triggerCallMembershipEventUpdate();
Expand Down Expand Up @@ -255,7 +251,7 @@ export class LegacyMembershipManager implements IMembershipManager {
this.client._unstable_sendDelayedStateEvent(
this.room.roomId,
{
delay: this.membershipServerSideExpiryTimeout,
delay: this.delayedLeaveEventDelay,
},
EventType.GroupCallMemberPrefix,
{}, // leave event
Expand All @@ -270,11 +266,8 @@ export class LegacyMembershipManager implements IMembershipManager {
e.data["org.matrix.msc4140.errcode"] === "M_MAX_DELAY_EXCEEDED"
) {
const maxDelayAllowed = e.data["org.matrix.msc4140.max_delay"];
if (
typeof maxDelayAllowed === "number" &&
this.membershipServerSideExpiryTimeout > maxDelayAllowed
) {
this.membershipServerSideExpiryTimeoutOverride = maxDelayAllowed;
if (typeof maxDelayAllowed === "number" && this.delayedLeaveEventDelay > maxDelayAllowed) {
this.delayedLeaveEventDelayOverride = maxDelayAllowed;
return prepareDelayedDisconnection();
}
}
Expand Down Expand Up @@ -343,15 +336,15 @@ export class LegacyMembershipManager implements IMembershipManager {
}
logger.info("Sent updated call member event.");
} catch (e) {
const resendDelay = this.callMemberEventRetryDelayMinimum + Math.random() * this.callMemberEventRetryJitter;
const resendDelay = this.membershipEventLocalRateLimit + Math.random() * this.membershipEventJitter;
logger.warn(`Failed to send call member event (retrying in ${resendDelay}): ${e}`);
await sleep(resendDelay);
await this.triggerCallMembershipEventUpdate();
}
}

private scheduleDelayDisconnection(): void {
this.memberEventTimeout = setTimeout(this.delayDisconnection, this.membershipKeepAlivePeriod);
this.memberEventTimeout = setTimeout(this.delayDisconnection, this.delayedLeaveEventRestartPeriod);
}

private readonly delayDisconnection = async (): Promise<void> => {
Expand Down
Loading