nestjsgrpcgrpc-node

NestJS GRPC Error: call.sendMetadata is not a function


I'm trying to send a metadata from the server side gprc using NestJS framework. On the official NestJS guide here: it shows a example of doing the server side grpc metadata:

@Controller()
export class HeroesService {
    @GrpcMethod()
    findOne(data: HeroById, metadata: Metadata, call: ServerUnaryCall<any>): Hero {
        const serverMetadata = new Metadata();
        const items = [
          { id: 1, name: 'John' },
          { id: 2, name: 'Doe' },
        ];
    
        serverMetadata.add('Set-Cookie', 'yummy_cookie=choco');
        call.sendMetadata(serverMetadata);
    
        return items.find(({ id }) => id === data.id);
    }
}

On my code, I wrote a similar code:

@GrpcMethod('ClinicService', 'GetCustomerClinicNames')
async GetCustomerClinicNames_GRPC(data: CustomerClinicID, call:ServerUnaryCall<Any,Any>) {
    const metadata = new Metadata();
    const result = await this.clinicService.GetClinicName(Number(data.customer_id));
    console.log(result);
    metadata.add('context', "Jello")
    call.sendMetadata(metadata)
    return { response: result};
}

However, it gives me an error says:

[Nest] 53188  - 04/06/2022, 5:17:50 PM   ERROR [RpcExceptionsHandler] call.sendMetadata is not a function
TypeError: call.sendMetadata is not a function
    at ClinicController.GetCustomerClinicNames_GRPC (C:\Users\Vibrant\Desktop\core-samples\src\clinic\clinic.controller.ts:118:10)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at C:\Users\Vibrant\Desktop\core-samples\node_modules\@nestjs\microservices\context\rpc-proxy.js:11:32

But I think the .sendMetadata is indeed a function. Where am I wrong about this?

For the sendMetadata Function, it is defined as:

export declare type ServerSurfaceCall = {
    cancelled: boolean;
    readonly metadata: Metadata;
    getPeer(): string;
    sendMetadata(responseMetadata: Metadata): void;
    getDeadline(): Deadline;
} & EventEmitter;

export declare type ServerUnaryCall<RequestType, ResponseType> = ServerSurfaceCall & {
    request: RequestType;
};

Solution

  • So apparently you need to keep the metadata parameter in your async GetCustomerClinicNames_GRPC. I tried with and without and it only worked when I had it.

    so for example, I tried:

    @GrpcMethod('HeroesService', 'FindOne')
    findOne(data: any, call: ServerUnaryCall<any, any>): any
    

    and that didn't work, then I tried:

    @GrpcMethod('HeroesService', 'FindOne')
    findOne(data: any, _metadata: Metadata, call: ServerUnaryCall<any, any>): any
    

    and it worked by doing something like:

    @GrpcMethod('HeroesService', 'FindOne')
    findOne(data: any, _metadata: Metadata, call: ServerUnaryCall<any, any>): any {
        const items = [
            { id: 1, name: 'John' },
            { id: 2, name: 'Doe' },
        ];
        
        const metadata = new Metadata();
        metadata.add('context', 'Jello');
        call.sendMetadata(metadata);
    
        return items.find(({ id }) => id === data.id);
    }
    

    I'm not sure why though, since we are using named arguments.