Skip to content
This repository was archived by the owner on Oct 18, 2024. It is now read-only.

Commit

Permalink
Merge pull request #708 from SuperViz/feat/connection-limits-per-product
Browse files Browse the repository at this point in the history
Implement connection limits by product instead of by room
  • Loading branch information
carlossantos74 authored Jul 11, 2024
2 parents e408b8c + ecec227 commit 08aaedf
Show file tree
Hide file tree
Showing 24 changed files with 135 additions and 55 deletions.
17 changes: 13 additions & 4 deletions __mocks__/limits.mock.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { ComponentLimits } from '../src/services/limits/types';

export const LIMITS_MOCK: ComponentLimits = {
videoConference: true,
presence: true,
comments: true,
transcript: true,
presence: {
canUse: true,
maxParticipants: 50,
},
realtime: {
canUse: true,
maxParticipants: 200,
},
videoConference: {
canUse: true,
maxParticipants: 255,
canUseTranscript: true,
},
};
9 changes: 8 additions & 1 deletion src/components/base/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useGlobalStore } from '../../services/stores';
import { ComponentNames } from '../types';

import { BaseComponent } from '.';
import { LIMITS_MOCK } from '../../../__mocks__/limits.mock';

class DummyComponent extends BaseComponent {
protected logger: Logger;
Expand Down Expand Up @@ -70,6 +71,7 @@ describe('BaseComponent', () => {
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
Presence3DManagerService: Presence3DManager,
connectionLimit: LIMITS_MOCK.videoConference.maxParticipants,
useStore,
});

Expand All @@ -90,6 +92,7 @@ describe('BaseComponent', () => {
ioc: new IOC(MOCK_LOCAL_PARTICIPANT),
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
connectionLimit: LIMITS_MOCK.videoConference.maxParticipants,
useStore,
});

Expand All @@ -109,6 +112,7 @@ describe('BaseComponent', () => {
ioc: new IOC(MOCK_LOCAL_PARTICIPANT),
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
connectionLimit: LIMITS_MOCK.videoConference.maxParticipants,
useStore,
});

Expand All @@ -126,8 +130,9 @@ describe('BaseComponent', () => {
config: null as unknown as Configuration,
eventBus: null as unknown as EventBus,
useStore: null as unknown as typeof useStore,
connectionLimit: LIMITS_MOCK.videoConference.maxParticipants,
});
}).toThrowError();
}).toThrow();
});
});

Expand All @@ -141,6 +146,7 @@ describe('BaseComponent', () => {
ioc: new IOC(MOCK_LOCAL_PARTICIPANT),
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
connectionLimit: LIMITS_MOCK.videoConference.maxParticipants,
useStore,
});

Expand All @@ -162,6 +168,7 @@ describe('BaseComponent', () => {
ioc: new IOC(MOCK_LOCAL_PARTICIPANT),
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
connectionLimit: LIMITS_MOCK.videoConference.maxParticipants,
useStore,
});

Expand Down
4 changes: 3 additions & 1 deletion src/components/base/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { DefaultAttachComponentOptions } from './types';
export abstract class BaseComponent extends Observable {
public abstract name: ComponentNames;
protected abstract logger: Logger;
protected connectionLimit: number | 'unlimited';
protected group: Group;
protected ioc: IOC;
protected eventBus: EventBus;
Expand Down Expand Up @@ -51,7 +52,8 @@ export abstract class BaseComponent extends Observable {
this.eventBus = eventBus;
this.isAttached = true;
this.ioc = ioc;
this.room = ioc.createRoom(this.name);
this.connectionLimit = params.connectionLimit ?? 50;
this.room = ioc.createRoom(this.name, this.connectionLimit);

if (!hasJoinedRoom.value) {
this.logger.log(`${this.name} @ attach - not joined yet`);
Expand Down
1 change: 1 addition & 0 deletions src/components/base/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface DefaultAttachComponentOptions {
eventBus: EventBus;
useStore: <T extends StoreType>(name: T) => Store<T>;
Presence3DManagerService: typeof Presence3DManager;
connectionLimit: number | 'unlimited';
}

export type GlobalStore = {
Expand Down
4 changes: 4 additions & 0 deletions src/components/comments/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { ComponentNames } from '../types';
import { PinAdapter, CommentsSide, Annotation, PinCoordinates } from './types';

import { Comments } from './index';
import { LIMITS_MOCK } from '../../../__mocks__/limits.mock';

const MOCK_PARTICIPANTS: ParticipantByGroupApi[] = [
{
Expand Down Expand Up @@ -83,6 +84,7 @@ describe('Comments', () => {
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
Presence3DManagerService: Presence3DManager,
connectionLimit: LIMITS_MOCK.presence.maxParticipants,
useStore,
});

Expand Down Expand Up @@ -337,6 +339,7 @@ describe('Comments', () => {
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
Presence3DManagerService: Presence3DManager,
connectionLimit: LIMITS_MOCK.presence.maxParticipants,
useStore,
});

Expand All @@ -356,6 +359,7 @@ describe('Comments', () => {
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
Presence3DManagerService: Presence3DManager,
connectionLimit: LIMITS_MOCK.presence.maxParticipants,
useStore,
});

Expand Down
2 changes: 2 additions & 0 deletions src/components/form-elements/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ComponentNames } from '../types';
import { FieldEvents } from './types';

import { FormElements } from '.';
import { LIMITS_MOCK } from '../../../__mocks__/limits.mock';

describe('form elements', () => {
let instance: any;
Expand All @@ -32,6 +33,7 @@ describe('form elements', () => {
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
Presence3DManagerService: Presence3DManager,
connectionLimit: LIMITS_MOCK.presence.maxParticipants,
useStore,
});
});
Expand Down
2 changes: 2 additions & 0 deletions src/components/presence-mouse/canvas/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { MOCK_CANVAS } from '../../../../__mocks__/canvas.mock';
import { MOCK_CONFIG } from '../../../../__mocks__/config.mock';
import { EVENT_BUS_MOCK } from '../../../../__mocks__/event-bus.mock';
import { LIMITS_MOCK } from '../../../../__mocks__/limits.mock';
import { MOCK_LOCAL_PARTICIPANT } from '../../../../__mocks__/participants.mock';
import { useStore } from '../../../common/utils/use-store';
import { IOC } from '../../../services/io';
Expand Down Expand Up @@ -53,6 +54,7 @@ const createMousePointers = (): PointersCanvas => {
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
Presence3DManagerService: Presence3DManager,
connectionLimit: LIMITS_MOCK.presence.maxParticipants,
useStore,
});

Expand Down
3 changes: 3 additions & 0 deletions src/components/presence-mouse/html/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Presence3DManager } from '../../../services/presence-3d-manager';
import { ParticipantMouse } from '../types';

import { PointersHTML } from '.';
import { LIMITS_MOCK } from '../../../../__mocks__/limits.mock';

const createMousePointers = (id: string = 'html'): PointersHTML => {
const presenceMouseComponent = new PointersHTML(id);
Expand All @@ -17,6 +18,7 @@ const createMousePointers = (id: string = 'html'): PointersHTML => {
config: MOCK_CONFIG,
Presence3DManagerService: Presence3DManager,
eventBus: EVENT_BUS_MOCK,
connectionLimit: LIMITS_MOCK.presence.maxParticipants,
useStore,
});

Expand Down Expand Up @@ -379,6 +381,7 @@ describe('MousePointers on HTML', () => {
eventBus: EVENT_BUS_MOCK,
ioc: new IOC(MOCK_LOCAL_PARTICIPANT),
Presence3DManagerService: Presence3DManager,
connectionLimit: LIMITS_MOCK.presence.maxParticipants,
useStore,
});

Expand Down
14 changes: 8 additions & 6 deletions src/components/realtime/channel.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { LIMITS_MOCK } from '../../../__mocks__/limits.mock';
import { MOCK_OBSERVER_HELPER } from '../../../__mocks__/observer-helper.mock';
import { MOCK_LOCAL_PARTICIPANT } from '../../../__mocks__/participants.mock';
import { IOC } from '../../services/io';
Expand All @@ -21,7 +22,8 @@ describe('Realtime Channel', () => {
ChannelInstance = new Channel(
'channel',
new IOC(MOCK_LOCAL_PARTICIPANT),
MOCK_LOCAL_PARTICIPANT
MOCK_LOCAL_PARTICIPANT,
LIMITS_MOCK.realtime.maxParticipants,
);

ChannelInstance['state'] = RealtimeChannelState.CONNECTED;
Expand Down Expand Up @@ -120,7 +122,7 @@ describe('Realtime Channel', () => {
});

const h = await ChannelInstance.fetchHistory();

expect(spy).toHaveBeenCalled();
expect(h).toEqual({
'unit-test-event-name': [
Expand Down Expand Up @@ -202,17 +204,17 @@ describe('Realtime Channel', () => {
ChannelInstance['state'] = RealtimeChannelState.DISCONNECTED;

ChannelInstance.disconnect();

expect(spy).not.toHaveBeenCalled();
});

test('Should log an error if a disconnect attempt is made when the channel is already disconnected', () => {
const spy = jest.spyOn(ChannelInstance['logger'], 'log' as any);
ChannelInstance['state'] = RealtimeChannelState.DISCONNECTED;

ChannelInstance.disconnect();

expect(spy).toHaveBeenCalled();
})
});
});
})
});
9 changes: 7 additions & 2 deletions src/components/realtime/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,18 @@ export class Channel extends Observable {
callback: (data: unknown) => void;
}> = [];

constructor(name: string, ioc: IOC, localParticipant: Participant) {
constructor(
name: string,
ioc: IOC,
localParticipant: Participant,
connectionLimit: number | 'unlimited',
) {
super();

this.name = name;
this.ioc = ioc;
this.logger = new Logger('@superviz/sdk/realtime-channel');
this.channel = this.ioc.createRoom(`realtime:${this.name}`);
this.channel = this.ioc.createRoom(`realtime:${this.name}`, connectionLimit);
this.localParticipant = localParticipant;

this.subscribeToRealtimeEvents();
Expand Down
2 changes: 2 additions & 0 deletions src/components/realtime/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Presence3DManager } from '../../services/presence-3d-manager';
import { RealtimeComponentState } from './types';

import { Realtime } from '.';
import { LIMITS_MOCK } from '../../../__mocks__/limits.mock';

jest.mock('lodash/throttle', () => jest.fn((fn) => fn));
jest.useFakeTimers();
Expand All @@ -27,6 +28,7 @@ describe('realtime component', () => {
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
Presence3DManagerService: Presence3DManager,
connectionLimit: LIMITS_MOCK.realtime.maxParticipants,
useStore,
});

Expand Down
4 changes: 2 additions & 2 deletions src/components/realtime/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class Realtime extends BaseComponent {

if (channel) return channel;

channel = new Channel(name, this.ioc, this.localParticipant);
channel = new Channel(name, this.ioc, this.localParticipant, this.connectionLimit);

this.channels.set(name, channel);

Expand Down Expand Up @@ -100,7 +100,7 @@ export class Realtime extends BaseComponent {

protected start(): void {
this.logger.log('started');
this.channel = new Channel('default', this.ioc, this.localParticipant);
this.channel = new Channel('default', this.ioc, this.localParticipant, this.connectionLimit);

this.channel.subscribe(RealtimeChannelEvent.REALTIME_CHANNEL_STATE_CHANGED, (state) => {
if (state !== RealtimeChannelState.CONNECTED) return;
Expand Down
2 changes: 1 addition & 1 deletion src/components/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ export enum ComponentNames {
}

export enum PresenceMap {
'comments' = 'presence',
'presence3dMatterport' = 'presence',
'presence3dAutodesk' = 'presence',
'presence3dThreejs' = 'presence',
'realtime' = 'presence',
'whoIsOnline' = 'presence',
'formElements' = 'presence',
}
Expand Down
3 changes: 3 additions & 0 deletions src/components/video/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { ParticipantToFrame } from './types';

import { VideoConference } from '.';
import { MEETING_COLORS } from '../../common/types/meeting-colors.types';
import { LIMITS_MOCK } from '../../../__mocks__/limits.mock';

Object.assign(global, { TextDecoder, TextEncoder });

Expand Down Expand Up @@ -94,6 +95,7 @@ describe('VideoConference', () => {
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
Presence3DManagerService: Presence3DManager,
connectionLimit: LIMITS_MOCK.videoConference.maxParticipants,
useStore,
});

Expand All @@ -118,6 +120,7 @@ describe('VideoConference', () => {
Presence3DManagerService: Presence3DManager,
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
connectionLimit: LIMITS_MOCK.videoConference.maxParticipants,
useStore,
});

Expand Down
2 changes: 2 additions & 0 deletions src/components/who-is-online/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { Avatar, WhoIsOnlineParticipant, TooltipData } from './types';

import { WhoIsOnline } from './index';
import { MEETING_COLORS } from '../../common/types/meeting-colors.types';
import { LIMITS_MOCK } from '../../../__mocks__/limits.mock';

const generateMockParticipant = ({
id,
Expand Down Expand Up @@ -61,6 +62,7 @@ describe('Who Is Online', () => {
config: MOCK_CONFIG,
eventBus: EVENT_BUS_MOCK,
Presence3DManagerService: Presence3DManager,
connectionLimit: LIMITS_MOCK.presence.maxParticipants,
useStore,
});

Expand Down
21 changes: 17 additions & 4 deletions src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,8 @@ const init = async (apiKey: string, options: SuperVizSdkOptions): Promise<Launch
throw new Error('Failed to validate API key');
}

const [environment, limits, waterMark] = await Promise.all([
const [environment, waterMark] = await Promise.all([
ApiService.fetchConfig(apiUrl, apiKey),
ApiService.fetchLimits(apiUrl, apiKey),
ApiService.fetchWaterMark(apiUrl, apiKey),
]).catch(() => {
throw new Error('Failed to load configuration from server');
Expand All @@ -130,7 +129,21 @@ const init = async (apiKey: string, options: SuperVizSdkOptions): Promise<Launch
environment: (options.environment as EnvironmentTypes) ?? EnvironmentTypes.PROD,
roomId,
debug: options.debug,
limits,
limits: {
presence: {
canUse: true,
maxParticipants: 50,
},
realtime: {
canUse: true,
maxParticipants: 200,
},
videoConference: {
canUse: true,
maxParticipants: 255,
canUseTranscript: true,
},
},
waterMark,
colors: options.customColors,
features,
Expand All @@ -141,7 +154,7 @@ const init = async (apiKey: string, options: SuperVizSdkOptions): Promise<Launch
ApiService.createOrUpdateParticipant({
name: participant.name,
participantId: participant.id,
avatar: participant.avatar?.imageUrl,
avatar: participant.avatar?.imageUrl,
});

return LauncherFacade(options);
Expand Down
Loading

0 comments on commit 08aaedf

Please sign in to comment.