From 5dc0da0aa6fd36758a5878ba64d5b96c1acca382 Mon Sep 17 00:00:00 2001 From: Anas Abbal Date: Sun, 7 Jul 2024 19:42:35 +0100 Subject: [PATCH] feat: Implement caching in DriverService for optimized data retrieval --- apps/driver/src/driver.controller.ts | 1 - apps/driver/src/driver.module.ts | 5 ++++ apps/driver/src/driver.service.ts | 36 ++++++++++++++++++++++++---- apps/user/src/user.module.ts | 5 ++++ apps/user/src/user.service.ts | 27 ++++++++++++++++++--- apps/user/test/app.e2e-spec.ts | 2 ++ 6 files changed, 68 insertions(+), 8 deletions(-) diff --git a/apps/driver/src/driver.controller.ts b/apps/driver/src/driver.controller.ts index 37d5476..aaf4699 100644 --- a/apps/driver/src/driver.controller.ts +++ b/apps/driver/src/driver.controller.ts @@ -1,7 +1,6 @@ import { Controller, Get } from '@nestjs/common'; import { DriverService } from './driver.service'; import { MessagePattern } from '@nestjs/microservices'; -import { DriverDto } from '@app/shared/events/driver/driver.dto'; import { Driver } from './models/driver.entity'; @Controller('drivers') diff --git a/apps/driver/src/driver.module.ts b/apps/driver/src/driver.module.ts index 026c45b..0730461 100644 --- a/apps/driver/src/driver.module.ts +++ b/apps/driver/src/driver.module.ts @@ -5,6 +5,7 @@ import { DriverService } from './driver.service'; import * as dotenv from 'dotenv'; import { TypeOrmModule } from '@nestjs/typeorm'; import { Driver } from './models/driver.entity'; +import { CacheModule } from '@nestjs/cache-manager'; dotenv.config(); @@ -17,6 +18,10 @@ dotenv.config(); process.env.DATABASE_NAME, process.env.DATABASE_TYPE as 'mongodb' | 'postgres' ), + CacheModule.register({ + ttl: 60, // seconds + max: 100, // maximum number of items in cache + }), ], controllers: [DriverController], providers: [DriverService], diff --git a/apps/driver/src/driver.service.ts b/apps/driver/src/driver.service.ts index 5c8204d..54a0464 100644 --- a/apps/driver/src/driver.service.ts +++ b/apps/driver/src/driver.service.ts @@ -1,8 +1,10 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { Inject, Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { DriverStatus } from './enums/driver.status'; import { Driver } from './models/driver.entity'; +import { CACHE_MANAGER } from '@nestjs/cache-manager'; +import { Cache } from 'cache-manager'; @@ -13,7 +15,9 @@ export class DriverService { constructor( @InjectRepository(Driver) - private readonly driverRepository: Repository + private readonly driverRepository: Repository, + @Inject(CACHE_MANAGER) + private readonly cacheManager: Cache, ) {} async createDriver(userId: string): Promise { @@ -34,8 +38,21 @@ export class DriverService { } async findAllDrivers(): Promise { + this.logger.log('Begin fetching all drivers'); + + const cacheKey = 'all-drivers'; + const cachedDrivers = await this.cacheManager.get(cacheKey); + + if (cachedDrivers) { + this.logger.log('Drivers fetched from cache'); + return cachedDrivers; + } + try { - return await this.driverRepository.find(); + const drivers = await this.driverRepository.find(); + await this.cacheManager.set(cacheKey, drivers, 600 ); // cache for 10 minutes + this.logger.log('Drivers fetched from database and cached'); + return drivers; } catch (error) { this.logger.error(`Error while fetching drivers from database: ${error.message}`); throw error; @@ -43,6 +60,16 @@ export class DriverService { } async findAllSortedByStatus(): Promise { + this.logger.log('Begin fetching and sorting all drivers by status'); + + const cacheKey = 'all-drivers-sorted-by-status'; + const cachedSortedDrivers = await this.cacheManager.get(cacheKey); + + if (cachedSortedDrivers) { + this.logger.log('Sorted drivers fetched from cache'); + return cachedSortedDrivers; + } + try { const drivers = await this.findAllDrivers(); const order = [ @@ -52,7 +79,8 @@ export class DriverService { DriverStatus.THREE_SET_AVAILABLE, ]; const sortedDrivers = this.sortDriversByStatus(drivers, order); - + await this.cacheManager.set(cacheKey, sortedDrivers, 600 ); // cache for 10 minutes + this.logger.log('Sorted drivers fetched from database and cached'); return sortedDrivers; } catch (error) { this.logger.error(`Error while fetching and sorting drivers: ${error.message}`); diff --git a/apps/user/src/user.module.ts b/apps/user/src/user.module.ts index e471dc9..ac7d60f 100644 --- a/apps/user/src/user.module.ts +++ b/apps/user/src/user.module.ts @@ -9,6 +9,7 @@ import { UserType } from './model/user.type'; import { UserTypeController } from './services/user.type.controller'; import { UserTypeService } from './services/user.type.service'; import { ClientsModule, Transport } from '@nestjs/microservices'; +import { CacheModule } from '@nestjs/cache-manager'; dotenv.config(); @@ -34,6 +35,10 @@ dotenv.config(); }, }, ]), + CacheModule.register({ + ttl: 60, // seconds + max: 100, // maximum number of items in cache + }), ], controllers: [UserController, UserTypeController], providers: [UserService, UserTypeService] diff --git a/apps/user/src/user.service.ts b/apps/user/src/user.service.ts index c63fd2a..96de411 100644 --- a/apps/user/src/user.service.ts +++ b/apps/user/src/user.service.ts @@ -1,6 +1,7 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { Inject, Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { User } from './model/user.entity'; +import { Cache } from 'cache-manager'; import { Repository } from 'typeorm'; import { ExceptionPayloadFactory } from '@app/shared/exception/exception.payload.factory'; import { throwException } from '@app/shared/exception/exception.util'; @@ -8,6 +9,7 @@ import { UserCreateCommand } from '@app/shared/commands/auth/user.create.cmd'; import { hashPassword } from '@app/shared/utils/hash.pass'; import { validateCommand } from '@app/shared/utils/validate'; import { ClientProxy, ClientProxyFactory, Transport } from '@nestjs/microservices'; +import { CACHE_MANAGER } from '@nestjs/cache-manager'; @@ -20,6 +22,8 @@ export class UserService { constructor( @InjectRepository(User) private readonly userRepository: Repository, + @Inject(CACHE_MANAGER) + private cacheManager: Cache, ) { this.driverServiceClient = ClientProxyFactory.create({ transport: Transport.TCP, // Choose your transport protocol @@ -76,24 +80,41 @@ export class UserService { } async findUserById(id: string): Promise { this.logger.log(`Begin fetching user with id ${id}`); + + const cachedUser = await this.cacheManager.get(`user-${id}`); + if (cachedUser) { + this.logger.log(`User fetched from cache with id ${id}`); + return cachedUser; + } + const user = await this.userRepository.findOne({ where: {id}}); - if(!user){ + if (!user) { this.logger.error(`User with id ${id} not found`); throwException(ExceptionPayloadFactory.USER_NAME_NOT_FOUND); } + this.logger.log(`User fetched successfully with id ${id}`); + await this.cacheManager.set(`user-${id}`, user, 600); // cache for 10 minutes return user; } async getAll(): Promise { this.logger.log(`Begin fetching users`); + + const cachedUsers = await this.cacheManager.get('all-users'); + if (cachedUsers) { + this.logger.log(`Users fetched from cache`); + return cachedUsers; + } + try { const users = await this.userRepository.find(); this.logger.log(`Fetched users: ${JSON.stringify(users)}`); + await this.cacheManager.set('all-users', users, 600 ); // cache for 10 minutes return users; } catch (error) { this.logger.error('Error fetching all users:', error.message); throw error; } } -} +} \ No newline at end of file diff --git a/apps/user/test/app.e2e-spec.ts b/apps/user/test/app.e2e-spec.ts index 8b872b2..a70f9da 100644 --- a/apps/user/test/app.e2e-spec.ts +++ b/apps/user/test/app.e2e-spec.ts @@ -3,6 +3,8 @@ import { INestApplication } from '@nestjs/common'; import * as request from 'supertest'; import { UserModule } from './../src/user.module'; + + describe('UserController (e2e)', () => { let app: INestApplication;