【发布时间】:2022-11-30 13:39:32
【问题描述】:
我对 NestJS 中跨微服务的正确异常处理有疑问。当前设置如下所示。客户端请求 ==(REST)==> API 网关 ==(RabbitMQ / RPC)==> Service-A
在 Service-A 中发生异常,我将其作为 RPC 异常抛出并希望在 API 网关中转换为 HTTPException。
我的 API 网关的结构如下所示 => 控制器 => 服务 => RabbitMQ RPC 请求
我的服务 A 看起来像这样: => Controller => Service => CQRS => CommandHandler => GenericRepo 等。
从那以后我发现最好在控制器中处理异常。因此,我的 API 控制器和 API 服务如下所示。
@ApiTags('User')
@Controller('user')
export class UserController {
private readonly _logger = new Logger(UserController.name);
constructor(
@Inject(IRESETSERVICE) private readonly _userService: UserService
) {}
@ApiOperation({ summary: 'Create a new user' })
@ApiCreatedResponse({ description: 'The user has been successfully created.' })
@ApiUnprocessableEntityResponse({ description: 'The user could not be created.' })
@ApiForbiddenResponse({ description: 'Forbidden.' })
@ApiUnauthorizedResponse({ description: 'Unauthorized.' })
@ApiInternalServerErrorResponse({ description: 'Internal server error.' })
@Post()
async create(@Body() createUserDto: CreateUserDto) {
try {
return this._userService.create(createUserDto);
}
catch (error) {
this._logger.error(error.message);
return error;
}
}
}
@Injectable()
export class UserService implements IRestService {
private readonly _logger = new Logger(UserService.name)
constructor(
private readonly _amqpService: AmqpService
) {};
async create(createUserDto: CreateUserDto): Promise<CreateUserResponseDto> {
return this._amqpService.request(AmqpExchange.ACCOUNT_SERVICE, AmqpRoutingKey.USER + AmqpRoutingKeyOperation.CREATE, { dto: createUserDto });
}
}
服务中的控制器包括。服务本身看起来像这样:
@Controller()
export class UserController {
private readonly _logger = new Logger(UserService.name)
constructor(
@Inject(IAMQPSERVICE) private readonly _usersService: UserService
) {}
@RabbitRPC({
exchange: AmqpExchange.ACCOUNT_SERVICE,
routingKey: AmqpRoutingKey.USER + AmqpRoutingKeyOperation.CREATE,
queue: AmqpRoutingKey.USER + AmqpRoutingKeyOperation.CREATE,
})
async create(@RabbitPayload() payload) {
return this._usersService.create(payload.request.dto);
}
}
@Injectable()
export class UserService implements IAmqpService {
private readonly _logger = new Logger(UserService.name)
constructor(
private readonly _queryBus: QueryBus,
private readonly _commandBus: CommandBus,
) {}
async create(createUserDto: CreateUserDto) {
return this._commandBus.execute(new CreateUserCommand(createUserDto));
}
}
@CommandHandler(CreateUserCommand)
export class CreateUserHandler implements ICommandHandler<CreateUserCommand> {
constructor(
private _userUseCases: UserUseCases,
private _userFactoryService: UserFactoryService
) {}
async execute(command: CreateUserCommand) {
console.log('Async CreateUserCommand...');
const createUserResponse = new CreateUserResponseDto();
try {
const user = this._userFactoryService.createNewUser(command.createUserDto);
const createdUser = await this._userUseCases.createUser(user);
createUserResponse.success = true;
createUserResponse.createdUser = createdUser;
} catch (error) {
// report and log error
createUserResponse.success = false;
return new MyRpcException(error,500);
}
return createUserResponse;
}
}
`
CommandHandler (MyRpcException) 中抛出的异常我准备好作为响应,但邮递员显示状态 201(已创建)尽管 500。我的 MyRpcException 解决方案来自:How to handle RpcException in NestJS 但没有工作(最后评论)
我测试了自定义 ExceptionFilter
【问题讨论】:
标签: typescript exception nestjs nestjs-exception-filters