Skip to content

Commit

Permalink
[FIX] Video Conf Message Blocks not always updating when running on m…
Browse files Browse the repository at this point in the history
…icro services (#27764)
  • Loading branch information
pierre-lehnen-rc authored Feb 9, 2023
1 parent 4b234fe commit e86f1af
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 15 deletions.
4 changes: 2 additions & 2 deletions apps/meteor/client/lib/VideoConfManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ export type DirectCallParams = {
uid: IUser['_id'];
rid: IRoom['_id'];
callId: string;

// #ToDo: The attributes below should not be part of DirectCallParams - they are used by local events only, never notification events.
dismissed?: boolean;
acceptTimeout?: ReturnType<typeof setTimeout> | undefined;
// TODO: improve this, nowadays there is not possible check if the video call has finished, but ist a nice improvement
// state: 'incoming' | 'outgoing' | 'connected' | 'disconnected' | 'dismissed';
};

type IncomingDirectCall = DirectCallParams & { timeout: number };
Expand Down
20 changes: 20 additions & 0 deletions apps/meteor/server/modules/listeners/listeners.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { UserStatus, isSettingColor } from '@rocket.chat/core-typings';
import type { IUser, IRoom, VideoConference } from '@rocket.chat/core-typings';
import { parse } from '@rocket.chat/message-parser';
import type { IServiceClass } from '@rocket.chat/core-services';
import { EnterpriseSettings } from '@rocket.chat/core-services';
Expand Down Expand Up @@ -96,6 +97,25 @@ export class ListenersModule {
notifications.notifyLoggedInThisInstance('roles-change', update);
});

service.onEvent(
'user.video-conference',
({
userId,
action,
params,
}: {
userId: string;
action: string;
params: {
callId: VideoConference['_id'];
uid: IUser['_id'];
rid: IRoom['_id'];
};
}) => {
notifications.notifyUserInThisInstance(userId, 'video-conference', { action, params });
},
);

service.onEvent('presence.status', ({ user }) => {
const { _id, username, name, status, statusText, roles } = user;
if (!status) {
Expand Down
43 changes: 30 additions & 13 deletions apps/meteor/server/services/video-conference/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ export class VideoConfService extends ServiceClassInternal implements IVideoConf
if (call.endedAt || call.status > VideoConferenceStatus.STARTED) {
// If the caller is still calling about a call that has already ended, notify it
if (action === 'call' && caller === call.createdBy._id) {
Notifications.notifyUser(call.createdBy._id, 'video-conference.end', { rid, uid, callId });
this.notifyUser(call.createdBy._id, 'end', { rid, uid, callId });
}

return false;
Expand All @@ -410,6 +410,14 @@ export class VideoConfService extends ServiceClassInternal implements IVideoConf
return true;
}

private notifyUser(
userId: IUser['_id'],
action: string,
params: { uid: IUser['_id']; rid: IRoom['_id']; callId: VideoConference['_id'] },
): void {
api.broadcast('user.video-conference', { userId, action, params });
}

private notifyVideoConfUpdate(rid: IRoom['_id'], callId: VideoConference['_id']): void {
Notifications.notifyRoom(rid, callId);
}
Expand Down Expand Up @@ -442,19 +450,20 @@ export class VideoConfService extends ServiceClassInternal implements IVideoConf
const params = { rid: call.rid, uid: call.createdBy._id, callId: call._id };

// Notify the caller that the call was ended by the server
Notifications.notifyUser(call.createdBy._id, 'video-conference.end', params);
this.notifyUser(call.createdBy._id, 'end', params);

// If the callee hasn't joined the call yet, notify them that it has already ended
const subscriptions = await Subscriptions.findByRoomIdAndNotUserId(call.rid, call.createdBy._id, {
projection: { 'u._id': 1, '_id': 0 },
}).toArray();

for (const subscription of subscriptions) {
// Skip notifying users that already joined the call
if (call.users.find(({ _id }) => _id === subscription.u._id)) {
continue;
}

Notifications.notifyUser(subscription.u._id, 'video-conference.end', params);
this.notifyUser(subscription.u._id, 'end', params);
}
}

Expand Down Expand Up @@ -614,13 +623,16 @@ export class VideoConfService extends ServiceClassInternal implements IVideoConf
// After 40 seconds if the status is still "calling", we cancel the call automatically.
setTimeout(async () => {
try {
const call = await VideoConferenceModel.findOneById<Pick<VideoConference, '_id' | 'status'>>(callId, { projection: { status: 1 } });
const call = await VideoConferenceModel.findOneById<IDirectVideoConference>(callId);

if (call?.status !== VideoConferenceStatus.CALLING) {
return;
}
if (call) {
await this.endDirectCall(call);
if (call.status !== VideoConferenceStatus.CALLING) {
return;
}

await this.cancel(user._id, callId);
await this.cancel(user._id, callId);
}
} catch {
// Ignore errors on this timeout
}
Expand All @@ -633,12 +645,17 @@ export class VideoConfService extends ServiceClassInternal implements IVideoConf
};
}

private async notifyUsersOfRoom(rid: IRoom['_id'], uid: IUser['_id'], eventName: string, ...args: any[]): Promise<void> {
private async notifyUsersOfRoom(
rid: IRoom['_id'],
uid: IUser['_id'],
action: string,
params: { uid: IUser['_id']; rid: IRoom['_id']; callId: VideoConference['_id'] },
): Promise<void> {
const subscriptions = Subscriptions.findByRoomIdAndNotUserId(rid, uid, {
projection: { 'u._id': 1, '_id': 0 },
});

await subscriptions.forEach((subscription) => Notifications.notifyUser(subscription.u._id, eventName, ...args));
await subscriptions.forEach((subscription) => this.notifyUser(subscription.u._id, action, params));
}

private async startGroup(
Expand Down Expand Up @@ -677,7 +694,7 @@ export class VideoConfService extends ServiceClassInternal implements IVideoConf
VideoConferenceModel.setMessageById(callId, 'started', messageId);

if (call.ringing) {
await this.notifyUsersOfRoom(rid, user._id, 'video-conference.ring', { callId, rid, title, uid: call.createdBy, providerName });
await this.notifyUsersOfRoom(rid, user._id, 'ring', { callId, rid, uid: call.createdBy._id });
}

return {
Expand Down Expand Up @@ -917,9 +934,9 @@ export class VideoConfService extends ServiceClassInternal implements IVideoConf
private async updateDirectCall(call: IDirectVideoConference, newUserId: IUser['_id']): Promise<void> {
// If it's an user that hasn't joined yet
if (call.ringing && !call.users.find(({ _id }) => _id === newUserId)) {
Notifications.notifyUser(call.createdBy._id, 'video-conference.join', { rid: call.rid, uid: newUserId, callId: call._id });
this.notifyUser(call.createdBy._id, 'join', { rid: call.rid, uid: newUserId, callId: call._id });
if (newUserId !== call.createdBy._id) {
Notifications.notifyUser(newUserId, 'video-conference.join', { rid: call.rid, uid: newUserId, callId: call._id });
this.notifyUser(newUserId, 'join', { rid: call.rid, uid: newUserId, callId: call._id });
// If the callee joined the direct call, then we stopped ringing
await VideoConferenceModel.setRingingById(call._id, false);
}
Expand Down
10 changes: 10 additions & 0 deletions packages/core-services/src/Events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import type {
VoipEventDataSignature,
AtLeast,
UserStatus,
VideoConference,
} from '@rocket.chat/core-typings';

import type { AutoUpdateRecord } from './types/IMeteor';
Expand Down Expand Up @@ -91,6 +92,15 @@ export type EventSignatures = {
'user.roleUpdate'(update: Record<string, any>): void;
'user.updateCustomStatus'(userStatus: IUserStatus): void;
'user.typing'(data: { user: Partial<IUser>; isTyping: boolean; roomId: string }): void;
'user.video-conference'(data: {
userId: IUser['_id'];
action: string;
params: {
callId: VideoConference['_id'];
uid: IUser['_id'];
rid: IRoom['_id'];
};
}): void;
'presence.status'(data: {
user: Pick<IUser, '_id' | 'username' | 'status' | 'statusText' | 'name' | 'roles'>;
previousStatus: UserStatus | undefined;
Expand Down

0 comments on commit e86f1af

Please sign in to comment.