Skip to content

Commit 8d41eda

Browse files
committed
GRPC Server namespaces support added for loaded proto descriptors
- Recursive scan of descriptors object - Service names with namespaces concatenated with dot-syntax
1 parent ef2147d commit 8d41eda

1 file changed

Lines changed: 72 additions & 5 deletions

File tree

packages/microservices/server/server-grpc.ts

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,33 @@ export class ServerGrpc extends Server implements CustomTransportStrategy {
5555
this.logger.error(invalidPackageError.message, invalidPackageError.stack);
5656
throw invalidPackageError;
5757
}
58-
for (const name of this.getServiceNames(grpcPkg)) {
58+
// Take all of the services defined in grpcPkg and assign them to
59+
// method handlers defined in Controllers
60+
for (const definition of this.getServiceNames(grpcPkg)) {
5961
this.grpcClient.addService(
60-
grpcPkg[name].service,
61-
await this.createService(grpcPkg[name], name),
62+
// First parameter requires exact service definition from proto
63+
definition.service.service,
64+
// Here full proto definition required along with namespaced pattern name
65+
await this.createService(definition.service, definition.name)
6266
);
6367
}
6468
}
6569

66-
public getServiceNames(grpcPkg: any) {
67-
return Object.keys(grpcPkg).filter(name => grpcPkg[name].service);
70+
/**
71+
* Will return all of the services along with their fully namespaced
72+
* names as an array of objects.
73+
*
74+
* This method initiates recursive scan of grpcPkg object
75+
*
76+
* @param grpcPkg
77+
*/
78+
public getServiceNames(grpcPkg: any): {name: string, service: any}[] {
79+
const keys = Object.keys(grpcPkg);
80+
// Define accumulator to collect all of the services available to load
81+
const services: {name: string, service: any}[] = [];
82+
// Initiate recursive services collector starting with empty name
83+
this._getServiceNamesCollector('', grpcPkg, services);
84+
return services;
6885
}
6986

7087
public async createService(grpcService: any, name: string) {
@@ -177,4 +194,54 @@ export class ServerGrpc extends Server implements CustomTransportStrategy {
177194
throw invalidProtoError;
178195
}
179196
}
197+
198+
/**
199+
* Recursively fetch all of the service methods available on loaded
200+
* protobuf descriptor object, and collect those as an objects with
201+
* dot-syntax full-path names.
202+
*
203+
* Example:
204+
* for proto package Bundle.FirstService with service Events { rpc...
205+
* will be resolved to object of (while loaded for Bundle package):
206+
* {
207+
* name: "FirstService.Events",
208+
* service: {Object}
209+
* }
210+
*
211+
* @param name
212+
* @param grpcDefinition
213+
* @param accumulator
214+
* @private
215+
*/
216+
private _getServiceNamesCollector(name, grpcDefinition, accumulator) {
217+
// Confirm that next definition to unwrap is an object
218+
if (typeof grpcDefinition !== 'object')
219+
// Exit for non objects
220+
return;
221+
// Collect keys for traverse
222+
const keys = Object.keys(grpcDefinition);
223+
// Traverse definitions or namespace extensions
224+
for (const key of keys) {
225+
// Define name extension variable
226+
let nameExtended = '';
227+
// If depth is zero then just add key
228+
if (name.length === 0)
229+
nameExtended = key;
230+
// If depth non-zero then add next through dot syntax
231+
else
232+
nameExtended = name + '.' + key;
233+
// Take nested object
234+
const nested = grpcDefinition[key];
235+
// Check if it's in depth with service definition
236+
if (nested.hasOwnProperty('service')) {
237+
// Add new service object to accumulator
238+
accumulator.push({
239+
name: nameExtended,
240+
service: nested
241+
});
242+
} else
243+
// Continue recursion until objects end or service definition found
244+
this._getServiceNamesCollector(nameExtended, nested, accumulator);
245+
}
246+
}
180247
}

0 commit comments

Comments
 (0)