diff --git a/backend/src/config/dependency-injector.config.ts b/backend/src/config/dependency-injector.config.ts index 5a399c2..6cd692d 100644 --- a/backend/src/config/dependency-injector.config.ts +++ b/backend/src/config/dependency-injector.config.ts @@ -12,7 +12,7 @@ import { RecordingService, RedisService, RoomService, - S3Storage, + S3StorageProvider, S3Service, SystemEventService, TaskSchedulerService, @@ -50,7 +50,7 @@ export const registerDependencies = () => { container.bind(MeetStorageService).toSelf().inSingletonScope(); container.bind(ParticipantService).toSelf().inSingletonScope(); - container.bind(S3Storage).toSelf().inSingletonScope(); + container.bind(S3StorageProvider).toSelf().inSingletonScope(); container.bind(StorageFactory).toSelf().inSingletonScope(); }; diff --git a/backend/src/services/index.ts b/backend/src/services/index.ts index 52aa05b..71f48cf 100644 --- a/backend/src/services/index.ts +++ b/backend/src/services/index.ts @@ -13,6 +13,6 @@ export * from './mutex.service.js'; export * from './storage/index.js'; export * from './redis.service.js'; export * from './s3.service.js'; -export * from './storage/providers/s3-storage.js'; +export * from './storage/providers/s3-storage.provider.js'; export * from './token.service.js'; export * from './user.service.js'; diff --git a/backend/src/services/room.service.ts b/backend/src/services/room.service.ts index e2dca99..a99e539 100644 --- a/backend/src/services/room.service.ts +++ b/backend/src/services/room.service.ts @@ -3,8 +3,8 @@ import { inject, injectable } from '../config/dependency-injector.config.js'; import { CreateOptions, Room, SendDataOptions } from 'livekit-server-sdk'; import { LoggerService } from './logger.service.js'; import { LiveKitService } from './livekit.service.js'; -import { GlobalPreferencesService } from './preferences/global-preferences.service.js'; -import { MeetRoom, MeetRoomOptions, ParticipantRole } from '@typings-ce'; +import { MeetStorageService } from './storage/storage.service.js'; +import { MeetRoom, MeetRoomFilters, MeetRoomOptions, MeetRoomPreferences, ParticipantRole } from '@typings-ce'; import { MeetRoomHelper } from '../helpers/room.helper.js'; import { SystemEventService } from './system-event.service.js'; import { TaskSchedulerService } from './task-scheduler.service.js'; @@ -13,6 +13,7 @@ import { OpenViduComponentsAdapterHelper } from '../helpers/index.js'; import { uid } from 'uid/single'; import { MEET_NAME_ID } from '../environment.js'; import ms from 'ms'; +import { UtilsHelper } from '../helpers/utils.helper.js'; /** * Service for managing OpenVidu Meet rooms. @@ -24,7 +25,7 @@ import ms from 'ms'; export class RoomService { constructor( @inject(LoggerService) protected logger: LoggerService, - @inject(GlobalPreferencesService) protected globalPrefService: GlobalPreferencesService, + @inject(MeetStorageService) protected storageService: MeetStorageService, @inject(LiveKitService) protected livekitService: LiveKitService, @inject(SystemEventService) protected systemEventService: SystemEventService, @inject(TaskSchedulerService) protected taskSchedulerService: TaskSchedulerService @@ -66,7 +67,7 @@ export class RoomService { const { preferences, expirationDate, roomIdPrefix } = roomOptions; const roomId = roomIdPrefix ? `${roomIdPrefix}-${uid(15)}` : uid(15); - const openviduRoom: MeetRoom = { + const meetRoom: MeetRoom = { roomId, roomIdPrefix, creationDate: Date.now(), @@ -77,9 +78,9 @@ export class RoomService { publisherRoomUrl: `${baseUrl}/room/${roomId}?secret=${secureUid(10)}` }; - await this.globalPrefService.saveOpenViduRoom(openviduRoom); + await this.storageService.saveMeetRoom(meetRoom); - return openviduRoom; + return meetRoom; } /** @@ -113,13 +114,41 @@ export class RoomService { return room; } + /** + * Updates the preferences of a specific meeting room. + * + * @param roomId - The unique identifier of the meeting room to update + * @param preferences - The new preferences to apply to the meeting room + * @returns A Promise that resolves to the updated MeetRoom object + */ + async updateMeetRoomPreferences(roomId: string, preferences: MeetRoomPreferences): Promise { + const room = await this.getMeetRoom(roomId); + room.preferences = preferences; + + return await this.storageService.saveMeetRoom(room); + } + /** * Retrieves a list of rooms. * @returns A Promise that resolves to an array of {@link MeetRoom} objects. * @throws If there was an error retrieving the rooms. */ - async listOpenViduRooms(): Promise { - return await this.globalPrefService.getOpenViduRooms(); + async getAllMeetRooms({ maxItems, nextPageToken, fields }: MeetRoomFilters): Promise<{ + rooms: MeetRoom[]; + isTruncated: boolean; + nextPageToken?: string; + }> { + const response = await this.storageService.getMeetRooms(maxItems, nextPageToken); + + if (fields && fields.length > 0) { + const fieldsArray = Array.isArray(fields) ? fields : fields.split(',').map((f) => f.trim()); + const filteredRooms = response.rooms.map((room) => + UtilsHelper.filterObjectFields(room as unknown as Record, fieldsArray) + ); + response.rooms = filteredRooms as MeetRoom[]; + } + + return response; } /** @@ -128,8 +157,19 @@ export class RoomService { * @param roomId - The name of the room to retrieve. * @returns A promise that resolves to an {@link MeetRoom} object. */ - async getMeetRoom(roomId: string): Promise { - return await this.globalPrefService.getOpenViduRoom(roomId); + async getMeetRoom(roomId: string, fields?: string): Promise { + const meetRoom = await this.storageService.getMeetRoom(roomId); + + if (fields && fields.length > 0) { + const fieldsArray = Array.isArray(fields) ? fields : fields.split(',').map((f) => f.trim()); + const filteredRoom = UtilsHelper.filterObjectFields( + meetRoom as unknown as Record, + fieldsArray + ); + return filteredRoom as MeetRoom; + } + + return meetRoom; } /** @@ -140,7 +180,7 @@ export class RoomService { * @param roomIds - An array of room names to be deleted. * @returns A promise that resolves with an array of successfully deleted room names. */ - async deleteRooms(roomIds: string[]): Promise { + async bulkDeleteRooms(roomIds: string[]): Promise { const [openViduResults, livekitResults] = await Promise.all([ this.deleteOpenViduRooms(roomIds), Promise.allSettled(roomIds.map((roomId) => this.livekitService.deleteRoom(roomId))) @@ -171,10 +211,8 @@ export class RoomService { * @param roomIds - List of room names to delete. * @returns A promise that resolves with an array of successfully deleted room names. */ - async deleteOpenViduRooms(roomIds: string[]): Promise { - const results = await Promise.allSettled( - roomIds.map((roomId) => this.globalPrefService.deleteOpenViduRoom(roomId)) - ); + protected async deleteOpenViduRooms(roomIds: string[]): Promise { + const results = await Promise.allSettled(roomIds.map((roomId) => this.storageService.deleteMeetRoom(roomId))); const successfulRooms: string[] = []; @@ -307,21 +345,22 @@ export class RoomService { * @returns {Promise} A promise that resolves when the operation is complete. */ protected async deleteOpenViduExpiredRooms(): Promise { - const now = Date.now(); - this.logger.verbose(`Checking OpenVidu expired rooms at ${new Date(now).toISOString()}`); - const rooms = await this.listOpenViduRooms(); - const expiredRooms = rooms - .filter((room) => room.expirationDate && room.expirationDate < now) - .map((room) => room.roomId); + // const now = Date.now(); + // this.logger.verbose(`Checking OpenVidu expired rooms at ${new Date(now).toISOString()}`); + // const rooms = await this.getAllMeetRooms(); + // const expiredRooms = rooms + // .filter((room) => room.expirationDate && room.expirationDate < now) + // .map((room) => room.roomId); - if (expiredRooms.length === 0) { - this.logger.verbose('No OpenVidu expired rooms to delete.'); - return []; - } + // if (expiredRooms.length === 0) { + // this.logger.verbose('No OpenVidu expired rooms to delete.'); + // return []; + // } - this.logger.info(`Deleting ${expiredRooms.length} OpenVidu expired rooms: ${expiredRooms.join(', ')}`); + // this.logger.info(`Deleting ${expiredRooms.length} OpenVidu expired rooms: ${expiredRooms.join(', ')}`); - return await this.deleteOpenViduRooms(expiredRooms); + // return await this.deleteOpenViduRooms(expiredRooms); + return []; } /** @@ -333,52 +372,43 @@ export class RoomService { * @protected */ protected async restoreMissingLivekitRooms(): Promise { - this.logger.verbose(`Checking missing Livekit rooms ...`); - - const [lkResult, ovResult] = await Promise.allSettled([ - this.livekitService.listRooms(), - this.listOpenViduRooms() - ]); - - let lkRooms: Room[] = []; - let ovRooms: MeetRoom[] = []; - - if (lkResult.status === 'fulfilled') { - lkRooms = lkResult.value; - } else { - this.logger.error('Failed to list Livekit rooms:', lkResult.reason); - } - - if (ovResult.status === 'fulfilled') { - ovRooms = ovResult.value; - } else { - this.logger.error('Failed to list OpenVidu rooms:', ovResult.reason); - } - - const missingRooms: MeetRoom[] = ovRooms.filter( - (ovRoom) => !lkRooms.some((room) => room.name === ovRoom.roomId) - ); - - if (missingRooms.length === 0) { - this.logger.verbose('All OpenVidu rooms are present in Livekit. No missing rooms to restore. '); - return; - } - - this.logger.info(`Restoring ${missingRooms.length} missing rooms`); - - const creationResults = await Promise.allSettled( - missingRooms.map(({ roomId }: MeetRoom) => { - this.logger.debug(`Restoring room: ${roomId}`); - this.createLivekitRoom(roomId); - }) - ); - - creationResults.forEach((result, index) => { - if (result.status === 'rejected') { - this.logger.error(`Failed to restore room "${missingRooms[index].roomId}": ${result.reason}`); - } else { - this.logger.info(`Restored room "${missingRooms[index].roomId}"`); - } - }); + // this.logger.verbose(`Checking missing Livekit rooms ...`); + // const [lkResult, ovResult] = await Promise.allSettled([ + // this.livekitService.listRooms(), + // this.getAllMeetRooms() + // ]); + // let lkRooms: Room[] = []; + // let ovRooms: MeetRoom[] = []; + // if (lkResult.status === 'fulfilled') { + // lkRooms = lkResult.value; + // } else { + // this.logger.error('Failed to list Livekit rooms:', lkResult.reason); + // } + // if (ovResult.status === 'fulfilled') { + // ovRooms = ovResult.value; + // } else { + // this.logger.error('Failed to list OpenVidu rooms:', ovResult.reason); + // } + // const missingRooms: MeetRoom[] = ovRooms.filter( + // (ovRoom) => !lkRooms.some((room) => room.name === ovRoom.roomId) + // ); + // if (missingRooms.length === 0) { + // this.logger.verbose('All OpenVidu rooms are present in Livekit. No missing rooms to restore. '); + // return; + // } + // this.logger.info(`Restoring ${missingRooms.length} missing rooms`); + // const creationResults = await Promise.allSettled( + // missingRooms.map(({ roomId }: MeetRoom) => { + // this.logger.debug(`Restoring room: ${roomId}`); + // this.createLivekitRoom(roomId); + // }) + // ); + // creationResults.forEach((result, index) => { + // if (result.status === 'rejected') { + // this.logger.error(`Failed to restore room "${missingRooms[index].roomId}": ${result.reason}`); + // } else { + // this.logger.info(`Restored room "${missingRooms[index].roomId}"`); + // } + // }); } } diff --git a/backend/src/services/storage/index.ts b/backend/src/services/storage/index.ts index 5dc0800..f68160f 100644 --- a/backend/src/services/storage/index.ts +++ b/backend/src/services/storage/index.ts @@ -1,4 +1,4 @@ export * from './storage.service.js'; export * from './storage.interface.js'; export * from './storage.factory.js'; -export * from './providers/s3-storage.js'; +export * from './providers/s3-storage.provider.js'; diff --git a/backend/src/services/storage/providers/s3-storage.ts b/backend/src/services/storage/providers/s3-storage.provider.ts similarity index 71% rename from backend/src/services/storage/providers/s3-storage.ts rename to backend/src/services/storage/providers/s3-storage.provider.ts index fe1ad9d..5cbb130 100644 --- a/backend/src/services/storage/providers/s3-storage.ts +++ b/backend/src/services/storage/providers/s3-storage.provider.ts @@ -5,8 +5,9 @@ import { LoggerService } from '../../logger.service.js'; import { RedisService } from '../../redis.service.js'; import { OpenViduMeetError } from '../../../models/error.model.js'; import { inject, injectable } from '../../../config/dependency-injector.config.js'; -import { MEET_S3_ROOMS_PREFIX, MEET_S3_SUBBUCKET } from '../../../environment.js'; +import { MEET_S3_ROOMS_PREFIX } from '../../../environment.js'; import { RedisKeyName } from '../../../models/redis.model.js'; +import { PutObjectCommandOutput } from '@aws-sdk/client-s3'; /** * Implementation of the StorageProvider interface using AWS S3 for persistent storage @@ -26,10 +27,10 @@ import { RedisKeyName } from '../../../models/redis.model.js'; * @implements {StorageProvider} */ @injectable() -export class S3Storage +export class S3StorageProvider implements StorageProvider { - protected readonly S3_GLOBAL_PREFERENCES_KEY = `${MEET_S3_SUBBUCKET}/global-preferences.json`; + protected readonly S3_GLOBAL_PREFERENCES_KEY = `global-preferences.json`; constructor( @inject(LoggerService) protected logger: LoggerService, @inject(S3Service) protected s3Service: S3Service, @@ -131,49 +132,47 @@ export class S3Storage { const { roomId } = ovRoom; const s3Path = `${MEET_S3_ROOMS_PREFIX}/${roomId}/${roomId}.json`; - const roomStr = JSON.stringify(ovRoom); + const redisPayload = JSON.stringify(ovRoom); + const redisKey = RedisKeyName.ROOM + roomId; - const results = await Promise.allSettled([ + const [s3Result, redisResult] = await Promise.allSettled([ this.s3Service.saveObject(s3Path, ovRoom), - // TODO: Use a key prefix for Redis - this.redisService.set(roomId, roomStr, false) + this.redisService.set(redisKey, redisPayload, false) ]); - const s3Result = results[0]; - const redisResult = results[1]; - if (s3Result.status === 'fulfilled' && redisResult.status === 'fulfilled') { return ovRoom; } - // Rollback changes if one of the operations failed - if (s3Result.status === 'fulfilled') { - try { - await this.s3Service.deleteObject(s3Path); - } catch (rollbackError) { - this.logger.error(`Error rolling back S3 save for room ${roomId}: ${rollbackError}`); - } - } - - if (redisResult.status === 'fulfilled') { - try { - await this.redisService.delete(roomId); - } catch (rollbackError) { - this.logger.error(`Error rolling back Redis set for room ${roomId}: ${rollbackError}`); - } - } + // Rollback any changes made by the successful operation + await this.rollbackRoomSave(roomId, s3Result, redisResult, s3Path, redisKey); // Return the error that occurred first - const rejectedResult: PromiseRejectedResult = + const failedOperation: PromiseRejectedResult = s3Result.status === 'rejected' ? s3Result : (redisResult as PromiseRejectedResult); - const error = rejectedResult.reason; + const error = failedOperation.reason; this.handleError(error, `Error saving Room preferences for room ${roomId}`); throw error; } + /** + * Retrieves the list of Meet rooms from S3. + * + * @param maxItems - Maximum number of items to retrieve. + * @param nextPageToken - Continuation token for pagination. + * @returns An object containing the list of rooms, a flag indicating whether the list is truncated, and, if available, the next page token. + */ async getMeetRooms( maxItems: number, nextPageToken?: string @@ -189,71 +188,48 @@ export class S3Storage[] = []; - // // Retrieve the data for each room - // roomFiles.forEach((item) => { - // if (item?.Key && item.Key.endsWith('.json')) { - // promises.push(getOpenViduRoom(item.Key) as Promise); - // } - // }); + // Extract room IDs directly and filter out invalid values + const roomIds = roomFiles + .map((file) => this.extractRoomId(file.Key)) + .filter((id): id is string => Boolean(id)); - // Extract room names from file paths - const roomIds = roomFiles.map((file) => this.extractRoomId(file.Key)).filter(Boolean) as string[]; + // Fetch and log any room lookup errors individually // Fetch room preferences in parallel const rooms = await Promise.all( - roomIds.map(async (roomId: string) => { - if (!roomId) return null; - + roomIds.map(async (roomId) => { try { return await this.getMeetRoom(roomId); - } catch (error: any) { - this.logger.warn(`Failed to fetch room "${roomId}": ${error.message}`); + } catch (error: unknown) { + this.logger.warn(`Failed to fetch room "${roomId}": ${error}`); return null; } }) ); // Filter out null values - const roomsResponse = rooms.filter(Boolean) as R[]; - return { rooms: roomsResponse, isTruncated: !!IsTruncated, nextPageToken: NextContinuationToken }; + const validRooms = rooms.filter((room) => room !== null) as R[]; + return { rooms: validRooms, isTruncated: !!IsTruncated, nextPageToken: NextContinuationToken }; } catch (error) { this.handleError(error, 'Error fetching Room preferences'); return { rooms: [], isTruncated: false }; } } - /** - * Extracts the room id from the given file path. - * Assumes the room name is located one directory before the file name. - * Example: 'path/to/roomId/file.json' -> 'roomId' - * @param filePath - The S3 object key representing the file path. - * @returns The extracted room name or null if extraction fails. - */ - private extractRoomId(filePath?: string): string | null { - if (!filePath) return null; - - const parts = filePath.split('/'); - - if (parts.length < 2) { - this.logger.warn(`Invalid room file path: ${filePath}`); - return null; - } - - return parts[parts.length - 2]; - } - async getMeetRoom(roomId: string): Promise { try { + // Try to get room preferences from Redis cache const room: R | null = await this.getFromRedis(roomId); if (!room) { - this.logger.debug(`Room ${roomId} not found in Redis. Fetching from S3...`); - return await this.getFromS3(`${MEET_S3_ROOMS_PREFIX}/${roomId}/${roomId}.json`); + const s3RoomPath = `${MEET_S3_ROOMS_PREFIX}/${roomId}/${roomId}.json`; + this.logger.debug(`Room ${roomId} not found in Redis. Fetching from S3 at ${s3RoomPath}...`); + + return await this.getFromS3(s3RoomPath); } this.logger.debug(`Room ${roomId} verified in Redis`); @@ -265,11 +241,12 @@ export class S3Storage { + const s3RoomPath = `${MEET_S3_ROOMS_PREFIX}/${roomId}/${roomId}.json`; + const redisKey = RedisKeyName.ROOM + roomId; + try { - await Promise.all([ - this.s3Service.deleteObject(`${MEET_S3_ROOMS_PREFIX}/${roomId}/${roomId}.json`), - this.redisService.delete(roomId) - ]); + await Promise.all([this.s3Service.deleteObject(s3RoomPath), this.redisService.delete(redisKey)]); + this.logger.verbose(`Room ${roomId} deleted successfully from S3 and Redis`); } catch (error) { this.handleError(error, `Error deleting Room preferences for room ${roomId}`); } @@ -320,6 +297,61 @@ export class S3Storage 'roomId' + * + * @param filePath - The S3 object key representing the file path. + * @returns The extracted room ID or null if extraction fails. + */ + protected extractRoomId(filePath?: string): string | null { + if (!filePath) return null; + + const parts = filePath.split('/'); + const roomId = parts.slice(-2, -1)[0]; + + if (!roomId) { + this.logger.warn(`Invalid room file path: ${filePath}`); + return null; + } + + return roomId; + } + + /** + * Performs rollback of saved room data. + * + * @param roomId - The room identifier. + * @param s3Result - The result of the S3 save operation. + * @param redisResult - The result of the Redis set operation. + * @param s3Path - The S3 key used to save the room data. + * @param redisKey - The Redis key used to cache the room data. + */ + protected async rollbackRoomSave( + roomId: string, + s3Result: PromiseSettledResult, + redisResult: PromiseSettledResult, + s3Path: string, + redisKey: string + ): Promise { + if (s3Result.status === 'fulfilled') { + try { + await this.s3Service.deleteObject(s3Path); + } catch (rollbackError) { + this.logger.error(`Error rolling back S3 save for room ${roomId}: ${rollbackError}`); + } + } + + if (redisResult.status === 'fulfilled') { + try { + await this.redisService.delete(redisKey); + } catch (rollbackError) { + this.logger.error(`Error rolling back Redis set for room ${roomId}: ${rollbackError}`); + } + } + } + protected handleError(error: any, message: string) { if (error instanceof OpenViduMeetError) { this.logger.error(`${message}: ${error.message}`); diff --git a/backend/src/services/storage/storage.factory.ts b/backend/src/services/storage/storage.factory.ts index cc54478..aa6dce8 100644 --- a/backend/src/services/storage/storage.factory.ts +++ b/backend/src/services/storage/storage.factory.ts @@ -1,5 +1,5 @@ import { StorageProvider } from './storage.interface.js'; -import { S3Storage } from './providers/s3-storage.js'; +import { S3StorageProvider } from './providers/s3-storage.provider.js'; import { MEET_PREFERENCES_STORAGE_MODE } from '../../environment.js'; import { inject, injectable } from '../../config/dependency-injector.config.js'; import { LoggerService } from '../logger.service.js'; @@ -13,7 +13,7 @@ import { LoggerService } from '../logger.service.js'; @injectable() export class StorageFactory { constructor( - @inject(S3Storage) protected s3Storage: S3Storage, + @inject(S3StorageProvider) protected s3StorageProvider: S3StorageProvider, @inject(LoggerService) protected logger: LoggerService ) {} @@ -22,11 +22,11 @@ export class StorageFactory { switch (storageMode) { case 's3': - return this.s3Storage; + return this.s3StorageProvider; default: this.logger.info('No preferences storage mode specified. Defaulting to S3.'); - return this.s3Storage; + return this.s3StorageProvider; } } } diff --git a/backend/src/services/storage/storage.interface.ts b/backend/src/services/storage/storage.interface.ts index f4ffde4..07fb5d7 100644 --- a/backend/src/services/storage/storage.interface.ts +++ b/backend/src/services/storage/storage.interface.ts @@ -35,6 +35,17 @@ export interface StorageProvider; + /** + * + * Retrieves the OpenVidu Meet Rooms. + * + * @param maxItems - The maximum number of items to retrieve. If not provided, all items will be retrieved. + * @param nextPageToken - The token for the next page of results. If not provided, the first page will be retrieved. + * @returns A promise that resolves to an object containing รง + * - the retrieved rooms, + * - a boolean indicating if there are more items to retrieve + * - an optional next page token. + */ getMeetRooms( maxItems?: number, nextPageToken?: string diff --git a/backend/src/services/storage/storage.service.ts b/backend/src/services/storage/storage.service.ts index 1ca2157..e040b39 100644 --- a/backend/src/services/storage/storage.service.ts +++ b/backend/src/services/storage/storage.service.ts @@ -65,12 +65,12 @@ export class MeetStorageService; } - async saveOpenViduRoom(ovRoom: R): Promise { - this.logger.info(`Saving OpenVidu room ${ovRoom.roomId}`); - return this.storageProvider.saveMeetRoom(ovRoom) as Promise; + async saveMeetRoom(meetRoom: R): Promise { + this.logger.info(`Saving OpenVidu room ${meetRoom.roomId}`); + return this.storageProvider.saveMeetRoom(meetRoom) as Promise; } - async getOpenViduRooms( + async getMeetRooms( maxItems?: number, nextPageToken?: string ): Promise<{ @@ -92,23 +92,24 @@ export class MeetStorageService { - const openviduRoom = await this.storageProvider.getMeetRoom(roomId); + async getMeetRoom(roomId: string): Promise { + const meetRoom = await this.storageProvider.getMeetRoom(roomId); - if (!openviduRoom) { + if (!meetRoom) { this.logger.error(`Room not found for room ${roomId}`); throw errorRoomNotFound(roomId); } - return openviduRoom as R; + return meetRoom as R; } - async deleteOpenViduRoom(roomId: string): Promise { + async deleteMeetRoom(roomId: string): Promise { return this.storageProvider.deleteMeetRoom(roomId); } + //TODO: REMOVE THIS METHOD async getOpenViduRoomPreferences(roomId: string): Promise { - const openviduRoom = await this.getOpenViduRoom(roomId); + const openviduRoom = await this.getMeetRoom(roomId); if (!openviduRoom.preferences) { throw new Error('Room preferences not found'); @@ -126,9 +127,9 @@ export class MeetStorageService { this.validateRoomPreferences(roomPreferences); - const openviduRoom = await this.getOpenViduRoom(roomId); + const openviduRoom = await this.getMeetRoom(roomId); openviduRoom.preferences = roomPreferences; - return this.saveOpenViduRoom(openviduRoom); + return this.saveMeetRoom(openviduRoom); } /**