0
# gRPC Integration
1
2
Specialized support for gRPC protocol with service definitions, streaming methods, and protocol buffer integration, providing high-performance RPC communication with type safety and bidirectional streaming capabilities.
3
4
## Capabilities
5
6
### gRPC Method Decorators
7
8
Decorators for defining gRPC service methods with support for unary and streaming patterns.
9
10
```typescript { .api }
11
/**
12
* Registers gRPC method handler for unary calls
13
* @param service - Optional service name from proto definition
14
* @returns Method decorator
15
*/
16
function GrpcMethod(service?: string): MethodDecorator;
17
/**
18
* Registers gRPC method handler for unary calls
19
* @param service - Service name from proto definition
20
* @param method - Optional method name, defaults to function name
21
* @returns Method decorator
22
*/
23
function GrpcMethod(service: string, method?: string): MethodDecorator;
24
25
/**
26
* Registers gRPC streaming method handler with RxJS observables
27
* @param service - Optional service name from proto definition
28
* @param method - Optional method name, defaults to function name
29
* @returns Method decorator
30
*/
31
function GrpcStreamMethod(service?: string, method?: string): MethodDecorator;
32
33
/**
34
* Registers gRPC streaming method with pass-through for manual stream handling
35
* @param service - Optional service name from proto definition
36
* @param method - Optional method name, defaults to function name
37
* @returns Method decorator
38
*/
39
function GrpcStreamCall(service?: string, method?: string): MethodDecorator;
40
```
41
42
**Usage Examples:**
43
44
```typescript
45
import { Controller } from '@nestjs/common';
46
import { GrpcMethod, GrpcStreamMethod, GrpcStreamCall } from '@nestjs/microservices';
47
import { Observable } from 'rxjs';
48
49
// Proto definition:
50
// service HeroService {
51
// rpc FindOne (HeroById) returns (Hero);
52
// rpc FindMany (Empty) returns (stream Hero);
53
// rpc CreateMany (stream CreateHeroRequest) returns (stream Hero);
54
// }
55
56
@Controller()
57
export class HeroController {
58
// Unary method - single request, single response
59
@GrpcMethod('HeroService', 'FindOne')
60
findOne(data: HeroById): Hero {
61
return this.heroService.findById(data.id);
62
}
63
64
// Server streaming - single request, stream response
65
@GrpcStreamMethod('HeroService', 'FindMany')
66
findMany(data: Empty): Observable<Hero> {
67
return this.heroService.findAll();
68
}
69
70
// Bidirectional streaming with RxJS
71
@GrpcStreamMethod('HeroService', 'CreateMany')
72
createMany(data: Observable<CreateHeroRequest>): Observable<Hero> {
73
return data.pipe(
74
map(request => this.heroService.create(request)),
75
tap(hero => this.logger.log(`Created hero: ${hero.name}`))
76
);
77
}
78
79
// Manual stream handling with pass-through
80
@GrpcStreamCall('HeroService', 'ProcessStream')
81
processStream(call: any): void {
82
call.on('data', (data: any) => {
83
const result = this.processHeroData(data);
84
call.write(result);
85
});
86
87
call.on('end', () => {
88
call.end();
89
});
90
91
call.on('error', (error: any) => {
92
this.logger.error('Stream error:', error);
93
call.destroy(error);
94
});
95
}
96
}
97
```
98
99
### gRPC Service Decorator
100
101
Class decorator for defining gRPC service controllers.
102
103
```typescript { .api }
104
/**
105
* Class decorator for gRPC service controllers (alias for @Controller)
106
* @param service - Optional service name
107
* @returns Class decorator
108
*/
109
function GrpcService(service?: string): ClassDecorator;
110
```
111
112
**Usage Examples:**
113
114
```typescript
115
import { GrpcService, GrpcMethod } from '@nestjs/microservices';
116
117
@GrpcService('UserService')
118
export class UserService {
119
@GrpcMethod()
120
getUser(request: GetUserRequest): GetUserResponse {
121
return this.userRepository.findById(request.id);
122
}
123
124
@GrpcMethod()
125
createUser(request: CreateUserRequest): CreateUserResponse {
126
const user = this.userRepository.create(request);
127
return { user, success: true };
128
}
129
}
130
```
131
132
### gRPC Client Interface
133
134
Interface for gRPC client operations providing access to service methods and typed clients.
135
136
```typescript { .api }
137
/**
138
* gRPC client interface for service method access
139
*/
140
interface ClientGrpc {
141
/**
142
* Get gRPC service by name with typed interface
143
* @param name - Service name from proto definition
144
* @returns Typed service interface with methods
145
*/
146
getService<T = any>(name: string): T;
147
148
/**
149
* Get gRPC client by service name
150
* @param name - Service name from proto definition
151
* @returns Typed client interface
152
*/
153
getClientByServiceName<T = any>(name: string): T;
154
}
155
```
156
157
**Usage Examples:**
158
159
```typescript
160
import { Injectable, OnModuleInit } from '@nestjs/common';
161
import { Client, ClientGrpc, Transport } from '@nestjs/microservices';
162
import { join } from 'path';
163
164
interface HeroService {
165
findOne(data: { id: number }): Observable<any>;
166
findMany(data: {}): Observable<any>;
167
}
168
169
interface UserService {
170
getUser(data: { id: string }): Observable<any>;
171
createUser(data: { name: string; email: string }): Observable<any>;
172
}
173
174
@Injectable()
175
export class AppService implements OnModuleInit {
176
@Client({
177
transport: Transport.GRPC,
178
options: {
179
package: ['hero', 'user'],
180
protoPath: [
181
join(__dirname, 'hero.proto'),
182
join(__dirname, 'user.proto')
183
],
184
url: 'localhost:5000',
185
},
186
})
187
private client: ClientGrpc;
188
189
private heroService: HeroService;
190
private userService: UserService;
191
192
onModuleInit() {
193
this.heroService = this.client.getService<HeroService>('HeroService');
194
this.userService = this.client.getService<UserService>('UserService');
195
}
196
197
async getHero(id: number) {
198
return this.heroService.findOne({ id }).toPromise();
199
}
200
201
async createUser(name: string, email: string) {
202
return this.userService.createUser({ name, email }).toPromise();
203
}
204
}
205
```
206
207
### gRPC Streaming Types
208
209
Enumeration for different gRPC method streaming types.
210
211
```typescript { .api }
212
/**
213
* gRPC method streaming type enumeration
214
*/
215
enum GrpcMethodStreamingType {
216
NO_STREAMING = 'no_stream',
217
RX_STREAMING = 'rx_stream',
218
PT_STREAMING = 'pt_stream'
219
}
220
```
221
222
### gRPC Configuration Options
223
224
Configuration interfaces for gRPC transport setup.
225
226
```typescript { .api }
227
/**
228
* gRPC transport configuration options
229
*/
230
interface GrpcOptions {
231
/** Protocol buffer package name(s) */
232
package: string | string[];
233
/** Path to .proto file(s) */
234
protoPath: string | string[];
235
/** gRPC server URL */
236
url?: string;
237
/** Proto loader options */
238
loader?: {
239
keepCase?: boolean;
240
longs?: any;
241
enums?: any;
242
defaults?: boolean;
243
oneofs?: boolean;
244
includeDirs?: string[];
245
};
246
/** gRPC credentials for authentication */
247
credentials?: any;
248
/** Channel options */
249
channelOptions?: Record<string, any>;
250
}
251
```
252
253
**Usage Examples:**
254
255
```typescript
256
import { NestFactory } from '@nestjs/core';
257
import { Transport, MicroserviceOptions } from '@nestjs/microservices';
258
import { join } from 'path';
259
260
// gRPC Server setup
261
async function bootstrap() {
262
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
263
AppModule,
264
{
265
transport: Transport.GRPC,
266
options: {
267
package: ['hero', 'user'],
268
protoPath: [
269
join(__dirname, 'proto/hero.proto'),
270
join(__dirname, 'proto/user.proto')
271
],
272
url: '0.0.0.0:5000',
273
loader: {
274
keepCase: true,
275
longs: String,
276
enums: String,
277
defaults: true,
278
oneofs: true,
279
includeDirs: [join(__dirname, 'proto')]
280
},
281
channelOptions: {
282
'grpc.keepalive_time_ms': 30000,
283
'grpc.keepalive_timeout_ms': 5000,
284
'grpc.keepalive_permit_without_calls': true
285
}
286
},
287
},
288
);
289
290
await app.listen();
291
}
292
293
// gRPC Client setup
294
const client = ClientProxyFactory.create({
295
transport: Transport.GRPC,
296
options: {
297
package: 'hero',
298
protoPath: join(__dirname, 'hero.proto'),
299
url: 'localhost:5000',
300
loader: {
301
keepCase: true,
302
longs: String,
303
enums: String
304
}
305
},
306
}) as ClientGrpc;
307
```
308
309
### Advanced gRPC Features
310
311
**Metadata Handling:**
312
313
```typescript
314
import { Metadata } from '@grpc/grpc-js';
315
316
@Controller()
317
export class AdvancedGrpcController {
318
@GrpcMethod('UserService', 'GetUserWithMetadata')
319
getUserWithMetadata(data: any, metadata: Metadata): any {
320
// Access request metadata
321
const authToken = metadata.get('authorization')[0];
322
const requestId = metadata.get('request-id')[0];
323
324
console.log(`Auth token: ${authToken}`);
325
console.log(`Request ID: ${requestId}`);
326
327
return this.userService.findById(data.id, { authToken, requestId });
328
}
329
330
@GrpcStreamMethod('UserService', 'StreamUsers')
331
streamUsers(data: Observable<any>, metadata: Metadata): Observable<any> {
332
const correlationId = metadata.get('correlation-id')[0];
333
334
return data.pipe(
335
tap(request => console.log(`Processing request ${correlationId}:`, request)),
336
mergeMap(request => this.userService.processStreamRequest(request)),
337
tap(response => console.log(`Response for ${correlationId}:`, response))
338
);
339
}
340
}
341
```
342
343
**Error Handling:**
344
345
```typescript
346
import { RpcException } from '@nestjs/microservices';
347
import { status } from '@grpc/grpc-js';
348
349
@Controller()
350
export class GrpcErrorController {
351
@GrpcMethod('UserService', 'GetUser')
352
getUser(data: { id: string }): any {
353
try {
354
const user = this.userService.findById(data.id);
355
if (!user) {
356
throw new RpcException({
357
code: status.NOT_FOUND,
358
message: `User with ID ${data.id} not found`
359
});
360
}
361
return user;
362
} catch (error) {
363
if (error instanceof ValidationError) {
364
throw new RpcException({
365
code: status.INVALID_ARGUMENT,
366
message: error.message,
367
details: error.details
368
});
369
}
370
371
throw new RpcException({
372
code: status.INTERNAL,
373
message: 'Internal server error'
374
});
375
}
376
}
377
}
378
```
379
380
**Interceptors for gRPC:**
381
382
```typescript
383
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
384
import { Observable } from 'rxjs';
385
import { tap } from 'rxjs/operators';
386
387
@Injectable()
388
export class GrpcLoggingInterceptor implements NestInterceptor {
389
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
390
const rpcContext = context.switchToRpc();
391
const data = rpcContext.getData();
392
const metadata = rpcContext.getContext();
393
394
const serviceName = context.getClass().name;
395
const methodName = context.getHandler().name;
396
397
console.log(`gRPC call: ${serviceName}.${methodName}`);
398
console.log(`Request data:`, data);
399
400
const now = Date.now();
401
return next.handle().pipe(
402
tap(response => {
403
const duration = Date.now() - now;
404
console.log(`gRPC response (${duration}ms):`, response);
405
})
406
);
407
}
408
}
409
```