@moveaxlab/nestjs-grpc-client
v10.1.0
Published
 [](https://www.npmjs.com/package/@moveaxlab/nestjs-grpc-client) 
export class PackageDataLoaderProvider extends GrpcDataLoaderProvider<PackageClient> {
client: PackageClient;
logger = new Logger(PackageDataLoaderProvider.name);
createMetadata(_: Request): Metadata {
const metadata = new Metadata();
// you can use the Express' request token to authenticate also the gRPC call
metadata.set('authorization', req.get('authorization'));
return metadata;
}
get cacheConfig() {
return {
someMethod: {
cacheKeyFn: (request: grpcPkg.ISomeMethodRequest) => {
return `pkgService.someMethod:${input.param1}-${input.param2}`;
},
ttl: 60,
},
};
}
}
export const PackageService = createDataLoaderDecorator(PackageDataLoaderProvider.prototype);
export type PackageDataloader = DataLoaderForClient<PackageClient>;- The
cacheConfiggetter returns an object containing cache configuration for the various methods. If a method needs to be cached, thecacheConfigmust contain an entry for that method that takes in input the method request and returns a string, which will be used as the cache key. A TTL can be specified, that will be used if global caching is enabled (see below). - The
PackageServiceis an object containing a parameter decorator for each method of the gRPC client. You can use the decorator in your resolvers to obtain an instance of the dataloader (see below). - The
PackageDataloaderis a type containing the types of each method dataloader. You can use the type in your resolvers to add type safety to your loaders.
Add the GrpcDataLoaderInterceptor to your app in order to load dataloaders relevant for the request at runtime:
import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { GrpcDataLoaderInterceptor } from '@moveax/nestjs-grpc-client';
@Module({
provides: [
{
provide: APP_INTERCEPTOR,
useClass: GrpcDataLoaderInterceptor,
}
],
/* ... */
})
export class AppModule {}Now you can use the dataloader in your resolvers:
// imports omitted for lack of will
@Resolver()
class Whatever {
@Query()
async getWhatever(
@PackageService.someMethod() loader: PackageDataloader['someMethod']
) {
const response = await loader.load(/* gRPC request */);
// do whatever you want with the response now
}
}Batching requests
To batch several requests to a given service when doing API composition,
specify the mergeConfig inside your dataloader provider.
The mergeConfig provides two properties for each endpoint:
mergeInput, that takes an array of requests and combines them to a single requestsplitOutput, that takes the original array of requests and a single response, and splits it into an array of responses
Global caching
To use global caching, pass true to the loader decorator:
// imports omitted for lack of will
@Resolver()
class Whatever {
@Query()
async getWhatever(
@PackageService.someMethod(true) loader: PackageDataloader['someMethod']
) {
const response = await loader.load(/* gRPC request */);
// do whatever you want with the response now
}
}The ttl must be set to something greater than 0 inside the cacheConfig
for the dataloader, for global caching to work. The TTL is expressed in seconds.
All requests to that specific dataloader will be cached for ttl seconds,
in a cache shared between all calls. Use global caching with care: the global cache will skip all authorization logic
that may live inside your backend services.
