简体   繁体   中英

NestJS - Grpc client: RpcException from server is serialized to an Error instead of RpcException

I've been at this all day and can't seem to find a solution,
please help:)

The service communication works, the issue is with the error handling...

Scenario:

Service-A is invoked via HTTP. (probably not relevant but just in case)
Service-A calls Service-B via RPC.
Service-B throws an error.
an exception filter on Service-B 's controller catches that error and translates it to a RpcException and returns that to to Service-A .
Service-A receives an Error not a RpcExcpetion .

The error is caught in the global error handler as it is not recognized as a RpcException
(would have been caught in Service-B 's RpcExceptionFilter ...)

Some code:

Service-A :

client configuration
    @Module({
        imports: [...],
        controllers: [...],
        providers: [{
            provide: 'somePackage',
            useFactory(configService: ConfigService) {
                return ClientProxyFactory.create(
                    {
                        transport: Transport.GRPC,
                        options: {
                            url: 'localhost:5000',
                            package: 'somePackage',
                            protoPath: 'pathToProto',
                        },
                    }
                );
            },
            inject: [ConfigService],
        }]
    })
client service injection and init
    export class ServiceA implements OnModuleInit {
    
        private someService: SomeServiceClient;
    
        onModuleInit(): any {
            this.someService = this.client.getService<SomeServiceClient>('SomeService');
        }
    
        constructor(@Inject(somePackage) private client: ClientGrpc)
    }
client method call

await lastValueFrom(this.someService.workWork(workWorkRequest));

Service-B :

error conversion (ExceptionFilter)
catch(exception: RpcException){
        const rpcException: RpcException = someConversionFunction(exception);
        return throwError(() => rpcException.getError());
    }

some logging outputs :

this is what thrown on service-a :
[error][2022-05-30T18:58:13.132Z]-[App/Main] - 9 FAILED_PRECONDITION: Some Service-B error message if i try catch the call and log the error:

Error: 9 FAILED_PRECONDITION: Some Service-B error message
    at Object.callErrorFromStatus (@grpc/grpc-js/src/call.ts:81:24)
    at Object.onReceiveStatus (@grpc/grpc-js/src/client.ts:343:36)
    at Object.onReceiveStatus (@grpc/grpc-js/src/client-interceptors.ts:462:34)
    at Object.onReceiveStatus (@grpc/grpc-js/src/client-interceptors.ts:424:48)
    at @grpc/grpc-js/src/call-stream.ts:323:24
    at processTicksAndRejections (node:internal/process/task_queues:78:11) {
    code: 9,
    details: 'Some Service-B error message',
    metadata: Metadata { internalRepr: Map(0) {}, options: {} }
}

what i expect is basically the same, just as a RpcError:
RpcException [Error]: Some Service-B error message

I've tried to minimize the code as much as possible...
Any input is welcome...
Thanks!

If anyone stumbles across this,
It is now possible to add an error serializer when creating the ClientProxy like so:

class ErrorHandlingProxy extends ClientGrpcProxy {
  serializeError(err) {
    return new RpcException(err);
  }
}

@Module({
  providers: [
    {
      provide: 'HERO_PACKAGE',
      useFactory() {
        return new ErrorHandlingProxy(grpcClientOptions.options);
      },
    },
  ],
  controllers: [HeroController],
})
export class HeroModule {}

More details in this issue

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM