Skip to content

Commit

Permalink
Merge pull request #10110 from gilre/gilre-fix/grpc-client-serialize-…
Browse files Browse the repository at this point in the history
…error

fix(microservice): grpc-client serialize error
  • Loading branch information
kamilmysliwiec authored Aug 16, 2022
2 parents a1829bc + 1cebb6d commit c84ea3e
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 6 deletions.
12 changes: 12 additions & 0 deletions integration/microservices/e2e/sum-grpc.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ describe('GRPC transport', () => {
.expect(200, { result: 15 });
});

it(`GRPC Receiving serialized Error`, async () => {
await request(server)
.post('/error?client=standard')
.expect(200)
.expect('false');

await request(server)
.post('/error?client=custom')
.expect(200)
.expect('true');
});

it(`GRPC Sending and Receiving HTTP POST (multiple proto)`, async () => {
await request(server)
.post('/multi/sum')
Expand Down
53 changes: 51 additions & 2 deletions integration/microservices/src/grpc/grpc.controller.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
import { Body, Controller, HttpCode, Post } from '@nestjs/common';
import { Body, Controller, HttpCode, Post, Query } from '@nestjs/common';
import {
Client,
ClientGrpc,
GrpcMethod,
GrpcStreamCall,
GrpcStreamMethod,
Transport,
ClientGrpcProxy,
RpcException,
} from '@nestjs/microservices';
import { join } from 'path';
import { Observable, of } from 'rxjs';
import { Observable, of, catchError } from 'rxjs';

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

@Controller()
export class GrpcController {
private readonly customClient: ClientGrpc;
constructor() {
this.customClient = new ErrorHandlingProxy({
package: 'math',
protoPath: join(__dirname, 'math.proto'),
});
}

@Client({
transport: Transport.GRPC,
options: {
Expand Down Expand Up @@ -78,6 +94,19 @@ export class GrpcController {
});
}

@GrpcMethod('Math')
async divide(request: { dividend: number; divisor: number }): Promise<any> {
if (request.divisor === 0) {
throw new RpcException({
code: 3,
message: 'dividing by 0 is not possible',
});
}
return {
result: request.dividend / request.divisor,
};
}

@GrpcMethod('Math2')
async sum2({ data }: { data: number[] }): Promise<any> {
return of({
Expand All @@ -98,4 +127,24 @@ export class GrpcController {
const svc = this.clientMulti.getService<any>('Math2');
return svc.sum2({ data });
}

@Post('error')
@HttpCode(200)
serializeError(
@Query('client') query: 'custom' | 'standard' = 'standard',
@Body() body: Record<string, any>,
): Observable<boolean> {
const client = query === 'custom' ? this.customClient : this.client;
const svc = client.getService<any>('Math');

const errorDivideRequest = {
dividend: 1,
divisor: 0,
};
return svc.divide(errorDivideRequest).pipe(
catchError(err => {
return of(err instanceof RpcException);
}),
);
}
}
12 changes: 11 additions & 1 deletion integration/microservices/src/grpc/math.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ service Math {
rpc Sum (RequestSum) returns (SumResult);
rpc SumStream(stream RequestSum) returns(stream SumResult);
rpc SumStreamPass(stream RequestSum) returns(stream SumResult);
rpc Divide (RequestDivide) returns (DivideResult);
}

message SumResult {
Expand All @@ -14,4 +15,13 @@ message SumResult {

message RequestSum {
repeated int32 data = 1;
}
}

message RequestDivide {
int32 dividend = 1;
int32 divisor = 2 ;
}

message DivideResult {
int32 result = 1;
}
6 changes: 3 additions & 3 deletions packages/microservices/client/client-grpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export class ClientGrpcProxy extends ClientProxy implements ClientGrpc {
return;
}
}
observer.error(error);
observer.error(this.serializeError(error));
});
call.on('end', () => {
if (upstreamSubscription) {
Expand Down Expand Up @@ -216,7 +216,7 @@ export class ClientGrpcProxy extends ClientProxy implements ClientGrpc {
const callArgs = [
(error: unknown, data: unknown) => {
if (error) {
return observer.error(error);
return observer.error(this.serializeError(error));
}
observer.next(data);
observer.complete();
Expand All @@ -243,7 +243,7 @@ export class ClientGrpcProxy extends ClientProxy implements ClientGrpc {
return new Observable(observer => {
client[methodName](...args, (error: any, data: any) => {
if (error) {
return observer.error(error);
return observer.error(this.serializeError(error));
}
observer.next(data);
observer.complete();
Expand Down

0 comments on commit c84ea3e

Please sign in to comment.