Skip to content

Commit 5a0c02d

Browse files
authored
fix: CustomCacheInterceptor not returning cached value (#43)
* fix: cache interceptor not returning cached value * fix: use ctx.getArgs() for GraphQL resolver args * refactor: change getOrSetCache to use positional params
1 parent 706927d commit 5a0c02d

2 files changed

Lines changed: 54 additions & 38 deletions

File tree

src/cache/custom-cache.interceptor.ts

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
import { Reflector } from '@nestjs/core';
88
import { GqlExecutionContext } from '@nestjs/graphql';
99

10-
import { Observable, lastValueFrom } from 'rxjs';
10+
import { Observable, from, of, switchMap, tap } from 'rxjs';
1111

1212
import { CUSTOM_CACHE, CustomCacheOptions } from './custom-cache.decorator';
1313
import { CustomCacheService } from './custom-cache.service';
@@ -19,10 +19,7 @@ export class CustomCacheInterceptor implements NestInterceptor {
1919
private readonly reflector: Reflector,
2020
) {}
2121

22-
async intercept(
23-
context: ExecutionContext,
24-
next: CallHandler,
25-
): Promise<Observable<any>> {
22+
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
2623
const handler = context.getHandler();
2724
const options = this.reflector.get<CustomCacheOptions>(
2825
CUSTOM_CACHE,
@@ -33,24 +30,31 @@ export class CustomCacheInterceptor implements NestInterceptor {
3330
return next.handle();
3431
}
3532

36-
const args = this.getArgs(context);
37-
33+
const { key, ttl, logger } = options;
3834
const customKey = `${context.getClass().name}.${handler.name}`;
39-
const result = async () => await lastValueFrom(next.handle());
40-
41-
await this.customCacheService.setCache({
42-
options,
35+
const args = this.getArgs(context);
36+
const cacheKey = this.customCacheService.buildCacheKey(
37+
key ?? customKey,
4338
args,
44-
result,
45-
customKey,
46-
});
39+
);
4740

48-
return next.handle();
41+
return from(this.customCacheService.getCache(cacheKey, logger)).pipe(
42+
switchMap((cached) =>
43+
cached !== undefined
44+
? of(cached)
45+
: next
46+
.handle()
47+
.pipe(
48+
tap((data) =>
49+
this.customCacheService.setCache(cacheKey, data, ttl, logger),
50+
),
51+
),
52+
),
53+
);
4954
}
5055

5156
private getArgs(context: ExecutionContext): unknown[] {
5257
const ctx = GqlExecutionContext.create(context);
53-
const req = ctx.getContext().req;
54-
return req.body;
58+
return Object.values(ctx.getArgs());
5559
}
5660
}

src/cache/custom-cache.service.ts

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export class CustomCacheService {
4444
const methodOverride = async (...args: unknown[]) => {
4545
const result = async () => await methodRef.apply(instance, args);
4646

47-
return this.setCache({ customKey, options, result, args });
47+
return this.getOrSetCache(customKey, args, options, result);
4848
};
4949

5050
Object.defineProperty(instance, methodName, {
@@ -53,32 +53,44 @@ export class CustomCacheService {
5353
};
5454
}
5555

56-
async setCache({
57-
options,
58-
args,
59-
result: _result,
60-
customKey,
61-
}: {
62-
options: CustomCacheOptions;
63-
args: unknown[];
64-
result: () => Promise<unknown>;
65-
customKey: string;
66-
}) {
67-
const { key: cacheKey = customKey, ttl = Infinity, logger } = options;
56+
async getCache(key: string, logger?: CustomCacheOptions['logger']) {
57+
const cached = await this.cacheManager.get(key);
58+
if (cached !== undefined) {
59+
logger?.('Cache Hit', { cacheKey: key });
60+
}
61+
return cached;
62+
}
63+
64+
async setCache(
65+
key: string,
66+
data: unknown,
67+
ttl: number = Infinity,
68+
logger?: CustomCacheOptions['logger'],
69+
) {
70+
await this.cacheManager.set(key, data, ttl);
71+
logger?.('Cached', { cacheKey: key });
72+
}
6873

69-
const argsAddedKey = cacheKey + JSON.stringify(args);
74+
buildCacheKey(customKey: string, args: unknown[]) {
75+
return customKey + JSON.stringify(args);
76+
}
7077

71-
const cachedValue = await this.cacheManager.get(argsAddedKey);
72-
if (Boolean(cachedValue)) {
73-
logger?.('Cache Hit', { cacheKey });
78+
async getOrSetCache(
79+
customKey: string,
80+
args: unknown[],
81+
options: CustomCacheOptions,
82+
resultFn: () => Promise<unknown>,
83+
) {
84+
const { key: cacheKey = customKey, ttl = Infinity, logger } = options;
85+
const argsAddedKey = this.buildCacheKey(cacheKey, args);
7486

87+
const cachedValue = await this.getCache(argsAddedKey, logger);
88+
if (cachedValue !== undefined) {
7589
return cachedValue;
7690
}
7791

78-
const result = await _result();
79-
80-
await this.cacheManager.set(argsAddedKey, result, ttl);
81-
logger?.('Cached', { cacheKey });
92+
const result = await resultFn();
93+
await this.setCache(argsAddedKey, result, ttl, logger);
8294

8395
return result;
8496
}

0 commit comments

Comments
 (0)