Skip to content

Commit

Permalink
backend: Improved error logs when s3 is not available
Browse files Browse the repository at this point in the history
  • Loading branch information
CSantosM committed Jun 28, 2024
1 parent 687d48b commit 2f3f3ba
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 45 deletions.
8 changes: 6 additions & 2 deletions openvidu-call-back/src/models/error.model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
type StatusError = 400 | 404 | 406 | 409 | 422 | 500 | 501;
type StatusError = 400 | 404 | 406 | 409 | 422 | 500 | 503;
export class OpenViduCallError extends Error {
name: string;
statusCode: StatusError;
Expand All @@ -12,9 +12,13 @@ export class OpenViduCallError extends Error {
// General errors

export const errorLivekitIsNotAvailable = (): OpenViduCallError => {
return new OpenViduCallError('LiveKit Error', 'LiveKit is not available', 500);
return new OpenViduCallError('LiveKit Error', 'LiveKit is not available', 503);
};

export const errorS3NotAvailable = (error: any): OpenViduCallError => {
return new OpenViduCallError('S3 Error', `S3 is not available ${error}`, 503);
}

export const internalError = (error: any): OpenViduCallError => {
return new OpenViduCallError('Unexpected error', `Something went wrong ${error}`, 500);
};
Expand Down
70 changes: 30 additions & 40 deletions openvidu-call-back/src/services/recording.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,54 +189,44 @@ export class RecordingService {
}

private async getRecording(egressId: string): Promise<RecordingInfo> {
try {
const egressIdSanitized = this.sanitizeRegExp(egressId);
const regexPattern = `.*${egressIdSanitized}.*\\.json`;
const metadataObject = await this.s3Service.listObjects('.metadata', regexPattern);
const egressIdSanitized = this.sanitizeRegExp(egressId);
const regexPattern = `.*${egressIdSanitized}.*\\.json`;
const metadataObject = await this.s3Service.listObjects('.metadata', regexPattern);

if (!metadataObject.Contents || metadataObject.Contents.length === 0) {
throw errorRecordingNotFound(egressId);
}

const recording = await this.s3Service.getObjectAsJson(metadataObject.Contents[0].Key!) as RecordingInfo;
return recording;
// return RecordingHelper.toRecordingInfo(recording);
} catch (error) {
this.logger.error(`Error getting recording ${egressId}: ${error}`);
throw error;
if (!metadataObject.Contents || metadataObject.Contents.length === 0) {
throw errorRecordingNotFound(egressId);
}

const recording = (await this.s3Service.getObjectAsJson(metadataObject.Contents[0].Key!)) as RecordingInfo;
return recording;
// return RecordingHelper.toRecordingInfo(recording);
}

async getRecordingAsStream(
recordingId: string,
range?: string
): Promise<{ fileSize: number | undefined; fileStream: Readable; start?: number; end?: number }> {
try {
const egressInfo = await this.getRecording(recordingId);
const recordingPath = RecordingHelper.extractFileNameFromUrl(egressInfo.location);

if (!recordingPath) throw new Error(`Error extracting path from recording ${recordingId}`);

const data = await this.s3Service.getHeaderObject(recordingPath);
const fileSize = data.ContentLength;

if (range && fileSize) {
// Parse the range header
const parts = range.replace(/bytes=/, '').split('-');
const start = parseInt(parts[0], 10);
const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
const fileStream = await this.s3Service.getObjectAsStream(recordingPath, CALL_AWS_S3_BUCKET, {
start,
end
});
return { fileSize, fileStream, start, end };
} else {
const fileStream = await this.s3Service.getObjectAsStream(recordingPath);
return { fileSize, fileStream };
}
} catch (error) {
this.logger.error(`Error streaming recording ${recordingId}: ${error}`);
throw error;
const egressInfo = await this.getRecording(recordingId);
const recordingPath = RecordingHelper.extractFileNameFromUrl(egressInfo.location);

if (!recordingPath) throw new Error(`Error extracting path from recording ${recordingId}`);

const data = await this.s3Service.getHeaderObject(recordingPath);
const fileSize = data.ContentLength;

if (range && fileSize) {
// Parse the range header
const parts = range.replace(/bytes=/, '').split('-');
const start = parseInt(parts[0], 10);
const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
const fileStream = await this.s3Service.getObjectAsStream(recordingPath, CALL_AWS_S3_BUCKET, {
start,
end
});
return { fileSize, fileStream, start, end };
} else {
const fileStream = await this.s3Service.getObjectAsStream(recordingPath);
return { fileSize, fileStream };
}
}

Expand Down
25 changes: 22 additions & 3 deletions openvidu-call-back/src/services/s3.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
CALL_AWS_SECRET_KEY,
CALL_AWS_S3_WITH_PATH_STYLE_ACCESS
} from '../config.js';
import { internalError } from '../models/error.model.js';
import { errorS3NotAvailable, internalError } from '../models/error.model.js';
import { Readable } from 'stream';
import { LoggerService } from './logger.service.js';

Expand Down Expand Up @@ -93,8 +93,13 @@ export class S3Service {
Body: JSON.stringify(body)
});
return await this.run(command);
} catch (error) {
} catch (error: any) {
this.logger.error(`Error putting object in S3: ${error}`);

if (error.code === 'ECONNREFUSED') {
throw errorS3NotAvailable(error);
}

throw internalError(error);
}
}
Expand Down Expand Up @@ -179,6 +184,11 @@ export class S3Service {
return response;
} catch (error) {
this.logger.error(`Error listing objects: ${error}`);

if ((error as any).code === 'ECONNREFUSED') {
throw errorS3NotAvailable(error);
}

throw internalError(error);
}
}
Expand All @@ -194,6 +204,10 @@ export class S3Service {
return undefined;
}

if (error.code === 'ECONNREFUSED') {
throw errorS3NotAvailable(error);
}

this.logger.error(`Error getting object from S3. Maybe it has been deleted: ${error}`);
throw internalError(error);
}
Expand All @@ -208,8 +222,13 @@ export class S3Service {
} else {
throw new Error('Empty body response');
}
} catch (error) {
} catch (error: any) {
this.logger.error(`Error getting object from S3: ${error}`);

if (error.code === 'ECONNREFUSED') {
throw errorS3NotAvailable(error);
}

throw internalError(error);
}
}
Expand Down

0 comments on commit 2f3f3ba

Please sign in to comment.