Skip to content

Commit

Permalink
feat: add peerlist iterator API and integration
Browse files Browse the repository at this point in the history
  • Loading branch information
raviteja83 authored Sep 28, 2023
1 parent acfec6f commit 189bbb3
Show file tree
Hide file tree
Showing 25 changed files with 402 additions and 166 deletions.
2 changes: 1 addition & 1 deletion packages/hms-video-store/src/core/IHMSActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
HMSConfig,
HMSLogLevel,
HMSMidCallPreviewConfig,
HMSPeerListIterator,
HMSPluginSupportResult,
HMSPreferredSimulcastLayer,
HMSPreviewConfig,
Expand All @@ -21,6 +20,7 @@ import {
HMSGenericTypes,
HMSMessageID,
HMSPeerID,
HMSPeerListIterator,
HMSPeerListIteratorOptions,
HMSRoleName,
HMSTrackID,
Expand Down
14 changes: 13 additions & 1 deletion packages/hms-video-store/src/core/hmsSDKStore/HMSSDKActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,19 @@ export class HMSSDKActions<T extends HMSGenericTypes = { sessionStore: Record<st
}

getPeerListIterator(options?: HMSPeerListIteratorOptions) {
return this.sdk.getPeerListIterator(options);
const iterator = this.sdk.getPeerListIterator(options);
return {
hasNext: () => iterator.hasNext(),
next: async () => {
const sdkPeers = await iterator.next();
return sdkPeers.map(peer => SDKToHMS.convertPeer(peer) as HMSPeer);
},
findPeers: async () => {
const sdkPeers = await iterator.findPeers();
return sdkPeers.map(peer => SDKToHMS.convertPeer(peer) as HMSPeer);
},
getTotal: () => iterator.getTotal(),
};
}

initAppData(appData: Record<string, any>) {
Expand Down
1 change: 1 addition & 0 deletions packages/hms-video-store/src/core/hmsSDKStore/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export class SDKToHMS {
startedAt: sdkRoom.startedAt,
joinedAt: sdkRoom.joinedAt,
peerCount: sdkRoom.peerCount,
isLargeRoom: sdkRoom.large_room_optimization,
};
}

Expand Down
1 change: 0 additions & 1 deletion packages/hms-video-store/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export {
parsedUserAgent,
simulcastMapping,
DeviceType,
HMSPeerListIterator,
} from './hmsSDKStore/sdkTypes';
export * from './webrtc-stats';

Expand Down
7 changes: 7 additions & 0 deletions packages/hms-video-store/src/core/schema/peer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,10 @@ export interface HMSSpeaker {
trackID: HMSTrackID;
audioLevel: number;
}

export interface HMSPeerListIterator {
hasNext(): boolean;
next(): Promise<HMSPeer[]>;
getTotal(): number;
findPeers(): Promise<HMSPeer[]>;
}
1 change: 1 addition & 0 deletions packages/hms-video-store/src/core/schema/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ export interface HMSRoom {
* if this number is available room.peers is not guaranteed to have all the peers.
*/
peerCount?: number;
isLargeRoom?: boolean;
}
1 change: 1 addition & 0 deletions packages/hms-video-store/src/core/selectors/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ export const selectRTMPState = createSelector(selectRoom, room => room.rtmp);
export const selectHLSState = createSelector(selectRoom, room => room.hls);
export const selectSessionId = createSelector(selectRoom, room => room.sessionId);
export const selectRoomStartTime = createSelector(selectRoom, room => room.startedAt);
export const selectIsLargeRoom = createSelector(selectRoom, room => !!room.isLargeRoom);
export const selectTemplateAppData = (store: HMSStore) => store.templateAppData;
/** @deprecated - use `selectSessionStore` instead */
export const selectSessionMetadata = (store: HMSStore) => store.sessionMetadata;
Expand Down
1 change: 0 additions & 1 deletion packages/hms-video-web/src/interfaces/update-listener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export enum HMSPeerUpdate {
HAND_RAISE_CHANGED,
PEER_REMOVED,
PEER_ADDED,
PEER_ITERATOR_UPDATED,
}

export enum HMSTrackUpdate {
Expand Down
66 changes: 39 additions & 27 deletions packages/hms-video-web/src/sdk/HMSPeerListIterator.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,62 @@
import { HMSRemotePeer } from './models/peer';
import { IStore } from './store';
import { HMSPeerUpdate, HMSUpdateListener } from '../interfaces';
import { HMSPeerListIteratorOptions } from '../interfaces/peer-list-iterator';
import { PeerNotificationInfo } from '../notification-manager';
import { createRemotePeer } from '../notification-manager/managers/utils';
import { PeersIterationResponse } from '../signal/interfaces';
import ITransport from '../transport/ITransport';

export class HMSPeerListIterator {
private isEnd = false;
private iteratorID: string | null = null;
private DEFAULT_LIMIT = 10;
constructor(
private transport: ITransport,
private store: IStore,
private listener?: HMSUpdateListener,
private options?: HMSPeerListIteratorOptions,
) {}
private iterator: string | null = null;
private total = 0;
private defaultPaginationLimit = 10;
constructor(private transport: ITransport, private store: IStore, private options?: HMSPeerListIteratorOptions) {}

hasNext(): boolean {
return !this.isEnd;
}

getTotal(): number {
return this.total;
}

async findPeers() {
const response = await this.transport.findPeers({
...(this.options || {}),
limit: this.options?.limit || this.defaultPaginationLimit,
});
this.updateState(response);
return this.processPeers(response.peers);
}

async next() {
let response: PeersIterationResponse;
if (!this.iteratorID) {
response = await this.transport.findPeer({
...(this.options || {}),
limit: this.options?.limit || this.DEFAULT_LIMIT,
});
} else {
if (!this.iterator && !this.isEnd) {
return await this.findPeers();
} else if (this.iterator) {
response = await this.transport.peerIterNext({
iterator: this.iteratorID,
limit: this.options?.limit || this.DEFAULT_LIMIT,
iterator: this.iterator,
limit: this.options?.limit || this.defaultPaginationLimit,
});
this.updateState(response);
return this.processPeers(response.peers);
}
this.isEnd = response.eof;
this.iteratorID = response.iterator;
return [];
}

private processPeers(peers: PeerNotificationInfo[]) {
const hmsPeers: HMSRemotePeer[] = [];
response.peers.forEach(peer => {
const storeHasPeer = this.store.getPeerById(peer.peer_id);
if (!storeHasPeer) {
const hmsPeer = createRemotePeer(peer, this.store);
hmsPeers.push(hmsPeer);
this.store.addPeer(hmsPeer);
}
peers.forEach(peer => {
const hmsPeer = createRemotePeer(peer, this.store);
hmsPeers.push(hmsPeer);
});
this.listener?.onPeerUpdate(HMSPeerUpdate.PEER_ITERATOR_UPDATED, hmsPeers);
return hmsPeers;
}

private updateState(response: PeersIterationResponse) {
this.isEnd = response.eof;
this.total = response.total;
this.iterator = response.iterator;
}
}
2 changes: 1 addition & 1 deletion packages/hms-video-web/src/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ export class HMSSdk implements HMSInterface {
}

getPeerListIterator(options?: HMSPeerListIteratorOptions) {
return new HMSPeerListIterator(this.transport, this.store, this.listener, options);
return new HMSPeerListIterator(this.transport, this.store, options);
}

private handleAutoplayError = (error: HMSException) => {
Expand Down
8 changes: 4 additions & 4 deletions packages/hms-video-web/src/signal/ISignal.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {
AcceptRoleChangeParams,
BroadcastResponse,
findPeerRequestParams,
findPeersRequestParams,
GetSessionMetadataResponse,
HLSRequestParams,
HLSTimedMetadataParams,
JoinLeaveGroupResponse,
MultiTrackUpdateRequestParams,
peerIterNextRequestParams,
peerIterRequestParams,
PeersIterationResponse,
PollInfoGetParams,
PollInfoGetResponse,
Expand Down Expand Up @@ -136,7 +136,7 @@ export interface ISignal extends IAnalyticsTransportProvider {

removeFromGroup(peerId: string, name: string): Promise<void>;

findPeer(params: findPeerRequestParams): Promise<PeersIterationResponse>;
findPeers(params: findPeersRequestParams): Promise<PeersIterationResponse>;

peerIterNext(params: peerIterNextRequestParams): Promise<PeersIterationResponse>;
peerIterNext(params: peerIterRequestParams): Promise<PeersIterationResponse>;
}
2 changes: 1 addition & 1 deletion packages/hms-video-web/src/signal/interfaces/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export interface JoinLeaveGroupResponse {

export interface PeersIterationResponse {
iterator: string;
limit: number;
total: number;
eof: boolean;
peers: PeerNotificationInfo[];
}
4 changes: 2 additions & 2 deletions packages/hms-video-web/src/signal/interfaces/superpowers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@ export interface getPeerRequestParams {
peerId: string;
}

export interface findPeerRequestParams {
export interface findPeersRequestParams {
peerIds?: string[];
role?: string;
group?: string;
limit: number;
}

export interface peerIterNextRequestParams {
export interface peerIterRequestParams {
iterator: string;
limit: number;
}
9 changes: 5 additions & 4 deletions packages/hms-video-web/src/signal/jsonrpc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ import { sleep } from '../../utils/timer-utils';
import {
AcceptRoleChangeParams,
BroadcastResponse,
findPeerRequestParams,
findPeersRequestParams,
getPeerRequestParams,
GetSessionMetadataResponse,
HLSRequestParams,
HLSTimedMetadataParams,
JoinLeaveGroupResponse,
MultiTrackUpdateRequestParams,
peerIterNextRequestParams,
peerIterRequestParams,
PeersIterationResponse,
PollInfoGetParams,
PollInfoGetResponse,
Expand Down Expand Up @@ -387,10 +387,11 @@ export default class JsonRpcSignal implements ISignal {
await this.call(HMSSignalMethod.GROUP_REMOVE, { name, peer_id: peerId });
}

async peerIterNext(params: peerIterNextRequestParams): Promise<PeersIterationResponse> {
async peerIterNext(params: peerIterRequestParams): Promise<PeersIterationResponse> {
return await this.call(HMSSignalMethod.PEER_ITER_NEXT, params);
}
async findPeer(params: findPeerRequestParams): Promise<PeersIterationResponse> {

async findPeers(params: findPeersRequestParams): Promise<PeersIterationResponse> {
return await this.call(HMSSignalMethod.FIND_PEER, params);
}

Expand Down
8 changes: 4 additions & 4 deletions packages/hms-video-web/src/transport/ITransport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import {
} from '../interfaces';
import { HMSLocalTrack } from '../media/tracks';
import {
findPeerRequestParams,
findPeersRequestParams,
GetSessionMetadataResponse,
JoinLeaveGroupResponse,
MultiTrackUpdateRequestParams,
peerIterNextRequestParams,
peerIterRequestParams,
PeersIterationResponse,
SetSessionMetadataParams,
SetSessionMetadataResponse,
Expand Down Expand Up @@ -81,7 +81,7 @@ export default interface ITransport {

removeFromGroup(peerId: string, name: string): Promise<void>;

findPeer(params: findPeerRequestParams): Promise<PeersIterationResponse>;
findPeers(params: findPeersRequestParams): Promise<PeersIterationResponse>;

peerIterNext(params: peerIterNextRequestParams): Promise<PeersIterationResponse>;
peerIterNext(params: peerIterRequestParams): Promise<PeersIterationResponse>;
}
10 changes: 5 additions & 5 deletions packages/hms-video-web/src/transport/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ import { IStore } from '../sdk/store';
import InitService from '../signal/init';
import { InitConfig, InitFlags } from '../signal/init/models';
import {
findPeerRequestParams,
findPeersRequestParams,
HLSRequestParams,
HLSTimedMetadataParams,
HLSVariant,
JoinLeaveGroupResponse,
MultiTrackUpdateRequestParams,
peerIterNextRequestParams,
peerIterRequestParams,
PeersIterationResponse,
PollInfoGetParams,
PollInfoGetResponse,
Expand Down Expand Up @@ -750,10 +750,10 @@ export default class HMSTransport implements ITransport {
this.signal.removeFromGroup(peerId, name);
}

findPeer(params: findPeerRequestParams): Promise<PeersIterationResponse> {
return this.signal.findPeer(params);
findPeers(params: findPeersRequestParams): Promise<PeersIterationResponse> {
return this.signal.findPeers(params);
}
peerIterNext(params: peerIterNextRequestParams): Promise<PeersIterationResponse> {
peerIterNext(params: peerIterRequestParams): Promise<PeersIterationResponse> {
return this.signal.peerIterNext(params);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/hms-video-web/src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ export const HMSEvents = {

export const PROTOCOL_VERSION = '2.5';

export const PROTOCOL_SPEC = '20230627';
export const PROTOCOL_SPEC = '20230919';

export const HAND_RAISE_GROUP_NAME = '_handraise';
54 changes: 54 additions & 0 deletions packages/react-sdk/src/hooks/usePaginatedParticipants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { useRef, useState } from 'react';
import { HMSPeer, HMSPeerListIteratorOptions } from '@100mslive/hms-video-store';
import { useHMSActions } from '../primitives/HmsRoomProvider';

export interface usePaginatedParticipantsResult {
/**
* call this function to load initial peers and also when you want to poll the peers information
*/
loadPeers: Promise<void>;
/**
* this function is to be called when loadPeers is called atleast once. This will fetch the next batch of peers
*/
loadMorePeers: Promise<void>;
// list of peers loaded
peers: HMSPeer[];
// total number of peers matching the input options at the time of the request
total: number;
}

export type usePaginatedParticipantsInput = HMSPeerListIteratorOptions;

const processPeers = (peers: HMSPeer[]) => {
return peers.reduce<Record<string, HMSPeer>>((acc, peer) => {
acc[peer.id] = peer;
return acc;
}, {});
};

export const usePaginatedParticipants = (options: HMSPeerListIteratorOptions) => {
const actions = useHMSActions();
const iterator = useRef(actions.getPeerListIterator(options));
const [peers, setPeers] = useState<Record<string, HMSPeer>>({});
const [total, setTotal] = useState(0);

return {
loadPeers: () =>
iterator.current.findPeers().then(peers => {
setPeers(processPeers(peers));
setTotal(iterator.current.getTotal());
}),
loadMorePeers: () =>
iterator.current.next().then(peers => {
setPeers(prevPeers => {
return {
...prevPeers,
...processPeers(peers),
};
});
setTotal(iterator.current.getTotal());
}),
total,
peers: Object.values(peers),
};
};
Loading

0 comments on commit 189bbb3

Please sign in to comment.