Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement caching for user data in UserService and UserController #12

Merged
merged 2 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions apps/auth/src/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Controller, Get } from '@nestjs/common';
import { Body, Controller, Get } from '@nestjs/common';
import { AuthService } from './auth.service';
import { MessagePattern } from '@nestjs/microservices';
import { UserCreateCommand } from '@app/shared/commands/auth/user.create.cmd';

@Controller()
export class AuthController {
constructor(private readonly authService: AuthService) {}

@Get()
getHello(): string {
return this.authService.getHello();
@MessagePattern('register-auth')
async register(@Body() command: UserCreateCommand): Promise<any> {
return this.authService.register(command);
}
}
28 changes: 27 additions & 1 deletion apps/auth/src/auth.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,35 @@
import { Module } from '@nestjs/common';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { PassportModule } from '@nestjs/passport';
import { JwtModule } from '@nestjs/jwt';
import * as dotenv from 'dotenv';
import { ClientsModule, Transport } from '@nestjs/microservices';


dotenv.config();

@Module({
imports: [],
imports: [
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.register({
secret: process.env.JWT_SECRET,
signOptions: { expiresIn: '1h' },
}),
ClientsModule.register([
{
name: 'USER_SERVICE',
transport: Transport.RMQ,
options: {
urls: ['amqp://localhost:5672'],
queue: 'user_queue',
queueOptions: {
durable: false,
},
},
},
]),
],
controllers: [AuthController],
providers: [AuthService],
})
Expand Down
29 changes: 27 additions & 2 deletions apps/auth/src/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
import { UserCreateCommand } from '@app/shared/commands/auth/user.create.cmd';
import { IResponse } from '@app/shared/interfaces/response.interface';
import { validateCommand } from '@app/shared/utils/validate';
import { BadRequestException, Injectable } from '@nestjs/common';
import { BadRequestException, Inject, Injectable, Logger } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { ClientProxy } from '@nestjs/microservices';
import { firstValueFrom } from 'rxjs';

@Injectable()
export class AuthService {

private readonly logger = new Logger(AuthService.name);

constructor(
private readonly jwtService: JwtService,
@Inject('USER_SERVICE') private client: ClientProxy
){}

async register(command: UserCreateCommand): Promise<any> {
const user = await firstValueFrom(this.client.send({ cmd: 'createUser' }, command));
if(user)
return user;
return null;
}
async login(user: any) {
this.logger.log(`Generating JWT token for user: ${user.email}`);
const payload = { email: user.email, sub: user.id };
const token = this.jwtService.sign(payload);
this.logger.log(`JWT token generated successfully for user: ${user.email}`);
return {
access_token: token,
email: user.email
};
}
}
24 changes: 23 additions & 1 deletion apps/gateway/src/gateway.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { DriversController } from './rest/driver.controller';
import { UserService } from './services/user-service';
import { DriverService } from './services/driver-service';
import { AuthService } from './services/auth.service';
import { CacheInterceptor, CacheModule } from '@nestjs/cache-manager';
import { APP_INTERCEPTOR } from '@nestjs/core';

@Module({
imports: [
Expand All @@ -34,7 +36,19 @@ import { AuthService } from './services/auth.service';
port: 3002, // port of user-service
},
},
{
name: 'AUTH_SERVICE',
transport: Transport.TCP,
options: {
host: 'localhost',
port: 3005, // port of user-service
},
},
]),
CacheModule.register({
ttl: 5, // seconds
max: 100, // maximum number of items in cache
}),
WinstonModule.forRoot({
transports: [
new winston.transports.Console({
Expand All @@ -47,6 +61,14 @@ import { AuthService } from './services/auth.service';
}),
],
controllers: [AuthController, UserController, DriversController],
providers: [UserService, DriverService, AuthService]
providers: [
UserService,
DriverService,
AuthService,
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor,
},
],
})
export class GatewayModule {}
11 changes: 8 additions & 3 deletions apps/gateway/src/rest/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@ import { ResponseSuccess } from '@app/shared/dto/response.dto';



@Controller()
@Controller('auth')
export class AuthController {
/*constructor(private readonly authService: AuthService) {}
constructor(private readonly authService: AuthService) {}


@Post('register/:userTypeId')

@Post('register')
async REGISTER(@Body() command: any) : Promise<any>{
return this.authService.auth(command);
}
/*@Post('register/:userTypeId')
async register(@Body() createUserDto: UserCreateCommand | DriverCreateCmd,
@Param('userTypeId') userTypeId: string
) {
Expand Down
9 changes: 7 additions & 2 deletions apps/gateway/src/rest/user.controller.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
import { Body, Controller, Get, Param, Post } from '@nestjs/common';
import { Body, Controller, Get, Param, Post, UseInterceptors } from '@nestjs/common';
import { UserCreateCommand } from '@app/shared/commands/auth/user.create.cmd';
import { UserService } from '../services/user-service';
import { CacheInterceptor, CacheKey, CacheTTL } from '@nestjs/cache-manager';



@Controller('user')
@UseInterceptors(CacheInterceptor)
export class UserController {

constructor(private readonly userService: UserService) {}

@Get(':id')
@CacheKey('findUserById')
@CacheTTL(10) // cache for 10 seconds
async findUserById(@Param('id') id: string): Promise<any> {
return this.userService.findUserById(id);
}

@Get()
@CacheKey('getAllUsers')
@CacheTTL(30) // cache for 30 seconds
async getAllUsers(): Promise<any[]> {
return this.userService.getAllUsers();
}

// Example of handling a POST request to create a user
@Post()
async createUser(@Body() command: UserCreateCommand): Promise<any> {
return this.userService.createUser(command);
Expand Down
12 changes: 8 additions & 4 deletions apps/gateway/src/services/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import { DriverService } from "./driver-service";

@Injectable()
export class AuthService {
/*constructor(
constructor(
@Inject('USER_SERVICE') private readonly userClient: ClientProxy,
private readonly userService: UserService,
private readonly driverService: DriverService
private readonly driverService: DriverService,
@Inject('AUTH_SERVICE') private readonly authClient: ClientProxy
){}

async register(userTypeId: string, command: UserCreateCommand | DriverCreateCmd): Promise<string> {
/*async register(userTypeId: string, command: UserCreateCommand | DriverCreateCmd): Promise<string> {
try {
const userType = await this.userService.findUserTypeById(userTypeId);
console.log(`User type with id ${userType.id} found`);
Expand All @@ -39,8 +40,11 @@ export class AuthService {
throw new InternalServerErrorException('Failed to register user');
}
}
}*/
async auth(command: UserCreateCommand) : Promise<any> {
return await this.authClient.send({cmd: 'register-auth'}, command).toPromise();
}
async login(loginUserDto: any): Promise<any> {
/*async login(loginUserDto: any): Promise<any> {
try {
const result = await this.userClient.send({ cmd: 'login' }, loginUserDto).toPromise();
return result;
Expand Down
19 changes: 18 additions & 1 deletion apps/gateway/src/services/user-service.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { Injectable, Inject } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { Cache } from 'cache-manager';
import { UserCreateCommand } from '@app/shared/commands/auth/user.create.cmd'; // Adjust import path as needed
import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';
import { Logger } from 'winston';
import { CACHE_MANAGER } from '@nestjs/cache-manager';

@Injectable()
export class UserService {

constructor(
@Inject('USER_SERVICE') private readonly userClient: ClientProxy,
@Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: Logger,
@Inject(CACHE_MANAGER) private cacheManager: Cache
) {}

async createUser(command: UserCreateCommand): Promise<any> {
Expand All @@ -25,8 +28,15 @@ export class UserService {

async findUserById(id: string): Promise<any> {
try {
const cachedUser = await this.cacheManager.get(`user-${id}`);
if (cachedUser) {
this.logger.info(`Found user with id ${id} in cache`);
return cachedUser;
}

const result = await this.userClient.send({ cmd: 'findUserById' }, id).toPromise();
this.logger.info(`Found user with id ${id}`);
await this.cacheManager.set(`user-${id}`, result, 300); // Cache for 5 minutes
return result;
} catch (error) {
this.logger.error(`Error finding user with id ${id}: ${error.message}`);
Expand All @@ -36,12 +46,19 @@ export class UserService {

async getAllUsers(): Promise<any[]> {
try {
const cachedUsers = await this.cacheManager.get<any[]>('all-users');
if (cachedUsers) {
this.logger.info(`Fetched all users from cache`);
return cachedUsers;
}

const result = await this.userClient.send({ cmd: 'getAllUsers' }, {}).toPromise();
this.logger.info(`Fetched all users, count: ${result.length}`);
await this.cacheManager.set('all-users', result, 300); // Cache for 5 minutes
return result;
} catch (error) {
this.logger.error(`Error fetching all users: ${error.message}`);
throw error;
}
}
}
}
14 changes: 14 additions & 0 deletions apps/user/src/user.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { User } from './model/user.entity';
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';

dotenv.config();

Expand All @@ -20,6 +21,19 @@ dotenv.config();
process.env.DATABASE_NAME,
process.env.DATABASE_TYPE as 'mongodb' | 'postgres'
),
ClientsModule.register([
{
name: 'AUTH_SERVICE',
transport: Transport.RMQ,
options: {
urls: ['amqp://localhost:5672'],
queue: 'auth_queue',
queueOptions: {
durable: false,
},
},
},
]),
],
controllers: [UserController, UserTypeController],
providers: [UserService, UserTypeService]
Expand Down
Loading
Loading