Skip to content

Commit

Permalink
Merge pull request #11131 from Flusinerd/cache-ttl-bug
Browse files Browse the repository at this point in the history
fix(common): fix cache ttl not beeing respected
  • Loading branch information
kamilmysliwiec authored Mar 15, 2023
2 parents 77ee77a + ee11bea commit 7fb37bd
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 3 deletions.
35 changes: 35 additions & 0 deletions integration/cache/e2e/custom-ttl.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { CustomTtlModule } from '../src/custom-ttl/custom-ttl.module';

describe('Caching Custom TTL', () => {
let server;
let app: INestApplication;

beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [CustomTtlModule],
}).compile();

app = module.createNestApplication();
server = app.getHttpServer();
await app.init();
});

it('should return a differnt value after the TTL is elapsed', async () => {
await request(server).get('/').expect(200, '0');
await new Promise(resolve => setTimeout(resolve, 500));
await request(server).get('/').expect(200, '1');
});

it('should return the cached value within the TTL', async () => {
await request(server).get('/').expect(200, '0');
await new Promise(resolve => setTimeout(resolve, 200));
await request(server).get('/').expect(200, '0');
});

afterEach(async () => {
await app.close();
});
});
20 changes: 20 additions & 0 deletions integration/cache/src/custom-ttl/custom-ttl.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {
CacheInterceptor,
CacheTTL,
Controller,
Get,
UseInterceptors,
} from '@nestjs/common';

@Controller()
export class CustomTtlController {
counter = 0;
constructor() {}

@Get()
@CacheTTL(500)
@UseInterceptors(CacheInterceptor)
getNumber() {
return this.counter++;
}
}
8 changes: 8 additions & 0 deletions integration/cache/src/custom-ttl/custom-ttl.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { CacheModule, Module } from '@nestjs/common';
import { CustomTtlController } from './custom-ttl.controller';

@Module({
imports: [CacheModule.register()],
controllers: [CustomTtlController],
})
export class CustomTtlModule {}
40 changes: 40 additions & 0 deletions integration/cache/src/custom-ttl/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"compilerOptions": {
"module": "commonjs",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es6",
"sourceMap": true,
"allowJs": true,
"outDir": "./dist",
"paths": {
"@nestjs/common": ["../../packages/common"],
"@nestjs/common/*": ["../../packages/common/*"],
"@nestjs/core": ["../../packages/core"],
"@nestjs/core/*": ["../../packages/core/*"],
"@nestjs/microservices": ["../../packages/microservices"],
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],
"@nestjs/platform-socket.io/*": ["../../packages/platform-socket.io/*"],
"@nestjs/platform-ws": ["../../packages/platform-ws"],
"@nestjs/platform-ws/*": ["../../packages/platform-ws/*"]
}
},
"include": [
"src/**/*",
"e2e/**/*"
],
"exclude": [
"node_modules",
]
}
23 changes: 20 additions & 3 deletions packages/common/cache/interceptors/cache.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
NestInterceptor,
} from '../../interfaces';
import { Logger } from '../../services/logger.service';
import { isFunction, isNil } from '../../utils/shared.utils';
import { loadPackage } from '../../utils/load-package.util';
import { isFunction, isNil, isNumber } from '../../utils/shared.utils';
import {
CACHE_KEY_METADATA,
CACHE_MANAGER,
Expand All @@ -35,10 +36,22 @@ export class CacheInterceptor implements NestInterceptor {
protected readonly httpAdapterHost: HttpAdapterHost;

protected allowedMethods = ['GET'];

private cacheManagerIsv5OrGreater: boolean;

constructor(
@Inject(CACHE_MANAGER) protected readonly cacheManager: any,
@Inject(REFLECTOR) protected readonly reflector: any,
) {}
) {
// We need to check if the cache-manager package is v5 or greater
// because the set method signature changed in v5
const cacheManagerPackage = loadPackage(
'cache-manager',
'CacheModule',
() => require('cache-manager'),
);
this.cacheManagerIsv5OrGreater = 'memoryStore' in cacheManagerPackage;
}

async intercept(
context: ExecutionContext,
Expand All @@ -59,13 +72,17 @@ export class CacheInterceptor implements NestInterceptor {
const ttl = isFunction(ttlValueOrFactory)
? await ttlValueOrFactory(context)
: ttlValueOrFactory;

return next.handle().pipe(
tap(async response => {
if (response instanceof StreamableFile) {
return;
}

const args = isNil(ttl) ? [key, response] : [key, response, { ttl }];
const args = [key, response];
if (!isNil(ttl)) {
args.push(this.cacheManagerIsv5OrGreater ? ttl : { ttl });
}

try {
await this.cacheManager.set(...args);
Expand Down

0 comments on commit 7fb37bd

Please sign in to comment.