feat(api): add async error handling to critical module handlers
Wrap async operations at application layer boundaries with proper try/catch, LoggerService logging, and domain exceptions: - UploadMediaHandler: mediaStorage.upload() error boundary - ExportUserDataHandler: Promise.all() error logging - ForceDeleteUserHandler: $transaction error logging - LoginUserHandler: token generation error boundary - RefreshTokenHandler: token rotation error boundary - CreatePaymentHandler: payment gateway call error boundary Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { Inject } from '@nestjs/common';
|
||||
import { CommandHandler, type ICommandHandler } from '@nestjs/cqrs';
|
||||
import { createId } from '@paralleldrive/cuid2';
|
||||
import { NotFoundException, ValidationException } from '@modules/shared';
|
||||
import { type LoggerService, NotFoundException, ValidationException } from '@modules/shared';
|
||||
import { PropertyMediaEntity } from '../../../domain/entities/property-media.entity';
|
||||
import { PROPERTY_REPOSITORY, type IPropertyRepository } from '../../../domain/repositories/property.repository';
|
||||
import { MEDIA_STORAGE_SERVICE, type IMediaStorageService } from '../../../infrastructure/services/media-storage.service';
|
||||
@@ -14,6 +14,7 @@ export class UploadMediaHandler implements ICommandHandler<UploadMediaCommand> {
|
||||
constructor(
|
||||
@Inject(PROPERTY_REPOSITORY) private readonly propertyRepo: IPropertyRepository,
|
||||
@Inject(MEDIA_STORAGE_SERVICE) private readonly mediaStorage: IMediaStorageService,
|
||||
private readonly logger: LoggerService,
|
||||
) {}
|
||||
|
||||
async execute(command: UploadMediaCommand): Promise<{ mediaId: string; url: string }> {
|
||||
@@ -29,12 +30,22 @@ export class UploadMediaHandler implements ICommandHandler<UploadMediaCommand> {
|
||||
|
||||
const mediaType = command.file.mimetype.startsWith('video/') ? 'video' as const : 'image' as const;
|
||||
|
||||
const url = await this.mediaStorage.upload(
|
||||
command.file.buffer,
|
||||
command.file.originalname,
|
||||
command.file.mimetype,
|
||||
`properties/${command.propertyId}`,
|
||||
);
|
||||
let url: string;
|
||||
try {
|
||||
url = await this.mediaStorage.upload(
|
||||
command.file.buffer,
|
||||
command.file.originalname,
|
||||
command.file.mimetype,
|
||||
`properties/${command.propertyId}`,
|
||||
);
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Media upload failed for property ${command.propertyId}: ${error instanceof Error ? error.message : error}`,
|
||||
error instanceof Error ? error.stack : undefined,
|
||||
'UploadMediaHandler',
|
||||
);
|
||||
throw new ValidationException('Tải lên media thất bại, vui lòng thử lại');
|
||||
}
|
||||
|
||||
const mediaId = createId();
|
||||
const media = PropertyMediaEntity.createNew(
|
||||
|
||||
Reference in New Issue
Block a user