diff --git a/backend/src/services/livekit-webhook.service.ts b/backend/src/services/livekit-webhook.service.ts index adbb53f..c039505 100644 --- a/backend/src/services/livekit-webhook.service.ts +++ b/backend/src/services/livekit-webhook.service.ts @@ -199,7 +199,10 @@ export class LivekitWebhookService { // Send webhook notification switch (webhookAction) { case 'started': - tasks.push(this.openViduWebhookService.sendRecordingStartedWebhook(recordingInfo)); + tasks.push( + this.saveRoomMetadataFileIfNeeded(roomId), + this.openViduWebhookService.sendRecordingStartedWebhook(recordingInfo) + ); break; case 'updated': tasks.push(this.openViduWebhookService.sendRecordingUpdatedWebhook(recordingInfo)); @@ -217,7 +220,6 @@ export class LivekitWebhookService { break; case 'ended': tasks.push( - this.saveRoomSecretsFileIfNeeded(roomId), this.openViduWebhookService.sendRecordingEndedWebhook(recordingInfo), this.recordingService.releaseRoomRecordingActiveLock(roomId) ); @@ -235,20 +237,22 @@ export class LivekitWebhookService { } /** - * Saves room secrets to an S3 bucket if they haven't been saved already. + * Saves room metadata to a JSON file in the S3 bucket if it doesn't already exist. * - * This method checks if secrets for the specified room exist in the S3 storage. - * If they don't exist, it retrieves the room information, extracts the publisher - * and moderator secrets, and saves them to an S3 bucket under the path - * `${INTERNAL_CONFIG.S3_RECORDINGS_PREFIX}/.metadata/${roomId}/secrets.json`. + * This method checks if the metadata file for the given room already exists in the + * S3 bucket. If not, it retrieves the room information, extracts the necessary + * secrets and preferences, and saves them to a metadata JSON file in the + * .metadata/{roomId}/ directory of the S3 bucket. + * + * @param roomId - The unique identifier of the room */ - protected async saveRoomSecretsFileIfNeeded(roomId: string): Promise { + protected async saveRoomMetadataFileIfNeeded(roomId: string): Promise { try { - const filePath = `${INTERNAL_CONFIG.S3_RECORDINGS_PREFIX}/.metadata/${roomId}/secrets.json`; + const filePath = `${INTERNAL_CONFIG.S3_RECORDINGS_PREFIX}/.metadata/${roomId}/room_metadata.json`; const fileExists = await this.s3Service.exists(filePath); if (fileExists) { - this.logger.debug(`Room secrets already saved for room ${roomId}`); + this.logger.debug(`Room metadata already saved for room ${roomId} in recordings bucket`); return; } @@ -256,15 +260,18 @@ export class LivekitWebhookService { if (room) { const { publisherSecret, moderatorSecret } = MeetRoomHelper.extractSecretsFromRoom(room); - const secrets = { + const roomMetadata = { publisherSecret, - moderatorSecret + moderatorSecret, + preferences: { + recordingPreferences: room.preferences?.recordingPreferences + } }; - await this.s3Service.saveObject(filePath, secrets); - this.logger.debug(`Room secrets saved for room ${roomId}`); + await this.s3Service.saveObject(filePath, roomMetadata); + this.logger.debug(`Room metadata saved for room ${roomId} in recordings bucket`); } } catch (error) { - this.logger.error(`Error saving room secrets for room ${roomId}: ${error}`); + this.logger.error(`Error saving room metadata for room ${roomId} in recordings bucket: ${error}`); } } } diff --git a/backend/src/services/recording.service.ts b/backend/src/services/recording.service.ts index 5e4a41e..ddc0255 100644 --- a/backend/src/services/recording.service.ts +++ b/backend/src/services/recording.service.ts @@ -401,15 +401,15 @@ export class RecordingService { const recordingPath = `${INTERNAL_CONFIG.S3_RECORDINGS_PREFIX}/${RecordingHelper.extractFilename(recordingInfo)}`; newFilesToDelete.add(recordingPath); - // Get secrets.json file path if it is the only file remaining in the room's metadata directory - const secretsFilePath = await this.getSecretsFilePathIfOnlyRemaining( + // Get room_metadata.json file path under recordings bucket if it is the only file remaining in the room's metadata directory + const roomMetadataFilePath = await this.getRoomMetadataFilePathIfOnlyRemaining( recordingInfo.roomId, metadataFilePath, Array.from(new Set([...filesAlreadyAddedForDeletion, ...newFilesToDelete])) ); - if (secretsFilePath) { - newFilesToDelete.add(secretsFilePath); + if (roomMetadataFilePath) { + newFilesToDelete.add(roomMetadataFilePath); } return { filesToDelete: newFilesToDelete, recordingInfo }; @@ -537,15 +537,21 @@ export class RecordingService { } /** - * Determines if the secrets.json file should be deleted by checking if it would be - * the only file remaining in the room's metadata directory after deletion. + * Determines if the room_metadata.json file would be the only file remaining in a room's metadata + * directory after specified files are deleted. * - * @param roomId - Room identifier - * @param metadataFilePath - Path of the metadata file being deleted (for single deletion) - * @param filesToDeleteArray - Array of all files being deleted (for bulk deletion) - * @returns Path of the secrets.json file if it should be deleted, or null otherwise + * This method examines the contents of a room's metadata directory in S3 storage and checks whether, + * after the deletion of specified files, only the room_metadata.json file would remain. The method + * handles both single file deletion and bulk deletion scenarios. + * + * @param roomId - The identifier of the room whose metadata directory is being checked + * @param metadataFilePath - The full path of the metadata file being considered for deletion + * @param filesToDeleteArray - Optional array of file paths that are planned for deletion + * + * @returns The path to the room_metadata.json file if it would be the only remaining file after deletion, + * or null if multiple files would remain or if an error occurs during the process */ - protected async getSecretsFilePathIfOnlyRemaining( + protected async getRoomMetadataFilePathIfOnlyRemaining( roomId: string, metadataFilePath: string, filesToDeleteArray: string[] = [] @@ -568,7 +574,7 @@ export class RecordingService { ).map((item) => item.Key!); // If only secrets.json remains, return its path - if (remainingFiles.length === 1 && remainingFiles[0].endsWith('secrets.json')) { + if (remainingFiles.length === 1 && remainingFiles[0].endsWith('room_metadata.json')) { return remainingFiles[0]; } } else { @@ -584,8 +590,8 @@ export class RecordingService { const otherFiles = Contents.filter((item) => !item.Key?.endsWith(metadataBaseName || '')); // If the only other file is secrets.json, return its path - if (otherFiles.length === 1 && otherFiles[0].Key?.endsWith('secrets.json')) { - return `${INTERNAL_CONFIG.S3_RECORDINGS_PREFIX}/.metadata/${roomId}/secrets.json`; + if (otherFiles.length === 1 && otherFiles[0].Key?.endsWith('room_metadata.json')) { + return `${INTERNAL_CONFIG.S3_RECORDINGS_PREFIX}/.metadata/${roomId}/room_metadata.json`; } }