Skip to content

Commit 80eb038

Browse files
Merge branch 'cache-ttl-decorate' of https://github.com/joeyslack/nest into joeyslack-cache-ttl-decorate
2 parents e0e19a2 + ddcee87 commit 80eb038

6 files changed

Lines changed: 236 additions & 4 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export const CACHE_MANAGER = 'CACHE_MANAGER';
22
export const CACHE_MODULE_OPTIONS = 'CACHE_MODULE_OPTIONS';
33
export const CACHE_KEY_METADATA = 'cache_module:cache_key';
4+
export const CACHE_TTL_METADATA = 5;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { SetMetadata } from '../../decorators';
2+
import { CACHE_TTL_METADATA } from '../cache.constants';
3+
4+
/**
5+
* Decorator that sets the cache ttl setting the duration for cache expiration.
6+
*
7+
* For example: `@CacheTTL(5)`
8+
*
9+
* @param ttl number set the cache expiration time
10+
*
11+
* @see [Caching](https://docs.nestjs.com/techniques/caching)
12+
*
13+
* @publicApi
14+
*/
15+
export const CacheTTL = (ttl: number) => SetMetadata(CACHE_TTL_METADATA, ttl);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './cache-key.decorator';
2+
export * from './cache-ttl.decorator';

packages/common/cache/interceptors/cache.interceptor.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
HttpServer,
88
NestInterceptor,
99
} from '../../interfaces';
10-
import { CACHE_KEY_METADATA, CACHE_MANAGER } from '../cache.constants';
10+
import { CACHE_KEY_METADATA, CACHE_TTL_METADATA, CACHE_MANAGER } from '../cache.constants';
1111

1212
const HTTP_ADAPTER_HOST = 'HttpAdapterHost';
1313
const REFLECTOR = 'Reflector';
@@ -32,6 +32,8 @@ export class CacheInterceptor implements NestInterceptor {
3232
next: CallHandler,
3333
): Promise<Observable<any>> {
3434
const key = this.trackBy(context);
35+
const ttl = this.reflector.get(CACHE_TTL_METADATA, context.getHandler()) || null;
36+
3537
if (!key) {
3638
return next.handle();
3739
}
@@ -40,9 +42,13 @@ export class CacheInterceptor implements NestInterceptor {
4042
if (value) {
4143
return of(value);
4244
}
45+
4346
return next
4447
.handle()
45-
.pipe(tap(response => this.cacheManager.set(key, response)));
48+
.pipe(tap(response => {
49+
const args = ttl ? [key, response, {ttl}] : [key, response];
50+
this.cacheManager.set.apply(this.cacheManager, args);
51+
}));
4652
} catch {
4753
return next.handle();
4854
}
@@ -51,10 +57,12 @@ export class CacheInterceptor implements NestInterceptor {
5157
trackBy(context: ExecutionContext): string | undefined {
5258
const httpAdapter = this.httpAdapterHost.httpAdapter;
5359
const isHttpApp = httpAdapter && !!httpAdapter.getRequestMethod;
60+
const cacheMetadata = this.reflector.get(CACHE_KEY_METADATA, context.getHandler());
5461

55-
if (!isHttpApp) {
56-
return this.reflector.get(CACHE_KEY_METADATA, context.getHandler());
62+
if (!isHttpApp || cacheMetadata) {
63+
return cacheMetadata;
5764
}
65+
5866
const request = context.getArgByIndex(0);
5967
if (httpAdapter.getRequestMethod(request) !== 'GET') {
6068
return undefined;

packages/common/package-lock.json

Lines changed: 171 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { expect } from 'chai';
2+
import { CacheKey, CacheInterceptor, CacheTTL } from '../../cache';
3+
import { CACHE_KEY_METADATA, CACHE_TTL_METADATA } from '../../cache/cache.constants';
4+
import { UseInterceptors } from '../../decorators';
5+
import { Controller } from '../../decorators/core/controller.decorator';
6+
7+
describe('@Cache', () => {
8+
@Controller('test')
9+
@CacheKey('/a_different_cache_key')
10+
@CacheTTL(99999)
11+
@UseInterceptors(CacheInterceptor)
12+
class TestAll {}
13+
14+
@Controller()
15+
@UseInterceptors(CacheInterceptor)
16+
@CacheKey('/a_different_cache_key')
17+
class TestKey {}
18+
19+
@Controller()
20+
@UseInterceptors(CacheInterceptor)
21+
@CacheTTL(99999)
22+
class TestTTL {}
23+
24+
it('should override global defaults for CacheKey and CacheTTL', () => {
25+
expect(Reflect.getMetadata(CACHE_KEY_METADATA, TestAll)).to.be.eql('/a_different_cache_key') &&
26+
expect(Reflect.getMetadata(CACHE_TTL_METADATA, TestAll)).to.be.greaterThan(9999);
27+
});
28+
29+
it('should override only the TTL', () => {
30+
expect(Reflect.getMetadata(CACHE_TTL_METADATA, TestTTL)).to.be.greaterThan(9999);
31+
});
32+
33+
it('should override only the Key', () => {
34+
expect(Reflect.getMetadata(CACHE_KEY_METADATA, TestKey)).to.be.eql('/a_different_cache_key');
35+
});
36+
});

0 commit comments

Comments
 (0)