backend: update type parameters for storage interfaces and methods to improve clarity and consistency

This commit is contained in:
Carlos Santos 2025-05-28 11:46:13 +02:00
parent d843ee70b5
commit 172e8edcfd
3 changed files with 90 additions and 45 deletions

View File

@ -1,5 +1,5 @@
import { PutObjectCommandOutput } from '@aws-sdk/client-s3'; import { PutObjectCommandOutput } from '@aws-sdk/client-s3';
import { GlobalPreferences, MeetRoom } from '@typings-ce'; import { GlobalPreferences, MeetRecordingInfo, MeetRoom } from '@typings-ce';
import { inject, injectable } from 'inversify'; import { inject, injectable } from 'inversify';
import INTERNAL_CONFIG from '../../../config/internal-config.js'; import INTERNAL_CONFIG from '../../../config/internal-config.js';
import { OpenViduMeetError, RedisKeyName } from '../../../models/index.js'; import { OpenViduMeetError, RedisKeyName } from '../../../models/index.js';
@ -132,23 +132,23 @@ export class S3StorageProvider<G extends GlobalPreferences = GlobalPreferences,
* Persists a room object to S3 and Redis concurrently. * Persists a room object to S3 and Redis concurrently.
* If at least one operation fails, performs a rollback by deleting the successfully saved object. * If at least one operation fails, performs a rollback by deleting the successfully saved object.
* *
* @param ovRoom - The room object to save. * @param meetRoom - The room object to save.
* @returns The saved room if both operations succeed. * @returns The saved room if both operations succeed.
* @throws The error from the first failed operation. * @throws The error from the first failed operation.
*/ */
async saveMeetRoom(ovRoom: R): Promise<R> { async saveMeetRoom(meetRoom: R): Promise<R> {
const { roomId } = ovRoom; const { roomId } = meetRoom;
const s3Path = `${INTERNAL_CONFIG.S3_ROOMS_PREFIX}/${roomId}/${roomId}.json`; const s3Path = `${INTERNAL_CONFIG.S3_ROOMS_PREFIX}/${roomId}/${roomId}.json`;
const redisPayload = JSON.stringify(ovRoom); const redisPayload = JSON.stringify(meetRoom);
const redisKey = RedisKeyName.ROOM + roomId; const redisKey = RedisKeyName.ROOM + roomId;
const [s3Result, redisResult] = await Promise.allSettled([ const [s3Result, redisResult] = await Promise.allSettled([
this.s3Service.saveObject(s3Path, ovRoom), this.s3Service.saveObject(s3Path, meetRoom),
this.redisService.set(redisKey, redisPayload, false) this.redisService.set(redisKey, redisPayload, false)
]); ]);
if (s3Result.status === 'fulfilled' && redisResult.status === 'fulfilled') { if (s3Result.status === 'fulfilled' && redisResult.status === 'fulfilled') {
return ovRoom; return meetRoom;
} }
// Rollback any changes made by the successful operation // Rollback any changes made by the successful operation
@ -309,10 +309,9 @@ export class S3StorageProvider<G extends GlobalPreferences = GlobalPreferences,
} }
} }
/** /**
* Updates the archived room metadata for a given room in the S3 recordings bucket if it exists. * Updates the archived room metadata for a given room in the S3 recordings bucket if it exists.
* *
* @param roomId - The unique identifier of the room whose metadata needs to be updated. * @param roomId - The unique identifier of the room whose metadata needs to be updated.
*/ */
async updateArchivedRoomMetadata(roomId: string): Promise<void> { async updateArchivedRoomMetadata(roomId: string): Promise<void> {
@ -446,7 +445,7 @@ export class S3StorageProvider<G extends GlobalPreferences = GlobalPreferences,
} }
} }
protected handleError(error: any, message: string) { protected handleError(error: unknown, message: string) {
if (error instanceof OpenViduMeetError) { if (error instanceof OpenViduMeetError) {
this.logger.error(`${message}: ${error.message}`); this.logger.error(`${message}: ${error.message}`);
} else { } else {

View File

@ -4,28 +4,28 @@ import { GlobalPreferences, MeetRoom } from '@typings-ce';
* An interface that defines the contract for storage providers in the OpenVidu Meet application. * An interface that defines the contract for storage providers in the OpenVidu Meet application.
* Storage providers handle persistence of global application preferences and meeting room data. * Storage providers handle persistence of global application preferences and meeting room data.
* *
* @template T - The type of global preferences, extending GlobalPreferences * @template GPrefs - The type of global preferences, extending GlobalPreferences
* @template R - The type of room data, extending MeetRoom * @template MRoom - The type of room data, extending MeetRoom
* *
* Implementations of this interface should handle the persistent storage * Implementations of this interface should handle the persistent storage
* of application settings and room information, which could be backed by * of application settings and room information, which could be backed by
* various storage solutions (database, file system, cloud storage, etc.). * various storage solutions (database, file system, cloud storage, etc.).
*/ */
export interface StorageProvider<T extends GlobalPreferences = GlobalPreferences, R extends MeetRoom = MeetRoom> { export interface StorageProvider<GPrefs extends GlobalPreferences = GlobalPreferences, MRoom extends MeetRoom = MeetRoom> {
/** /**
* Initializes the storage with default preferences if they are not already set. * Initializes the storage with default preferences if they are not already set.
* *
* @param defaultPreferences - The default preferences to initialize with. * @param defaultPreferences - The default preferences to initialize with.
* @returns A promise that resolves when the initialization is complete. * @returns A promise that resolves when the initialization is complete.
*/ */
initialize(defaultPreferences: T): Promise<void>; initialize(defaultPreferences: GPrefs): Promise<void>;
/** /**
* Retrieves the global preferences of Openvidu Meet. * Retrieves the global preferences of Openvidu Meet.
* *
* @returns A promise that resolves to the global preferences, or null if not set. * @returns A promise that resolves to the global preferences, or null if not set.
*/ */
getGlobalPreferences(): Promise<T | null>; getGlobalPreferences(): Promise<GPrefs | null>;
/** /**
* Saves the given preferences. * Saves the given preferences.
@ -33,7 +33,7 @@ export interface StorageProvider<T extends GlobalPreferences = GlobalPreferences
* @param preferences - The preferences to save. * @param preferences - The preferences to save.
* @returns A promise that resolves to the saved preferences. * @returns A promise that resolves to the saved preferences.
*/ */
saveGlobalPreferences(preferences: T): Promise<T>; saveGlobalPreferences(preferences: GPrefs): Promise<GPrefs>;
/** /**
* *
@ -50,7 +50,7 @@ export interface StorageProvider<T extends GlobalPreferences = GlobalPreferences
maxItems?: number, maxItems?: number,
nextPageToken?: string nextPageToken?: string
): Promise<{ ): Promise<{
rooms: R[]; rooms: MRoom[];
isTruncated: boolean; isTruncated: boolean;
nextPageToken?: string; nextPageToken?: string;
}>; }>;
@ -61,15 +61,15 @@ export interface StorageProvider<T extends GlobalPreferences = GlobalPreferences
* @param roomId - The name of the room to retrieve. * @param roomId - The name of the room to retrieve.
* @returns A promise that resolves to the OpenVidu Room, or null if not found. * @returns A promise that resolves to the OpenVidu Room, or null if not found.
**/ **/
getMeetRoom(roomId: string): Promise<R | null>; getMeetRoom(roomId: string): Promise<MRoom | null>;
/** /**
* Saves the OpenVidu Meet Room. * Saves the OpenVidu Meet Room.
* *
* @param ovRoom - The OpenVidu Room to save. * @param meetRoom - The OpenVidu Room to save.
* @returns A promise that resolves to the saved * @returns A promise that resolves to the saved
**/ **/
saveMeetRoom(ovRoom: R): Promise<R>; saveMeetRoom(meetRoom: MRoom): Promise<MRoom>;
/** /**
* Deletes OpenVidu Meet Rooms. * Deletes OpenVidu Meet Rooms.
@ -86,7 +86,7 @@ export interface StorageProvider<T extends GlobalPreferences = GlobalPreferences
* *
* @param roomId - The name of the room to retrieve. * @param roomId - The name of the room to retrieve.
*/ */
getArchivedRoomMetadata(roomId: string): Promise<Partial<R> | null>; getArchivedRoomMetadata(roomId: string): Promise<Partial<MRoom> | null>;
/** /**
* Archives the metadata for a specific room. * Archives the metadata for a specific room.

View File

@ -12,11 +12,14 @@ import { LoggerService, MutexService, StorageFactory, StorageProvider } from '..
* This service provides an abstraction layer over the underlying storage implementation, * This service provides an abstraction layer over the underlying storage implementation,
* handling initialization, retrieval, and persistence of global preferences and room data. * handling initialization, retrieval, and persistence of global preferences and room data.
* *
* @typeParam G - Type for global preferences, extends GlobalPreferences * @template GPrefs - Type for global preferences, extends GlobalPreferences
* @typeParam R - Type for room data, extends MeetRoom * @template MRoom - Type for room data, extends MeetRoom
*/ */
@injectable() @injectable()
export class MeetStorageService<G extends GlobalPreferences = GlobalPreferences, R extends MeetRoom = MeetRoom> { export class MeetStorageService<
GPrefs extends GlobalPreferences = GlobalPreferences,
MRoom extends MeetRoom = MeetRoom
> {
protected storageProvider: StorageProvider; protected storageProvider: StorageProvider;
constructor( constructor(
@inject(LoggerService) protected logger: LoggerService, @inject(LoggerService) protected logger: LoggerService,
@ -28,7 +31,7 @@ export class MeetStorageService<G extends GlobalPreferences = GlobalPreferences,
/** /**
* Initializes default preferences if not already initialized. * Initializes default preferences if not already initialized.
* @returns {Promise<G>} Default global preferences. * @returns {Promise<GPrefs>} Default global preferences.
*/ */
async initializeGlobalPreferences(): Promise<void> { async initializeGlobalPreferences(): Promise<void> {
try { try {
@ -53,12 +56,12 @@ export class MeetStorageService<G extends GlobalPreferences = GlobalPreferences,
/** /**
* Retrieves the global preferences, initializing them if necessary. * Retrieves the global preferences, initializing them if necessary.
* @returns {Promise<GlobalPreferences>} * @returns {Promise<GPrefs>}
*/ */
async getGlobalPreferences(): Promise<G> { async getGlobalPreferences(): Promise<GPrefs> {
let preferences = await this.storageProvider.getGlobalPreferences(); let preferences = await this.storageProvider.getGlobalPreferences();
if (preferences) return preferences as G; if (preferences) return preferences as GPrefs;
await this.initializeGlobalPreferences(); await this.initializeGlobalPreferences();
preferences = await this.storageProvider.getGlobalPreferences(); preferences = await this.storageProvider.getGlobalPreferences();
@ -68,34 +71,50 @@ export class MeetStorageService<G extends GlobalPreferences = GlobalPreferences,
throw internalError('getting global preferences'); throw internalError('getting global preferences');
} }
return preferences as G; return preferences as GPrefs;
} }
/** /**
* Saves the global preferences. * Saves the global preferences to the storage provider.
* @param {GlobalPreferences} preferences * @param {GPrefs} preferences
* @returns {Promise<GlobalPreferences>} * @returns {Promise<GPrefs>}
*/ */
async saveGlobalPreferences(preferences: G): Promise<G> { async saveGlobalPreferences(preferences: GPrefs): Promise<GPrefs> {
this.logger.info('Saving global preferences'); this.logger.info('Saving global preferences');
return this.storageProvider.saveGlobalPreferences(preferences) as Promise<G>; return this.storageProvider.saveGlobalPreferences(preferences) as Promise<GPrefs>;
} }
async saveMeetRoom(meetRoom: R): Promise<R> { /**
* Saves the meet room to the storage provider.
*
* @param meetRoom - The meeting room object to be saved
* @returns A promise that resolves to the saved meeting room object
*/
async saveMeetRoom(meetRoom: MRoom): Promise<MRoom> {
this.logger.info(`Saving OpenVidu room ${meetRoom.roomId}`); this.logger.info(`Saving OpenVidu room ${meetRoom.roomId}`);
return this.storageProvider.saveMeetRoom(meetRoom) as Promise<R>; return this.storageProvider.saveMeetRoom(meetRoom) as Promise<MRoom>;
} }
/**
* Retrieves a paginated list of meeting rooms from the storage provider.
*
* @param maxItems - Optional maximum number of rooms to retrieve in a single request
* @param nextPageToken - Optional token for pagination to get the next page of results
* @returns A promise that resolves to an object containing:
* - rooms: Array of MRoom objects representing the meeting rooms
* - isTruncated: Boolean indicating if there are more results available
* - nextPageToken: Optional token for retrieving the next page of results
*/
async getMeetRooms( async getMeetRooms(
maxItems?: number, maxItems?: number,
nextPageToken?: string nextPageToken?: string
): Promise<{ ): Promise<{
rooms: R[]; rooms: MRoom[];
isTruncated: boolean; isTruncated: boolean;
nextPageToken?: string; nextPageToken?: string;
}> { }> {
return this.storageProvider.getMeetRooms(maxItems, nextPageToken) as Promise<{ return this.storageProvider.getMeetRooms(maxItems, nextPageToken) as Promise<{
rooms: R[]; rooms: MRoom[];
isTruncated: boolean; isTruncated: boolean;
nextPageToken?: string; nextPageToken?: string;
}>; }>;
@ -108,7 +127,7 @@ export class MeetStorageService<G extends GlobalPreferences = GlobalPreferences,
* @returns A promise that resolves to the room's preferences. * @returns A promise that resolves to the room's preferences.
* @throws Error if the room preferences are not found. * @throws Error if the room preferences are not found.
*/ */
async getMeetRoom(roomId: string): Promise<R> { async getMeetRoom(roomId: string): Promise<MRoom> {
const meetRoom = await this.storageProvider.getMeetRoom(roomId); const meetRoom = await this.storageProvider.getMeetRoom(roomId);
if (!meetRoom) { if (!meetRoom) {
@ -116,30 +135,57 @@ export class MeetStorageService<G extends GlobalPreferences = GlobalPreferences,
throw errorRoomNotFound(roomId); throw errorRoomNotFound(roomId);
} }
return meetRoom as R; return meetRoom as MRoom;
} }
/**
* Deletes multiple meeting rooms from storage.
*
* @param roomIds - Array of room identifiers to be deleted
* @returns A promise that resolves when all rooms have been successfully deleted
* @throws May throw an error if the deletion operation fails for any of the rooms
*/
async deleteMeetRooms(roomIds: string[]): Promise<void> { async deleteMeetRooms(roomIds: string[]): Promise<void> {
return this.storageProvider.deleteMeetRooms(roomIds); return this.storageProvider.deleteMeetRooms(roomIds);
} }
async getArchivedRoomMetadata(roomId: string): Promise<Partial<R> | null> { /**
return this.storageProvider.getArchivedRoomMetadata(roomId) as Promise<Partial<R> | null>; * Retrieves metadata for an archived room by its ID.
*
* @param roomId - The unique identifier of the room to retrieve metadata for
* @returns A promise that resolves to partial room metadata if found, or null if not found
*/
async getArchivedRoomMetadata(roomId: string): Promise<Partial<MRoom> | null> {
return this.storageProvider.getArchivedRoomMetadata(roomId) as Promise<Partial<MRoom> | null>;
} }
/**
* Archives the metadata for a specific room.
*
* @param roomId - The unique identifier of the room whose metadata should be archived
* @returns A Promise that resolves when the archival operation is complete
* @throws May throw an error if the archival operation fails or if the room ID is invalid
*/
async archiveRoomMetadata(roomId: string): Promise<void> { async archiveRoomMetadata(roomId: string): Promise<void> {
return this.storageProvider.archiveRoomMetadata(roomId); return this.storageProvider.archiveRoomMetadata(roomId);
} }
/**
* Updates the metadata of an archived room.
*
* @param roomId - The unique identifier of the room whose archived metadata should be updated
* @returns A promise that resolves when the archived room metadata has been successfully updated
* @throws May throw an error if the room ID is invalid or if the storage operation fails
*/
async updateArchivedRoomMetadata(roomId: string): Promise<void> { async updateArchivedRoomMetadata(roomId: string): Promise<void> {
return this.storageProvider.updateArchivedRoomMetadata(roomId); return this.storageProvider.updateArchivedRoomMetadata(roomId);
} }
/** /**
* Returns the default global preferences. * Returns the default global preferences.
* @returns {G} * @returns {GPrefs}
*/ */
protected async getDefaultPreferences(): Promise<G> { protected async getDefaultPreferences(): Promise<GPrefs> {
return { return {
projectId: MEET_NAME_ID, projectId: MEET_NAME_ID,
webhooksPreferences: { webhooksPreferences: {
@ -162,7 +208,7 @@ export class MeetStorageService<G extends GlobalPreferences = GlobalPreferences,
} }
} }
} }
} as G; } as GPrefs;
} }
/** /**