backend: optimize webhook notification methods for asynchronous execution

This commit is contained in:
Carlos Santos 2025-05-28 13:15:00 +02:00
parent b9a11dd45d
commit b6ace8d4ad
2 changed files with 95 additions and 51 deletions

View File

@ -155,7 +155,7 @@ export class LivekitWebhookService {
return; return;
} }
await this.openViduWebhookService.sendMeetingStartedWebhook(meetRoom); this.openViduWebhookService.sendMeetingStartedWebhook(meetRoom);
} catch (error) { } catch (error) {
this.logger.error('Error sending meeting started webhook:', error); this.logger.error('Error sending meeting started webhook:', error);
} }
@ -181,22 +181,18 @@ export class LivekitWebhookService {
this.logger.info(`Processing room_finished event for room: ${roomName}`); this.logger.info(`Processing room_finished event for room: ${roomName}`);
this.openViduWebhookService.sendMeetingEndedWebhook(meetRoom);
const tasks = [];
if (meetRoom.markedForDeletion) { if (meetRoom.markedForDeletion) {
// If the room is marked for deletion, we need to delete it // If the room is marked for deletion, we need to delete it
this.logger.info(`Deleting room ${roomName} after meeting finished because it was marked for deletion`); this.logger.info(`Deleting room ${roomName} after meeting finished because it was marked for deletion`);
await this.roomService.bulkDeleteRooms([roomName], true); tasks.push(this.roomService.bulkDeleteRooms([roomName], true));
} }
const results = await Promise.allSettled([ tasks.push(this.recordingService.releaseRecordingLockIfNoEgress(roomName));
this.recordingService.releaseRecordingLockIfNoEgress(roomName), await Promise.all(tasks);
this.openViduWebhookService.sendMeetingEndedWebhook(meetRoom)
]);
results.forEach((result) => {
if (result.status === 'rejected') {
this.logger.error(`Error processing room_finished event: ${result.reason}`);
}
});
} catch (error) { } catch (error) {
this.logger.error(`Error handling room finished event: ${error}`); this.logger.error(`Error handling room finished event: ${error}`);
} }
@ -236,13 +232,11 @@ export class LivekitWebhookService {
// Send webhook notification // Send webhook notification
switch (webhookAction) { switch (webhookAction) {
case 'started': case 'started':
specificTasks.push( specificTasks.push(this.storageService.archiveRoomMetadata(roomId));
this.storageService.archiveRoomMetadata(roomId), this.openViduWebhookService.sendRecordingStartedWebhook(recordingInfo);
this.openViduWebhookService.sendRecordingStartedWebhook(recordingInfo)
);
break; break;
case 'updated': case 'updated':
specificTasks.push(this.openViduWebhookService.sendRecordingUpdatedWebhook(recordingInfo)); this.openViduWebhookService.sendRecordingUpdatedWebhook(recordingInfo);
if (recordingInfo.status === MeetRecordingStatus.ACTIVE) { if (recordingInfo.status === MeetRecordingStatus.ACTIVE) {
// Send system event for active recording with the aim of cancelling the cleanup timer // Send system event for active recording with the aim of cancelling the cleanup timer
@ -256,10 +250,8 @@ export class LivekitWebhookService {
break; break;
case 'ended': case 'ended':
specificTasks.push( specificTasks.push(this.recordingService.releaseRecordingLockIfNoEgress(roomId));
this.openViduWebhookService.sendRecordingEndedWebhook(recordingInfo), this.openViduWebhookService.sendRecordingEndedWebhook(recordingInfo);
this.recordingService.releaseRecordingLockIfNoEgress(roomId)
);
break; break;
} }

View File

@ -18,44 +18,96 @@ export class OpenViduWebhookService {
@inject(MeetStorageService) protected globalPrefService: MeetStorageService @inject(MeetStorageService) protected globalPrefService: MeetStorageService
) {} ) {}
async sendMeetingStartedWebhook(room: MeetRoom) { /**
try { * Sends a webhook notification when a meeting has started.
await this.sendWebhookEvent(MeetWebhookEventType.MEETING_STARTED, room); *
} catch (error) { * This method triggers a background webhook event to notify external systems
this.logger.error(`Error sending meeting started webhook: ${error}`); * that a meeting session has begun for the specified room.
} *
* @param room - The meeting room object containing room details
*/
sendMeetingStartedWebhook(room: MeetRoom) {
this.sendWebhookEventInBackground(MeetWebhookEventType.MEETING_STARTED, room, `Room ID: ${room.roomId}`);
} }
async sendMeetingEndedWebhook(room: MeetRoom) { /**
try { * Sends a webhook notification when a meeting has ended.
await this.sendWebhookEvent(MeetWebhookEventType.MEETING_ENDED, room); *
} catch (error) { * This method triggers a background webhook event to notify external systems
this.logger.error(`Error sending meeting ended webhook: ${error}`); * that a meeting session has concluded for the specified room.
} *
* @param room - The MeetRoom object containing details of the ended meeting
*/
sendMeetingEndedWebhook(room: MeetRoom) {
this.sendWebhookEventInBackground(MeetWebhookEventType.MEETING_ENDED, room, `Room ID: ${room.roomId}`);
} }
async sendRecordingStartedWebhook(recordingInfo: MeetRecordingInfo) { /**
try { * Sends a webhook event notification when a recording has started.
await this.sendWebhookEvent(MeetWebhookEventType.RECORDING_STARTED, recordingInfo); *
} catch (error) { * This method triggers a background webhook event to notify external systems
this.logger.error(`Error sending recording started webhook: ${error}`); * that a meeting recording has been initiated.
} *
* @param recordingInfo - The recording information containing details about the started recording
*/
sendRecordingUpdatedWebhook(recordingInfo: MeetRecordingInfo) {
this.sendWebhookEventInBackground(
MeetWebhookEventType.RECORDING_UPDATED,
recordingInfo,
`Recording ID: ${recordingInfo.recordingId}`
);
} }
async sendRecordingUpdatedWebhook(recordingInfo: MeetRecordingInfo) { /**
try { * Sends a webhook notification when a recording has started.
await this.sendWebhookEvent(MeetWebhookEventType.RECORDING_UPDATED, recordingInfo); *
} catch (error) { * This method triggers a background webhook event to notify external services
this.logger.error(`Error sending recording updated webhook: ${error}`); * that a meeting recording has begun. The webhook includes the recording
} * information and uses the recording ID for identification purposes.
*
* @param recordingInfo - The recording information containing details about the started recording
*/
sendRecordingStartedWebhook(recordingInfo: MeetRecordingInfo) {
this.sendWebhookEventInBackground(
MeetWebhookEventType.RECORDING_STARTED,
recordingInfo,
`Recording ID: ${recordingInfo.recordingId}`
);
} }
async sendRecordingEndedWebhook(recordingInfo: MeetRecordingInfo) { /**
try { * Sends a webhook notification when a recording has ended.
await this.sendWebhookEvent(MeetWebhookEventType.RECORDING_ENDED, recordingInfo); *
} catch (error) { * This method triggers a background webhook event to notify external systems
this.logger.error(`Error sending recording ended webhook: ${error}`); * that a meeting recording has completed.
} *
* @param recordingInfo - The recording information containing details about the ended recording
*/
sendRecordingEndedWebhook(recordingInfo: MeetRecordingInfo) {
this.sendWebhookEventInBackground(
MeetWebhookEventType.RECORDING_ENDED,
recordingInfo,
`Recording ID: ${recordingInfo.recordingId}`
);
}
/**
* Sends a webhook event asynchronously in the background without blocking the main execution flow.
* If the webhook fails, logs a warning message with the error details and optional context information.
*
* @param event - The type of webhook event to send
* @param payload - The data payload to include with the webhook event
* @param context - Optional context string to include in error messages for debugging purposes
*/
protected sendWebhookEventInBackground(
event: MeetWebhookEventType,
payload: MeetWebhookPayload,
context?: string
): void {
this.sendWebhookEvent(event, payload).catch((error) => {
const contextInfo = context ? ` (${context})` : '';
this.logger.warn(`Background webhook ${event} failed${contextInfo}: ${error}`);
});
} }
protected async sendWebhookEvent(event: MeetWebhookEventType, payload: MeetWebhookPayload) { protected async sendWebhookEvent(event: MeetWebhookEventType, payload: MeetWebhookPayload) {