-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcache.decorator.ts
More file actions
89 lines (76 loc) · 2.48 KB
/
Copy pathcache.decorator.ts
File metadata and controls
89 lines (76 loc) · 2.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import { JSONStringifyKeyStrategy } from '../strategy/key/json.stringify.strategy.js';
import { IAsyncKeyStrategy } from '../types/key.strategy.types.js';
import {
IAsynchronousCacheType,
ISynchronousCacheType,
ICacheOptions
} from '../types/cache.types.js';
const defaultKeyStrategy = new JSONStringifyKeyStrategy();
export function Cache(
cachingStrategy: IAsynchronousCacheType | ISynchronousCacheType,
options?: ICacheOptions,
keyStrategy: IAsyncKeyStrategy = defaultKeyStrategy
) {
return function (
// eslint-disable-next-line @typescript-eslint/ban-types
target: Object & {
__cache_decarator_pending_results?: {
[key: string]: Promise<unknown> | undefined;
};
},
methodName: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
const className = target.constructor.name;
descriptor.value = async function (...args: unknown[]) {
const cacheKey = await keyStrategy.getKey(className, methodName, args);
const runMethod = async () => {
const methodCall = originalMethod.apply(this, args);
let methodResult;
const isAsync =
methodCall?.constructor?.name === 'AsyncFunction' ||
methodCall?.constructor?.name === 'Promise';
if (isAsync) {
methodResult = await methodCall;
} else {
methodResult = methodCall;
}
return methodResult;
};
if (!cacheKey || process.env.DISABLE_CACHE_DECORATOR) {
// do not cache this function, execute function
return runMethod();
}
if (!target.__cache_decarator_pending_results) {
target.__cache_decarator_pending_results = {};
}
if (!target.__cache_decarator_pending_results[cacheKey]) {
target.__cache_decarator_pending_results[cacheKey] = (async () => {
try {
try {
const entry = await cachingStrategy.getItem<unknown>(cacheKey);
if (entry !== undefined) {
return entry;
}
} catch (err) {
console.warn('@hokify/node-ts-cache: reading cache failed', cacheKey, err);
}
const methodResult = await runMethod();
try {
await cachingStrategy.setItem(cacheKey, methodResult, options);
} catch (err) {
console.warn('@hokify/node-ts-cache: writing result to cache failed', cacheKey, err);
}
return methodResult;
} finally {
// reset pending result object
target.__cache_decarator_pending_results![cacheKey] = undefined;
}
})();
}
return target.__cache_decarator_pending_results[cacheKey];
};
return descriptor;
};
}