Skip to content

Commit

Permalink
feat: added caching for the jobs controller
Browse files Browse the repository at this point in the history
  • Loading branch information
JanssenBrm committed Dec 2, 2024
1 parent c081558 commit 0fa9858
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 1 deletion.
84 changes: 84 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
"dependencies": {
"@elastic/elasticsearch": "~7.12.0",
"@nestjs/axios": "^1.0.0",
"@nestjs/cache-manager": "^2.3.0",
"@nestjs/common": "^9.1.6",
"@nestjs/core": "^9.1.6",
"@nestjs/elasticsearch": "^9.0.0",
"@nestjs/passport": "^9.0.0",
"@nestjs/platform-express": "^9.1.6",
"@nestjs/swagger": "^6.1.2",
"@nestjs/terminus": "^9.1.4",
"cache-manager": "^5.7.6",
"class-transformer": "^0.5.1",
"class-validator": "^0.13.2",
"commit-analyzer-fail-on-no-release": "^1.0.1",
Expand Down
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { LoggerMiddleware } from './middleware/logger.middleware';
import { ConfigService } from './config/config/config.service';
import { LoggerModule } from 'nestjs-pino';
import { v4 as uuidv4 } from 'uuid';
import { CachingModule } from './caching/caching.module';

@Module({
imports: [
Expand Down Expand Up @@ -41,6 +42,7 @@ import { v4 as uuidv4 } from 'uuid';
};
},
}),
CachingModule,
],
})
export class AppModule implements NestModule {
Expand Down
22 changes: 22 additions & 0 deletions src/caching/caching.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Module } from '@nestjs/common';
import { CachingService } from './services/cache.service';
import { ConfigModule } from '../config/config.module';
import { ConfigService } from '../config/config/config.service';
import { CacheModule } from '@nestjs/cache-manager';

@Module({
imports: [
ConfigModule,
CacheModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
ttl: configService.get('cache.ttl'),
max: configService.get('cache.max'),
}),
inject: [ConfigService],
}),
],
providers: [CachingService],
exports: [CachingService],
})
export class CachingModule {}
46 changes: 46 additions & 0 deletions src/caching/services/cache.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Inject, Injectable, Logger } from '@nestjs/common';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';

@Injectable()
export class CachingService {
private logger = new Logger('CachingService');

constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

/**
* Retrieve an element from the cache. If the element could not be found or an error occured, it will return undefined.
* @param key - Key to use for storing the results
*/
public async checkCache<T>(key: string): Promise<T | undefined> {
try {
this.logger.debug(`Checking cache for key: ${key}`);
const result = await this.cacheManager.get<T>(key);
if (result) {
this.logger.debug(`Found result in cache`);
} else {
this.logger.warn('Could not find entry in cache');
}
return result;
} catch (error) {
this.logger.error(`Could not query cache: ${JSON.stringify(error)}`);
return undefined;
}
}

/**
* Store a result into the cache of the application
* @param key - Key used to store the value in the cache.
* @param value - Value to store in the cache.
*/
public async store(key: string, value: any) {
try {
this.logger.debug(`Storing body cache for key: ${key}`);
await this.cacheManager.set(key, value);
} catch (error) {
this.logger.error(
`Could not store value in cache cache: ${JSON.stringify(error)}`,
);
}
}
}
16 changes: 16 additions & 0 deletions src/config/schema/config.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,20 @@ export const schema: convict.Schema<AppConfig> = {
arg: 'db_jobs_scroll_timeout',
},
},
cache: {
ttl: {
doc: 'TTL in miliseconds for caching the results',
format: 'Number',
default: 5000,
env: 'CACHE_TTL',
arg: 'cache_ttl',
},
max: {
doc: 'Maximum number of results to store in cache',
format: 'Number',
default: 100,
env: 'CACHE_MAX_ENTRIES',
arg: 'cache_max_entries',
},
},
};
12 changes: 11 additions & 1 deletion src/jobs/controllers/jobs/jobs.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import {
import { ApiBody, ApiOperation } from '@nestjs/swagger';
import { Job, PatchJob } from '../../models/job.dto';
import { DatabaseService } from '../../services/database/database.service';
import { CachingService } from '../../../caching/services/cache.service';

@Controller('jobs')
export class JobsController {
constructor(
private databaseService: DatabaseService,
private cachingService: CachingService,
private logger: Logger,
) {}

Expand Down Expand Up @@ -47,7 +49,15 @@ export class JobsController {
})
async queryJobs(@Body() query: any): Promise<Job[]> {
try {
return (await this.databaseService.queryJobs(query)) as Job[];
const cacheKey = `search_result_${btoa(JSON.stringify(query))}`;
let result: Job[] = await this.cachingService.checkCache<Job[]>(cacheKey);

if (!result) {
result = (await this.databaseService.queryJobs(query)) as Job[];
await this.cachingService.store(cacheKey, result);
}

return result;
} catch (error: any) {
this.logger.error(
`Could not query jobs: ${JSON.stringify(error)}`,
Expand Down
2 changes: 2 additions & 0 deletions src/jobs/jobs.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import { ElasticsearchModule } from '@nestjs/elasticsearch';
import { ConfigModule } from '../config/config.module';
import { ConfigService } from '../config/config/config.service';
import { DatabaseService } from './services/database/database.service';
import { CachingModule } from '../caching/caching.module';

@Module({
controllers: [JobsController],
imports: [
ConfigModule,
CachingModule,
ElasticsearchModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
Expand Down

0 comments on commit 0fa9858

Please sign in to comment.