@@ -27,8 +27,55 @@ interface CacheOptions {
27
27
}
28
28
29
29
/**
30
- * Iterates through the provided 'params' array and checks if any argument in 'args' at the specified 'index'
31
- * matches one of the pipe-separated values in 'value'. If a match is found, caching should be skipped.
30
+ * Uses a `CacheService` to attempt to retrieve a cached result before executing the original method. If
31
+ * no cached response exists, the method is executed and its result may be stored in the cache depending on configurable
32
+ * options. Caching can be conditionally skipped based on runtime arguments via `skipParams` (for positional args)
33
+ * and `skipNamedParams` (for object args).
34
+ *
35
+ * @param cacheService - The caching service used to store and retrieve cache entries.
36
+ * @param options - Optional configuration for caching behavior.
37
+ * @property skipParams - An array of rules for skipping caching based on specific argument values.
38
+ * @property skipNamedParams - An array of rules for skipping caching based on fields within argument objects.
39
+ * @property ttl - Optional time-to-live for the cache entry; falls back to global config if not provided.
40
+ *
41
+ * @returns A method decorator function that wraps the original method with caching logic.
42
+ *
43
+ * @example
44
+ * @cache (CacheService, { skipParams: [...], skipNamesParams: [...], ttl: 300 })
45
+ */
46
+ export function cache ( cacheService : CacheService , options : CacheOptions = { } ) {
47
+ return function ( target : any , context : ClassMethodDecoratorContext ) {
48
+ const methodName = String ( context . name ) ;
49
+
50
+ return async function ( this : any , ...args : unknown [ ] ) {
51
+ const requestDetails = extractRequestDetails ( args ) ;
52
+ const cacheKey = generateCacheKey ( methodName , args ) ;
53
+
54
+ const cachedResponse = await cacheService . getAsync ( cacheKey , methodName , requestDetails ) ;
55
+ if ( cachedResponse ) return cachedResponse ;
56
+
57
+ const result = await target . apply ( this , args ) ;
58
+ if (
59
+ result &&
60
+ ! shouldSkipCachingForSingleParams ( args , options . skipParams ) &&
61
+ ! shouldSkipCachingForNamedParams ( args , options . skipNamedParams )
62
+ ) {
63
+ await cacheService . set (
64
+ cacheKey ,
65
+ result ,
66
+ methodName ,
67
+ requestDetails ,
68
+ options . ttl ?? ConfigService . get ( 'CACHE_TTL' ) ,
69
+ ) ;
70
+ }
71
+ return result ;
72
+ } ;
73
+ } ;
74
+ }
75
+
76
+ /**
77
+ * This is a predicate function that takes a list of arguments and parameters,
78
+ * and it checks whether the given function should skip caching based on specific positional argument values.
32
79
*
33
80
* @param args - The arguments passed to the method in an array
34
81
* @param params - An array of CacheSingleParam caching rules
@@ -151,56 +198,6 @@ const extractRequestDetails = (args: unknown[]): RequestDetails => {
151
198
return new RequestDetails ( { requestId : '' , ipAddress : '' } ) ;
152
199
} ;
153
200
154
- /**
155
- * This decorator uses a `CacheService` to attempt to retrieve a cached result before executing the original method. If
156
- * no cached response exists, the method is executed and its result may be stored in the cache depending on configurable
157
- * options. Caching can be conditionally skipped based on runtime arguments via `skipParams` (for positional args)
158
- * and `skipNamedParams` (for object args).
159
- *
160
- * @param cacheService - The caching service used to store and retrieve cache entries.
161
- * @param options - Optional configuration for caching behavior.
162
- * @property skipParams - An array of rules for skipping caching based on specific argument values.
163
- * @property skipNamedParams - An array of rules for skipping caching based on fields within argument objects.
164
- * @property ttl - Optional time-to-live for the cache entry; falls back to global config if not provided.
165
- *
166
- * @returns A method decorator function that wraps the original method with caching logic.
167
- *
168
- * @example
169
- * @cache (CacheService, { skipParams: [...], skipNamesParams: [...], ttl: 300 })
170
- */
171
- export function cache ( cacheService : CacheService , options : CacheOptions = { } ) {
172
- return function ( _target : any , _propertyKey : string , descriptor : PropertyDescriptor ) {
173
- const method = descriptor . value ;
174
-
175
- descriptor . value = async function ( ...args : unknown [ ] ) {
176
- const requestDetails = extractRequestDetails ( args ) ;
177
- const cacheKey = generateCacheKey ( method . name , args ) ;
178
-
179
- const cachedResponse = await cacheService . getAsync ( cacheKey , method , requestDetails ) ;
180
- if ( cachedResponse ) {
181
- return cachedResponse ;
182
- }
183
-
184
- const result = await method . apply ( this , args ) ;
185
- if (
186
- result &&
187
- ! shouldSkipCachingForSingleParams ( args , options ?. skipParams ) &&
188
- ! shouldSkipCachingForNamedParams ( args , options ?. skipNamedParams )
189
- ) {
190
- await cacheService . set (
191
- cacheKey ,
192
- result ,
193
- method ,
194
- requestDetails ,
195
- options ?. ttl ?? ConfigService . get ( 'CACHE_TTL' ) ,
196
- ) ;
197
- }
198
-
199
- return result ;
200
- } ;
201
- } ;
202
- }
203
-
204
201
// export private methods under __test__ "namespace" but using const
205
202
// due to `ES2015 module syntax is preferred over namespaces` eslint warning
206
203
export const __test__ = {
0 commit comments