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 { GlobalPreferences, MeetRoom } from '@typings-ce';
import { GlobalPreferences, MeetRecordingInfo, MeetRoom } from '@typings-ce';
import { inject, injectable } from 'inversify';
import INTERNAL_CONFIG from '../../../config/internal-config.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.
* 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.
* @throws The error from the first failed operation.
*/
async saveMeetRoom(ovRoom: R): Promise<R> {
const { roomId } = ovRoom;
async saveMeetRoom(meetRoom: R): Promise<R> {
const { roomId } = meetRoom;
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 [s3Result, redisResult] = await Promise.allSettled([
this.s3Service.saveObject(s3Path, ovRoom),
this.s3Service.saveObject(s3Path, meetRoom),
this.redisService.set(redisKey, redisPayload, false)
]);
if (s3Result.status === 'fulfilled' && redisResult.status === 'fulfilled') {
return ovRoom;
return meetRoom;
}
// 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.
*
*
* @param roomId - The unique identifier of the room whose metadata needs to be updated.
*/
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) {
this.logger.error(`${message}: ${error.message}`);
} 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.
* Storage providers handle persistence of global application preferences and meeting room data.
*
* @template T - The type of global preferences, extending GlobalPreferences
* @template R - The type of room data, extending MeetRoom
* @template GPrefs - The type of global preferences, extending GlobalPreferences
* @template MRoom - The type of room data, extending MeetRoom
*
* Implementations of this interface should handle the persistent storage
* of application settings and room information, which could be backed by
* 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.
*
* @param defaultPreferences - The default preferences to initialize with.
* @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.
*
* @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.
@ -33,7 +33,7 @@ export interface StorageProvider<T extends GlobalPreferences = GlobalPreferences
* @param preferences - The preferences to save.
* @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,
nextPageToken?: string
): Promise<{
rooms: R[];
rooms: MRoom[];
isTruncated: boolean;
nextPageToken?: string;
}>;
@ -61,15 +61,15 @@ export interface StorageProvider<T extends GlobalPreferences = GlobalPreferences
* @param roomId - The name of the room to retrieve.
* @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.
*
* @param ovRoom - The OpenVidu Room to save.
* @param meetRoom - The OpenVidu Room to save.
* @returns A promise that resolves to the saved
**/
saveMeetRoom(ovRoom: R): Promise<R>;
saveMeetRoom(meetRoom: MRoom): Promise<MRoom>;
/**
* Deletes OpenVidu Meet Rooms.
@ -86,7 +86,7 @@ export interface StorageProvider<T extends GlobalPreferences = GlobalPreferences
*
* @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.

View File

@ -12,11 +12,14 @@ import { LoggerService, MutexService, StorageFactory, StorageProvider } from '..
* This service provides an abstraction layer over the underlying storage implementation,
* handling initialization, retrieval, and persistence of global preferences and room data.
*
* @typeParam G - Type for global preferences, extends GlobalPreferences
* @typeParam R - Type for room data, extends MeetRoom
* @template GPrefs - Type for global preferences, extends GlobalPreferences
* @template MRoom - Type for room data, extends MeetRoom
*/
@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;
constructor(
@inject(LoggerService) protected logger: LoggerService,
@ -28,7 +31,7 @@ export class MeetStorageService<G extends GlobalPreferences = GlobalPreferences,
/**
* Initializes default preferences if not already initialized.
* @returns {Promise<G>} Default global preferences.
* @returns {Promise<GPrefs>} Default global preferences.
*/
async initializeGlobalPreferences(): Promise<void> {
try {
@ -53,12 +56,12 @@ export class MeetStorageService<G extends GlobalPreferences = GlobalPreferences,
/**
* 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();
if (preferences) return preferences as G;
if (preferences) return preferences as GPrefs;
await this.initializeGlobalPreferences();
preferences = await this.storageProvider.getGlobalPreferences();
@ -68,34 +71,50 @@ export class MeetStorageService<G extends GlobalPreferences = GlobalPreferences,
throw internalError('getting global preferences');
}
return preferences as G;
return preferences as GPrefs;
}
/**
* Saves the global preferences.
* @param {GlobalPreferences} preferences
* @returns {Promise<GlobalPreferences>}
* Saves the global preferences to the storage provider.
* @param {GPrefs} preferences
* @returns {Promise<GPrefs>}
*/
async saveGlobalPreferences(preferences: G): Promise<G> {
async saveGlobalPreferences(preferences: GPrefs): Promise<GPrefs> {
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}`);
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(
maxItems?: number,
nextPageToken?: string
): Promise<{
rooms: R[];
rooms: MRoom[];
isTruncated: boolean;
nextPageToken?: string;
}> {
return this.storageProvider.getMeetRooms(maxItems, nextPageToken) as Promise<{
rooms: R[];
rooms: MRoom[];
isTruncated: boolean;
nextPageToken?: string;
}>;
@ -108,7 +127,7 @@ export class MeetStorageService<G extends GlobalPreferences = GlobalPreferences,
* @returns A promise that resolves to the room's preferences.
* @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);
if (!meetRoom) {
@ -116,30 +135,57 @@ export class MeetStorageService<G extends GlobalPreferences = GlobalPreferences,
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> {
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> {
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> {
return this.storageProvider.updateArchivedRoomMetadata(roomId);
}
/**
* Returns the default global preferences.
* @returns {G}
* @returns {GPrefs}
*/
protected async getDefaultPreferences(): Promise<G> {
protected async getDefaultPreferences(): Promise<GPrefs> {
return {
projectId: MEET_NAME_ID,
webhooksPreferences: {
@ -162,7 +208,7 @@ export class MeetStorageService<G extends GlobalPreferences = GlobalPreferences,
}
}
}
} as G;
} as GPrefs;
}
/**