diff --git a/README.md b/README.md index 7d655f8..171ee81 100644 --- a/README.md +++ b/README.md @@ -210,6 +210,15 @@ If the matching is successful, you will get a result, containing : - _INTERMEDIATE_ for a driver intermediate point - _NEUTRAL_ for a passenger point from the point of view of a driver +### Results caching + +Matching is a time-consuming process, so the results of a matching request are stored in cache before being paginated and returned to the requester. +An id is attributed to the overall results of a request : on further requests (for example to query for different pages of results), the requester can provide this id and get in return the cached data, avoiding another longer process of computing the results from scratch. Obviously, new computing must be done periodically to get fresh new results ! + +There's also a basic cache to store the results of the _same_ request sent multiple times successively. + +Cache TTLs are customizable in the `.env` file. + ## Tests / ESLint / Prettier Tests are run outside the container for ease of use (switching between different environments inside containers using prisma is complicated and error prone). diff --git a/package-lock.json b/package-lock.json index ce905e2..c8682bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "@nestjs/terminus": "^9.2.2", "@prisma/client": "^4.13.0", "axios": "^1.3.5", - "cache-manager": "^5.2.0", + "cache-manager": "^5.2.3", "cache-manager-ioredis-yet": "^1.1.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", @@ -1584,7 +1584,8 @@ }, "node_modules/@nestjs/cache-manager": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-1.0.0.tgz", + "integrity": "sha512-XMNdgsj3H+Ng/SYwFl13vRGNFA3e5Obk8LNwIuHLVSocnK2exReAWtscxEjQhoBc4FW4jAYOgU/U+mt18Q9T0g==", "peerDependencies": { "@nestjs/common": "^9.0.0", "cache-manager": "<=5", @@ -3385,7 +3386,8 @@ }, "node_modules/cache-manager": { "version": "5.2.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-5.2.3.tgz", + "integrity": "sha512-9OErI8fksFkxAMJ8Mco0aiZSdphyd90HcKiOMJQncSlU1yq/9lHHxrT8PDayxrmr9IIIZPOAEfXuGSD7g29uog==", "dependencies": { "lodash.clonedeep": "^4.5.0", "lru-cache": "^9.1.2" diff --git a/package.json b/package.json index 32d120f..0e8aa84 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@nestjs/terminus": "^9.2.2", "@prisma/client": "^4.13.0", "axios": "^1.3.5", - "cache-manager": "^5.2.0", + "cache-manager": "^5.2.3", "cache-manager-ioredis-yet": "^1.1.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", diff --git a/src/modules/ad/ad.module.ts b/src/modules/ad/ad.module.ts index 3756e70..93a9072 100644 --- a/src/modules/ad/ad.module.ts +++ b/src/modules/ad/ad.module.ts @@ -35,6 +35,27 @@ import { MatchMapper } from './match.mapper'; import { OutputDateTimeTransformer } from './infrastructure/output-datetime-transformer'; import { MatchingRepository } from './infrastructure/matching.repository'; import { MatchingMapper } from './matching.mapper'; +import { CacheModule } from '@nestjs/cache-manager'; +import { RedisClientOptions } from '@liaoliaots/nestjs-redis'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import { redisStore } from 'cache-manager-ioredis-yet'; + +const imports = [ + CqrsModule, + CacheModule.registerAsync({ + imports: [ConfigModule], + useFactory: async (configService: ConfigService) => ({ + store: await redisStore({ + host: configService.get('REDIS_HOST'), + port: configService.get('REDIS_PORT'), + password: configService.get('REDIS_PASSWORD'), + ttl: configService.get('CACHE_TTL'), + }), + }), + inject: [ConfigService], + }), + GeographyModule, +]; const grpcControllers = [MatchGrpcController]; @@ -106,7 +127,7 @@ const adapters: Provider[] = [ ]; @Module({ - imports: [CqrsModule, GeographyModule], + imports, controllers: [...grpcControllers], providers: [ ...messageHandlers, diff --git a/src/modules/ad/interface/grpc-controllers/match.grpc-controller.ts b/src/modules/ad/interface/grpc-controllers/match.grpc-controller.ts index 930eaa9..a6bf5af 100644 --- a/src/modules/ad/interface/grpc-controllers/match.grpc-controller.ts +++ b/src/modules/ad/interface/grpc-controllers/match.grpc-controller.ts @@ -1,4 +1,4 @@ -import { Controller, Inject, UsePipes } from '@nestjs/common'; +import { Controller, Inject, UseInterceptors, UsePipes } from '@nestjs/common'; import { GrpcMethod, RpcException } from '@nestjs/microservices'; import { RpcValidationPipe } from '@mobicoop/ddd-library'; import { RpcExceptionCode } from '@mobicoop/ddd-library'; @@ -11,6 +11,7 @@ import { AD_ROUTE_PROVIDER } from '@modules/ad/ad.di-tokens'; import { RouteProviderPort } from '@modules/ad/core/application/ports/route-provider.port'; import { MatchMapper } from '@modules/ad/match.mapper'; import { MatchingResult } from '@modules/ad/core/application/queries/match/match.query-handler'; +import { CacheInterceptor, CacheKey } from '@nestjs/cache-manager'; @UsePipes( new RpcValidationPipe({ @@ -27,6 +28,8 @@ export class MatchGrpcController { private readonly matchMapper: MatchMapper, ) {} + @CacheKey('MatcherServiceMatch') + @UseInterceptors(CacheInterceptor) @GrpcMethod('MatcherService', 'Match') async match(data: MatchRequestDto): Promise { try { diff --git a/src/modules/ad/tests/unit/interface/match.grpc.controller.spec.ts b/src/modules/ad/tests/unit/interface/match.grpc.controller.spec.ts index a138f04..7739a25 100644 --- a/src/modules/ad/tests/unit/interface/match.grpc.controller.spec.ts +++ b/src/modules/ad/tests/unit/interface/match.grpc.controller.spec.ts @@ -13,6 +13,7 @@ import { MatchRequestDto } from '@modules/ad/interface/grpc-controllers/dtos/mat import { WaypointDto } from '@modules/ad/interface/grpc-controllers/dtos/waypoint.dto'; import { MatchGrpcController } from '@modules/ad/interface/grpc-controllers/match.grpc-controller'; import { MatchMapper } from '@modules/ad/match.mapper'; +import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { QueryBus } from '@nestjs/cqrs'; import { RpcException } from '@nestjs/microservices'; import { Test, TestingModule } from '@nestjs/testing'; @@ -316,6 +317,10 @@ describe('Match Grpc Controller', () => { provide: MatchMapper, useValue: mockMatchMapper, }, + { + provide: CACHE_MANAGER, + useValue: {}, + }, ], }).compile();