backend: refactor RecordingService to use StorageProvider for listing objects and remove S3Service dependency
This commit is contained in:
parent
2872383b01
commit
333c7da5b2
@ -32,7 +32,6 @@ import {
|
|||||||
MutexService,
|
MutexService,
|
||||||
RedisLock,
|
RedisLock,
|
||||||
RoomService,
|
RoomService,
|
||||||
S3Service,
|
|
||||||
SystemEventService,
|
SystemEventService,
|
||||||
TaskSchedulerService
|
TaskSchedulerService
|
||||||
} from './index.js';
|
} from './index.js';
|
||||||
@ -40,7 +39,6 @@ import {
|
|||||||
@injectable()
|
@injectable()
|
||||||
export class RecordingService {
|
export class RecordingService {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(S3Service) protected s3Service: S3Service,
|
|
||||||
@inject(LiveKitService) protected livekitService: LiveKitService,
|
@inject(LiveKitService) protected livekitService: LiveKitService,
|
||||||
@inject(RoomService) protected roomService: RoomService,
|
@inject(RoomService) protected roomService: RoomService,
|
||||||
@inject(MutexService) protected mutexService: MutexService,
|
@inject(MutexService) protected mutexService: MutexService,
|
||||||
@ -306,7 +304,7 @@ export class RecordingService {
|
|||||||
protected async shouldDeleteRoomMetadata(roomId: string): Promise<boolean | null> {
|
protected async shouldDeleteRoomMetadata(roomId: string): Promise<boolean | null> {
|
||||||
try {
|
try {
|
||||||
const metadataPrefix = `${INTERNAL_CONFIG.S3_RECORDINGS_PREFIX}/.metadata/${roomId}`;
|
const metadataPrefix = `${INTERNAL_CONFIG.S3_RECORDINGS_PREFIX}/.metadata/${roomId}`;
|
||||||
const { Contents } = await this.s3Service.listObjectsPaginated(metadataPrefix);
|
const { Contents } = await this.storageService.listObjects(metadataPrefix, 1);
|
||||||
|
|
||||||
// If no metadata files exist or the list is empty, the room metadata should be deleted
|
// If no metadata files exist or the list is empty, the room metadata should be deleted
|
||||||
return !Contents || Contents.length === 0;
|
return !Contents || Contents.length === 0;
|
||||||
@ -346,10 +344,11 @@ export class RecordingService {
|
|||||||
try {
|
try {
|
||||||
// Construct the room prefix if a room ID is provided
|
// Construct the room prefix if a room ID is provided
|
||||||
const roomPrefix = roomId ? `/${roomId}` : '';
|
const roomPrefix = roomId ? `/${roomId}` : '';
|
||||||
|
const recordingPrefix = `${INTERNAL_CONFIG.S3_RECORDINGS_PREFIX}/.metadata${roomPrefix}`;
|
||||||
|
|
||||||
// Retrieve the recordings from the S3 bucket
|
// Retrieve the recordings from the S3 bucket
|
||||||
const { Contents, IsTruncated, NextContinuationToken } = await this.s3Service.listObjectsPaginated(
|
const { Contents, IsTruncated, NextContinuationToken } = await this.storageService.listObjects(
|
||||||
`${INTERNAL_CONFIG.S3_RECORDINGS_PREFIX}/.metadata${roomPrefix}`,
|
recordingPrefix,
|
||||||
maxItems,
|
maxItems,
|
||||||
nextPageToken
|
nextPageToken
|
||||||
);
|
);
|
||||||
|
|||||||
@ -128,7 +128,6 @@ export class S3Service {
|
|||||||
additionalPrefix = '',
|
additionalPrefix = '',
|
||||||
maxKeys = 50,
|
maxKeys = 50,
|
||||||
continuationToken?: string,
|
continuationToken?: string,
|
||||||
searchPattern = '',
|
|
||||||
bucket: string = MEET_S3_BUCKET
|
bucket: string = MEET_S3_BUCKET
|
||||||
): Promise<ListObjectsV2CommandOutput> {
|
): Promise<ListObjectsV2CommandOutput> {
|
||||||
// The complete prefix is constructed by combining the subbucket and the additionalPrefix.
|
// The complete prefix is constructed by combining the subbucket and the additionalPrefix.
|
||||||
@ -145,16 +144,7 @@ export class S3Service {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response: ListObjectsV2CommandOutput = await this.s3.send(command);
|
return await this.s3.send(command);
|
||||||
|
|
||||||
// If searchPattern is provided, filter the results.
|
|
||||||
|
|
||||||
if (searchPattern) {
|
|
||||||
const regex = new RegExp(searchPattern);
|
|
||||||
response.Contents = (response.Contents || []).filter((item) => item.Key && regex.test(item.Key));
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
this.logger.error(`S3 listObjectsPaginated: error listing objects with prefix "${basePrefix}": ${error}`);
|
this.logger.error(`S3 listObjectsPaginated: error listing objects with prefix "${basePrefix}": ${error}`);
|
||||||
throw internalError('listing objects from S3');
|
throw internalError('listing objects from S3');
|
||||||
|
|||||||
@ -58,6 +58,39 @@ export class S3StorageProvider<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists objects in the storage with optional pagination support.
|
||||||
|
*
|
||||||
|
* @param prefix - The prefix to filter objects by (acts as a folder path)
|
||||||
|
* @param maxItems - Maximum number of items to return (optional)
|
||||||
|
* @param nextPageToken - Token for pagination to get the next page (optional)
|
||||||
|
* @returns Promise resolving to paginated list of objects with metadata
|
||||||
|
*/
|
||||||
|
async listObjects(
|
||||||
|
prefix: string,
|
||||||
|
maxItems?: number,
|
||||||
|
nextPageToken?: string
|
||||||
|
): Promise<{
|
||||||
|
Contents?: Array<{
|
||||||
|
Key?: string;
|
||||||
|
LastModified?: Date;
|
||||||
|
Size?: number;
|
||||||
|
ETag?: string;
|
||||||
|
}>;
|
||||||
|
IsTruncated?: boolean;
|
||||||
|
NextContinuationToken?: string;
|
||||||
|
}> {
|
||||||
|
try {
|
||||||
|
this.logger.debug(
|
||||||
|
`Listing objects with prefix: ${prefix}, maxItems: ${maxItems}, nextPageToken: ${nextPageToken}`
|
||||||
|
);
|
||||||
|
return await this.s3Service.listObjectsPaginated(prefix, maxItems, nextPageToken);
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(error, `Error listing objects with prefix ${prefix}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes global preferences. If no preferences exist, persists the provided defaults.
|
* Initializes global preferences. If no preferences exist, persists the provided defaults.
|
||||||
* If preferences exist but belong to a different project, they are replaced.
|
* If preferences exist but belong to a different project, they are replaced.
|
||||||
|
|||||||
@ -33,6 +33,29 @@ export interface StorageProvider<
|
|||||||
*/
|
*/
|
||||||
getObjectHeaders(filePath: string): Promise<{ contentLength?: number; contentType?: string }>;
|
getObjectHeaders(filePath: string): Promise<{ contentLength?: number; contentType?: string }>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists objects in the storage with optional pagination support.
|
||||||
|
*
|
||||||
|
* @param prefix - The prefix to filter objects by (acts as a folder path)
|
||||||
|
* @param maxItems - Maximum number of items to return (optional)
|
||||||
|
* @param nextPageToken - Token for pagination to get the next page (optional)
|
||||||
|
* @returns Promise resolving to paginated list of objects with metadata
|
||||||
|
*/
|
||||||
|
listObjects(
|
||||||
|
prefix: string,
|
||||||
|
maxItems?: number,
|
||||||
|
nextPageToken?: string
|
||||||
|
): Promise<{
|
||||||
|
Contents?: Array<{
|
||||||
|
Key?: string;
|
||||||
|
LastModified?: Date;
|
||||||
|
Size?: number;
|
||||||
|
ETag?: string;
|
||||||
|
}>;
|
||||||
|
IsTruncated?: boolean;
|
||||||
|
NextContinuationToken?: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the global preferences of Openvidu Meet.
|
* Retrieves the global preferences of Openvidu Meet.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -42,6 +42,31 @@ export class MeetStorageService<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists objects in the storage with optional pagination support.
|
||||||
|
*
|
||||||
|
* @param prefix - The prefix to filter objects by (acts as a folder path)
|
||||||
|
* @param maxItems - Maximum number of items to return (optional)
|
||||||
|
* @param nextPageToken - Token for pagination to get the next page (optional)
|
||||||
|
* @returns Promise resolving to paginated list of objects with metadata
|
||||||
|
*/
|
||||||
|
listObjects(
|
||||||
|
prefix: string,
|
||||||
|
maxItems?: number,
|
||||||
|
nextPageToken?: string
|
||||||
|
): Promise<{
|
||||||
|
Contents?: Array<{
|
||||||
|
Key?: string;
|
||||||
|
LastModified?: Date;
|
||||||
|
Size?: number;
|
||||||
|
ETag?: string;
|
||||||
|
}>;
|
||||||
|
IsTruncated?: boolean;
|
||||||
|
NextContinuationToken?: string;
|
||||||
|
}> {
|
||||||
|
return this.storageProvider.listObjects(prefix, maxItems, nextPageToken);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes default preferences if not already initialized.
|
* Initializes default preferences if not already initialized.
|
||||||
* @returns {Promise<GPrefs>} Default global preferences.
|
* @returns {Promise<GPrefs>} Default global preferences.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user