@midwayjs/cache-manager 3.14.0 → 3.14.4-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ /**
2
+ * fork from https://github.com/node-cache-manager/node-cache-manager/tree/master
3
+ * reason: Support node.js v18 version below and add some features
4
+ * for example: add methodWrap
5
+ */
6
+ import { Cache, Config, FactoryConfig, FactoryStore, MemoryCache, MemoryConfig, MemoryStore, MultiCache, Store } from './types';
7
+ export declare function caching(name: 'memory', args?: MemoryConfig): Promise<MemoryCache>;
8
+ export declare function caching<S extends Store>(store: S): Promise<Cache<S>>;
9
+ export declare function caching<S extends Store, T extends object = never>(factory: FactoryStore<S, T>, args?: FactoryConfig<T>): Promise<Cache<S>>;
10
+ export declare function createCache(store: MemoryStore, args?: MemoryConfig): MemoryCache;
11
+ export declare function createCache(store: Store, args?: Config): Cache<Store>;
12
+ /**
13
+ * Module that lets you specify a hierarchy of caches.
14
+ */
15
+ export declare function multiCaching<Caches extends Cache[]>(caches: Caches): MultiCache;
16
+ //# sourceMappingURL=cacheManager.d.ts.map
@@ -0,0 +1,197 @@
1
+ "use strict";
2
+ /**
3
+ * fork from https://github.com/node-cache-manager/node-cache-manager/tree/master
4
+ * reason: Support node.js v18 version below and add some features
5
+ * for example: add methodWrap
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.multiCaching = exports.createCache = exports.caching = void 0;
9
+ const prmoiseCoalesce_1 = require("./prmoiseCoalesce");
10
+ const store_1 = require("./store");
11
+ /**
12
+ * Generic caching interface that wraps any caching library with a compatible interface.
13
+ */
14
+ async function caching(factory, args) {
15
+ if (factory === 'memory') {
16
+ const store = (0, store_1.memoryStore)(args);
17
+ return createCache(store, args);
18
+ }
19
+ if (typeof factory === 'function') {
20
+ const store = await factory(args);
21
+ return createCache(store, args);
22
+ }
23
+ return createCache(factory, args);
24
+ }
25
+ exports.caching = caching;
26
+ /**
27
+ * Create cache instance by store (non-async).
28
+ */
29
+ function createCache(store, args) {
30
+ return {
31
+ /**
32
+ * Wraps a function in cache. I.e., the first time the function is run,
33
+ * its results are stored in cache so subsequent calls retrieve from cache
34
+ * instead of calling the function.
35
+
36
+ * @example
37
+ * const result = await cache.wrap('key', () => Promise.resolve(1));
38
+ *
39
+ */
40
+ wrap: async (key, fn, ttl) => {
41
+ return (0, prmoiseCoalesce_1.coalesceAsync)(key, async () => {
42
+ const value = await store.get(key);
43
+ if (value === undefined) {
44
+ const result = await fn();
45
+ const cacheTTL = typeof ttl === 'function' ? ttl(result) : ttl;
46
+ await store.set(key, result, cacheTTL);
47
+ return result;
48
+ }
49
+ else if (args === null || args === void 0 ? void 0 : args.refreshThreshold) {
50
+ const cacheTTL = typeof ttl === 'function' ? ttl(value) : ttl;
51
+ const remainingTtl = await store.ttl(key);
52
+ if (remainingTtl !== -1 && remainingTtl < args.refreshThreshold) {
53
+ (0, prmoiseCoalesce_1.coalesceAsync)(`+++${key}`, fn).then(result => store.set(key, result, cacheTTL));
54
+ }
55
+ }
56
+ return value;
57
+ });
58
+ },
59
+ store: store,
60
+ del: (key) => store.del(key),
61
+ get: (key) => store.get(key),
62
+ set: (key, value, ttl) => store.set(key, value, ttl),
63
+ reset: () => store.reset(),
64
+ /**
65
+ * cache function with args
66
+ */
67
+ methodWrap: async (key, fn, fnArgs, ttl) => {
68
+ return (0, prmoiseCoalesce_1.coalesceAsync)(key, async () => {
69
+ const value = await store.get(key);
70
+ if (value === undefined) {
71
+ const result = await fn(...fnArgs);
72
+ const cacheTTL = typeof ttl === 'function' ? ttl(result) : ttl;
73
+ await store.set(key, result, cacheTTL);
74
+ return result;
75
+ }
76
+ else if (args === null || args === void 0 ? void 0 : args.refreshThreshold) {
77
+ const cacheTTL = typeof ttl === 'function' ? ttl(value) : ttl;
78
+ const remainingTtl = await store.ttl(key);
79
+ if (remainingTtl !== -1 && remainingTtl < args.refreshThreshold) {
80
+ // fn(...fnArgs).then(result => store.set(key, result, cacheTTL));
81
+ (0, prmoiseCoalesce_1.coalesceAsync)(`+++${key}`, () => fn(...fnArgs)).then(result => store.set(key, result, cacheTTL));
82
+ }
83
+ }
84
+ return value;
85
+ });
86
+ },
87
+ };
88
+ }
89
+ exports.createCache = createCache;
90
+ /**
91
+ * Module that lets you specify a hierarchy of caches.
92
+ */
93
+ function multiCaching(caches) {
94
+ const get = async (key) => {
95
+ for (const cache of caches) {
96
+ try {
97
+ const val = await cache.get(key);
98
+ if (val !== undefined)
99
+ return val;
100
+ }
101
+ catch (e) {
102
+ // ignore
103
+ }
104
+ }
105
+ };
106
+ const set = async (key, data, ttl) => {
107
+ await Promise.all(caches.map(cache => cache.set(key, data, ttl)));
108
+ };
109
+ return {
110
+ get,
111
+ set,
112
+ del: async (key) => {
113
+ await Promise.all(caches.map(cache => cache.del(key)));
114
+ },
115
+ async wrap(key, fn, ttl) {
116
+ let value;
117
+ let i = 0;
118
+ for (; i < caches.length; i++) {
119
+ try {
120
+ value = await caches[i].get(key);
121
+ if (value !== undefined)
122
+ break;
123
+ }
124
+ catch (e) {
125
+ // ignore
126
+ }
127
+ }
128
+ if (value === undefined) {
129
+ const result = await fn();
130
+ const cacheTTL = typeof ttl === 'function' ? ttl(result) : ttl;
131
+ await set(key, result, cacheTTL);
132
+ return result;
133
+ }
134
+ else {
135
+ const cacheTTL = typeof ttl === 'function' ? ttl(value) : ttl;
136
+ Promise.all(caches.slice(0, i).map(cache => cache.set(key, value, cacheTTL))).then();
137
+ caches[i].wrap(key, fn, ttl).then(); // call wrap for store for internal refreshThreshold logic, see: src/caching.ts caching.wrap
138
+ }
139
+ return value;
140
+ },
141
+ reset: async () => {
142
+ await Promise.all(caches.map(x => x.reset()));
143
+ },
144
+ mget: async (...keys) => {
145
+ const values = new Array(keys.length).fill(undefined);
146
+ for (const cache of caches) {
147
+ if (values.every(x => x !== undefined))
148
+ break;
149
+ try {
150
+ const val = await cache.store.mget(...keys);
151
+ val.forEach((v, i) => {
152
+ if (values[i] === undefined && v !== undefined)
153
+ values[i] = v;
154
+ });
155
+ }
156
+ catch (e) {
157
+ // ignore
158
+ }
159
+ }
160
+ return values;
161
+ },
162
+ mset: async (args, ttl) => {
163
+ await Promise.all(caches.map(cache => cache.store.mset(args, ttl)));
164
+ },
165
+ mdel: async (...keys) => {
166
+ await Promise.all(caches.map(cache => cache.store.mdel(...keys)));
167
+ },
168
+ methodWrap: async (key, fn, fnArgs, ttl) => {
169
+ let value;
170
+ let i = 0;
171
+ for (; i < caches.length; i++) {
172
+ try {
173
+ value = await caches[i].get(key);
174
+ if (value !== undefined)
175
+ break;
176
+ }
177
+ catch (e) {
178
+ // ignore
179
+ }
180
+ }
181
+ if (value === undefined) {
182
+ const result = await fn(...fnArgs);
183
+ const cacheTTL = typeof ttl === 'function' ? ttl(result) : ttl;
184
+ await set(key, result, cacheTTL);
185
+ return result;
186
+ }
187
+ else {
188
+ const cacheTTL = typeof ttl === 'function' ? ttl(value) : ttl;
189
+ Promise.all(caches.slice(0, i).map(cache => cache.set(key, value, cacheTTL))).then();
190
+ caches[i].methodWrap(key, fn, fnArgs, ttl).then(); // call wrap for store for internal refreshThreshold logic, see: src/caching.ts caching.wrap
191
+ }
192
+ return value;
193
+ },
194
+ };
195
+ }
196
+ exports.multiCaching = multiCaching;
197
+ //# sourceMappingURL=cacheManager.js.map
@@ -0,0 +1,4 @@
1
+ export * from './cacheManager';
2
+ export * from './store';
3
+ export * from './types';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./cacheManager"), exports);
18
+ __exportStar(require("./store"), exports);
19
+ __exportStar(require("./types"), exports);
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Enqueue a promise for the group identified by `key`.
3
+ *
4
+ * All requests received for the same key while a request for that key
5
+ * is already being executed will wait. Once the running request settles
6
+ * then all the waiting requests in the group will settle, too.
7
+ * This minimizes how many times the function itself runs at the same time.
8
+ * This function resolves or rejects according to the given function argument.
9
+ */
10
+ export declare function coalesceAsync<T>(
11
+ /**
12
+ * Any identifier to group requests together.
13
+ */
14
+ key: string,
15
+ /**
16
+ * The function to run.
17
+ */
18
+ fn: () => T | PromiseLike<T>): Promise<T>;
19
+ //# sourceMappingURL=prmoiseCoalesce.d.ts.map
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.coalesceAsync = void 0;
4
+ const callbacks = new Map();
5
+ /**
6
+ * Enqueue a promise for the group identified by `key`.
7
+ *
8
+ * All requests received for the same key while a request for that key
9
+ * is already being executed will wait. Once the running request settles
10
+ * then all the waiting requests in the group will settle, too.
11
+ * This minimizes how many times the function itself runs at the same time.
12
+ * This function resolves or rejects according to the given function argument.
13
+ */
14
+ async function coalesceAsync(
15
+ /**
16
+ * Any identifier to group requests together.
17
+ */
18
+ key,
19
+ /**
20
+ * The function to run.
21
+ */
22
+ fn) {
23
+ if (!hasKey(key)) {
24
+ addKey(key);
25
+ try {
26
+ const result = await Promise.resolve(fn());
27
+ coalesce({ key, result });
28
+ return result;
29
+ }
30
+ catch (error) {
31
+ coalesce({ key, error });
32
+ throw error;
33
+ }
34
+ }
35
+ return enqueue(key);
36
+ }
37
+ exports.coalesceAsync = coalesceAsync;
38
+ function hasKey(key) {
39
+ return callbacks.has(key);
40
+ }
41
+ function addKey(key) {
42
+ callbacks.set(key, []);
43
+ }
44
+ function removeKey(key) {
45
+ callbacks.delete(key);
46
+ }
47
+ function addCallbackToKey(key, callback) {
48
+ const stash = getCallbacksByKey(key);
49
+ stash.push(callback);
50
+ callbacks.set(key, stash);
51
+ }
52
+ function getCallbacksByKey(key) {
53
+ var _a;
54
+ return (_a = callbacks.get(key)) !== null && _a !== void 0 ? _a : [];
55
+ }
56
+ function enqueue(key) {
57
+ return new Promise((resolve, reject) => {
58
+ const callback = { resolve, reject };
59
+ addCallbackToKey(key, callback);
60
+ });
61
+ }
62
+ function dequeue(key) {
63
+ const stash = getCallbacksByKey(key);
64
+ removeKey(key);
65
+ return stash;
66
+ }
67
+ function coalesce(options) {
68
+ const { key, error, result } = options;
69
+ dequeue(key).forEach(callback => {
70
+ if (error) {
71
+ callback.reject(error);
72
+ }
73
+ else {
74
+ callback.resolve(result);
75
+ }
76
+ });
77
+ }
78
+ //# sourceMappingURL=prmoiseCoalesce.js.map
@@ -0,0 +1,6 @@
1
+ import { MemoryConfig, MemoryStore } from './types';
2
+ /**
3
+ * Wrapper for lru-cache.
4
+ */
5
+ export declare function memoryStore(args?: MemoryConfig): MemoryStore;
6
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.memoryStore = void 0;
4
+ const LRUCache = require("lru-cache");
5
+ const cloneDeep = require("lodash.clonedeep");
6
+ function clone(object) {
7
+ if (typeof object === 'object' && object !== null) {
8
+ return cloneDeep(object);
9
+ }
10
+ return object;
11
+ }
12
+ /**
13
+ * Wrapper for lru-cache.
14
+ */
15
+ function memoryStore(args) {
16
+ var _a;
17
+ const shouldCloneBeforeSet = (args === null || args === void 0 ? void 0 : args.shouldCloneBeforeSet) !== false; // clone by default
18
+ const isCacheable = (_a = args === null || args === void 0 ? void 0 : args.isCacheable) !== null && _a !== void 0 ? _a : (val => val !== undefined);
19
+ const lruOpts = {
20
+ ttlAutopurge: true,
21
+ ...args,
22
+ max: (args === null || args === void 0 ? void 0 : args.max) || 500,
23
+ ttl: (args === null || args === void 0 ? void 0 : args.ttl) !== undefined ? args.ttl : 0,
24
+ };
25
+ const lruCache = new LRUCache(lruOpts);
26
+ return {
27
+ async del(key) {
28
+ lruCache.delete(key);
29
+ },
30
+ get: async (key) => lruCache.get(key),
31
+ keys: async () => [...lruCache.keys()],
32
+ mget: async (...args) => args.map(x => lruCache.get(x)),
33
+ async mset(args, ttl) {
34
+ const opt = { ttl: ttl !== undefined ? ttl : lruOpts.ttl };
35
+ for (const [key, value] of args) {
36
+ if (!isCacheable(value))
37
+ throw new Error(`no cacheable value ${JSON.stringify(value)}`);
38
+ if (shouldCloneBeforeSet)
39
+ lruCache.set(key, clone(value), opt);
40
+ else
41
+ lruCache.set(key, value, opt);
42
+ }
43
+ },
44
+ async mdel(...args) {
45
+ for (const key of args)
46
+ lruCache.delete(key);
47
+ },
48
+ async reset() {
49
+ lruCache.clear();
50
+ },
51
+ ttl: async (key) => lruCache.getRemainingTTL(key),
52
+ async set(key, value, opt) {
53
+ if (!isCacheable(value))
54
+ throw new Error(`no cacheable value ${JSON.stringify(value)}`);
55
+ if (shouldCloneBeforeSet)
56
+ value = clone(value);
57
+ const ttl = opt !== undefined ? opt : lruOpts.ttl;
58
+ lruCache.set(key, value, { ttl });
59
+ },
60
+ get calculatedSize() {
61
+ return lruCache.calculatedSize;
62
+ },
63
+ /**
64
+ * This method is not available in the caching modules.
65
+ */
66
+ get size() {
67
+ return lruCache.size;
68
+ },
69
+ /**
70
+ * This method is not available in the caching modules.
71
+ */
72
+ dump: () => lruCache.dump(),
73
+ /**
74
+ * This method is not available in the caching modules.
75
+ */
76
+ load: (...args) => lruCache.load(...args),
77
+ };
78
+ }
79
+ exports.memoryStore = memoryStore;
80
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1,51 @@
1
+ import * as LRUCache from 'lru-cache';
2
+ export type MultiCache = Omit<Cache, 'store'> & Pick<Cache['store'], 'mset' | 'mget' | 'mdel'>;
3
+ export type Config = {
4
+ ttl?: Milliseconds;
5
+ refreshThreshold?: Milliseconds;
6
+ isCacheable?: (val: unknown) => boolean;
7
+ };
8
+ export type Milliseconds = number;
9
+ export type Store = {
10
+ get<T>(key: string): Promise<T | undefined>;
11
+ set<T>(key: string, data: T, ttl?: Milliseconds): Promise<void>;
12
+ del(key: string): Promise<void>;
13
+ reset(): Promise<void>;
14
+ mset(args: [string, unknown][], ttl?: Milliseconds): Promise<void>;
15
+ mget(...args: string[]): Promise<unknown[]>;
16
+ mdel(...args: string[]): Promise<void>;
17
+ keys(pattern?: string): Promise<string[]>;
18
+ ttl(key: string): Promise<number>;
19
+ };
20
+ export type StoreConfig = Config;
21
+ export type FactoryConfig<T> = T & Config;
22
+ export type FactoryStore<S extends Store, T extends object = never> = (config?: FactoryConfig<T>) => S | Promise<S>;
23
+ export type Stores<S extends Store, T extends object> = 'memory' | Store | FactoryStore<S, T>;
24
+ export type CachingConfig<T> = MemoryConfig | StoreConfig | FactoryConfig<T>;
25
+ export type WrapTTL<T> = Milliseconds | ((v: T) => Milliseconds);
26
+ export type Cache<S extends Store = Store> = {
27
+ set: (key: string, value: unknown, ttl?: Milliseconds) => Promise<void>;
28
+ get: <T>(key: string) => Promise<T | undefined>;
29
+ del: (key: string) => Promise<void>;
30
+ reset: () => Promise<void>;
31
+ wrap<T>(key: string, fn: () => Promise<T>, ttl?: WrapTTL<T>): Promise<T>;
32
+ methodWrap<T>(key: string, fn: (...args: any[]) => Promise<T>, fnArgs: any[], ttl?: WrapTTL<T>): Promise<T>;
33
+ store: S;
34
+ };
35
+ export type LRU = LRUCache<string, any>;
36
+ type Pre = LRUCache.LimitedByTTL;
37
+ type Options = Omit<Pre, 'ttlAutopurge'> & Partial<Pick<Pre, 'ttlAutopurge'>>;
38
+ export type MemoryConfig = {
39
+ max?: number;
40
+ sizeCalculation?: (value: unknown, key: string) => number;
41
+ shouldCloneBeforeSet?: boolean;
42
+ } & Options & Config;
43
+ export type MemoryStore = Store & {
44
+ get size(): number;
45
+ dump: LRU['dump'];
46
+ load: LRU['load'];
47
+ calculatedSize: LRU['calculatedSize'];
48
+ };
49
+ export type MemoryCache = Cache<MemoryStore>;
50
+ export {};
51
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
package/dist/factory.d.ts CHANGED
@@ -1,13 +1,10 @@
1
1
  import { IMidwayContainer, ServiceFactory, ServiceFactoryConfigOption } from '@midwayjs/core';
2
- import { CachingConfig } from 'cache-manager';
3
2
  import { CacheManagerOptions, MidwayCache, MidwayMultiCache, MidwayUnionCache } from './interface';
4
3
  export declare class CachingFactory extends ServiceFactory<MidwayUnionCache> {
5
4
  protected cacheManagerConfig: ServiceFactoryConfigOption<CacheManagerOptions>;
6
5
  protected applicationContext: IMidwayContainer;
7
6
  protected init(): Promise<void>;
8
7
  protected createClient(config: CacheManagerOptions<any>, clientName: string): Promise<void | MidwayUnionCache>;
9
- wrapCaching(cacheInstance: MidwayCache, cachingArgs?: CachingConfig<any>): MidwayCache;
10
- wrapMultiCaching(cacheInstance: MidwayMultiCache, caches: MidwayCache[]): MidwayMultiCache;
11
8
  getName(): string;
12
9
  getCaching(cacheKey: string): MidwayCache;
13
10
  getMultiCaching(cacheKey: string): MidwayMultiCache;
package/dist/factory.js CHANGED
@@ -11,8 +11,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.CachingFactory = void 0;
13
13
  const core_1 = require("@midwayjs/core");
14
- const cache_manager_1 = require("cache-manager");
15
- const promise_coalesce_1 = require("promise-coalesce");
14
+ const base_1 = require("./base");
16
15
  let CachingFactory = class CachingFactory extends core_1.ServiceFactory {
17
16
  async init() {
18
17
  await this.initClients(this.cacheManagerConfig);
@@ -42,14 +41,13 @@ let CachingFactory = class CachingFactory extends core_1.ServiceFactory {
42
41
  if (!storeConfig.store) {
43
42
  throw new core_1.MidwayCommonError(`cache instance "${clientName}" store is undefined, please check your configuration.`);
44
43
  }
45
- newFactory.push(await (0, cache_manager_1.caching)(storeConfig.store, storeConfig['options']));
44
+ newFactory.push(await (0, base_1.caching)(storeConfig.store, storeConfig['options']));
46
45
  }
47
46
  else {
48
47
  throw new core_1.MidwayCommonError('invalid cache config');
49
48
  }
50
49
  }
51
- const cacheInstance = await (0, cache_manager_1.multiCaching)(newFactory);
52
- return this.wrapMultiCaching(cacheInstance, newFactory);
50
+ return await (0, base_1.multiCaching)(newFactory);
53
51
  }
54
52
  else {
55
53
  // single cache
@@ -59,70 +57,9 @@ let CachingFactory = class CachingFactory extends core_1.ServiceFactory {
59
57
  if (!config.store) {
60
58
  throw new core_1.MidwayCommonError(`cache instance "${clientName}" store is undefined, please check your configuration.`);
61
59
  }
62
- const cacheInstance = await (0, cache_manager_1.caching)(config.store, config['options']);
63
- return this.wrapCaching(cacheInstance, config['options']);
60
+ return await (0, base_1.caching)(config.store, config['options']);
64
61
  }
65
62
  }
66
- wrapCaching(cacheInstance, cachingArgs) {
67
- if (cacheInstance.methodWrap) {
68
- return cacheInstance;
69
- }
70
- cacheInstance.methodWrap = async (key, fn, fnArgs, ttl) => {
71
- const store = cacheInstance.store;
72
- return (0, promise_coalesce_1.coalesceAsync)(key, async () => {
73
- const value = await store.get(key);
74
- if (value === undefined) {
75
- const result = await fn(...fnArgs);
76
- const cacheTTL = typeof ttl === 'function' ? ttl(result) : ttl;
77
- await store.set(key, result, cacheTTL);
78
- return result;
79
- }
80
- else if (cachingArgs === null || cachingArgs === void 0 ? void 0 : cachingArgs.refreshThreshold) {
81
- const cacheTTL = typeof ttl === 'function' ? ttl(value) : ttl;
82
- const remainingTtl = await store.ttl(key);
83
- if (remainingTtl !== -1 &&
84
- remainingTtl < cachingArgs.refreshThreshold) {
85
- // fn(...fnArgs).then(result => store.set(key, result, cacheTTL));
86
- (0, promise_coalesce_1.coalesceAsync)(`+++${key}`, () => fn(...fnArgs)).then(result => store.set(key, result, cacheTTL));
87
- }
88
- }
89
- return value;
90
- });
91
- };
92
- return cacheInstance;
93
- }
94
- wrapMultiCaching(cacheInstance, caches) {
95
- if (cacheInstance.methodWrap) {
96
- return cacheInstance;
97
- }
98
- cacheInstance.methodWrap = async (key, fn, fnArgs, ttl) => {
99
- let value;
100
- let i = 0;
101
- for (; i < caches.length; i++) {
102
- try {
103
- value = await caches[i].get(key);
104
- if (value !== undefined)
105
- break;
106
- }
107
- catch (e) {
108
- // ignore
109
- }
110
- }
111
- if (value === undefined) {
112
- const result = await fn(...fnArgs);
113
- const cacheTTL = typeof ttl === 'function' ? ttl(result) : ttl;
114
- await cacheInstance.set(key, result, cacheTTL);
115
- return result;
116
- }
117
- else {
118
- const cacheTTL = typeof ttl === 'function' ? ttl(value) : ttl;
119
- Promise.all(caches.slice(0, i).map(cache => cache.set(key, value, cacheTTL))).then();
120
- caches[i].methodWrap(key, fn, fnArgs, ttl).then(); // call wrap for store for internal refreshThreshold logic, see: src/caching.ts caching.wrap
121
- }
122
- return value;
123
- };
124
- return cacheInstance;
125
- }
126
63
  getName() {
127
64
  return 'cache-manager';
128
65
  }
package/dist/index.d.ts CHANGED
@@ -2,5 +2,6 @@ export { CacheConfiguration as Configuration, getClassMethodDefaultCacheKey, } f
2
2
  export * from './interface';
3
3
  export * from './factory';
4
4
  export * from './decorator/cacheKey';
5
- export * as CacheManager from 'cache-manager';
5
+ export * as CacheManager from './base';
6
+ export * from './store';
6
7
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -21,5 +21,6 @@ Object.defineProperty(exports, "getClassMethodDefaultCacheKey", { enumerable: tr
21
21
  __exportStar(require("./interface"), exports);
22
22
  __exportStar(require("./factory"), exports);
23
23
  __exportStar(require("./decorator/cacheKey"), exports);
24
- exports.CacheManager = require("cache-manager");
24
+ exports.CacheManager = require("./base");
25
+ __exportStar(require("./store"), exports);
25
26
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,4 @@
1
- import { Cache, Store, MemoryConfig, FactoryStore, FactoryConfig, MultiCache, WrapTTL } from 'cache-manager';
1
+ import { Cache, Store, MemoryConfig, FactoryStore, FactoryConfig, MultiCache } from './base';
2
2
  export type SingleCacheOptions<S extends Store = any, T extends object = any> = {
3
3
  store: 'memory';
4
4
  options?: MemoryConfig;
@@ -11,11 +11,7 @@ export type SingleCacheOptions<S extends Store = any, T extends object = any> =
11
11
  export type CacheManagerOptions<S extends Store = any, T extends object = any> = SingleCacheOptions<S> | {
12
12
  store: Array<string | Cache | SingleCacheOptions<S, T> | (() => Cache | Promise<Cache>)>;
13
13
  };
14
- export type MidwayCache = Cache & {
15
- methodWrap?: <T>(key: string, fn: (...args: any[]) => Promise<T>, fnArgs: any[], ttl?: WrapTTL<T>) => Promise<T>;
16
- };
17
- export type MidwayMultiCache = MultiCache & {
18
- methodWrap?: <T>(key: string, fn: (...args: any[]) => Promise<T>, fnArgs: any[], ttl?: WrapTTL<T>) => Promise<T>;
19
- };
14
+ export type MidwayCache = Cache;
15
+ export type MidwayMultiCache = MultiCache;
20
16
  export type MidwayUnionCache = MidwayCache | MidwayMultiCache;
21
17
  //# sourceMappingURL=interface.d.ts.map
@@ -0,0 +1,7 @@
1
+ import type { Config, Store } from './base';
2
+ import { IMidwayContainer } from '@midwayjs/core';
3
+ export interface RedisStore extends Store {
4
+ readonly isCacheable: (value: unknown) => boolean;
5
+ }
6
+ export declare function createRedisStore(instanceName: string): (options: Config, container: IMidwayContainer) => Promise<RedisStore>;
7
+ //# sourceMappingURL=store.d.ts.map
package/dist/store.js ADDED
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createRedisStore = void 0;
4
+ const core_1 = require("@midwayjs/core");
5
+ const getVal = (value) => JSON.stringify(value) || '"undefined"';
6
+ function createRedisStore(instanceName) {
7
+ return async (options, container) => {
8
+ const { RedisServiceFactory } = (0, core_1.safeRequire)('@midwayjs/redis');
9
+ const redisServiceFactory = await container.getAsync(RedisServiceFactory);
10
+ const redisInstance = redisServiceFactory.get(instanceName);
11
+ return createStore(redisInstance, options);
12
+ };
13
+ }
14
+ exports.createRedisStore = createRedisStore;
15
+ function createStore(redisCache, options) {
16
+ const isCacheable = (options === null || options === void 0 ? void 0 : options.isCacheable) || (value => value !== undefined && value !== null);
17
+ const keys = (pattern) => redisCache.keys(pattern);
18
+ return {
19
+ async get(key) {
20
+ const val = await redisCache.get(key);
21
+ if (val === undefined || val === null)
22
+ return undefined;
23
+ else
24
+ return JSON.parse(val);
25
+ },
26
+ async set(key, value, ttl) {
27
+ if (!isCacheable(value))
28
+ throw new core_1.MidwayCommonError(`"${value}" is not a cacheable value`);
29
+ const t = ttl === undefined ? options === null || options === void 0 ? void 0 : options.ttl : ttl;
30
+ if (t !== undefined && t !== 0)
31
+ await redisCache.set(key, getVal(value), 'PX', t);
32
+ else
33
+ await redisCache.set(key, getVal(value));
34
+ },
35
+ async mset(args, ttl) {
36
+ const t = ttl === undefined ? options === null || options === void 0 ? void 0 : options.ttl : ttl;
37
+ if (t !== undefined && t !== 0) {
38
+ const multi = redisCache.multi();
39
+ for (const [key, value] of args) {
40
+ if (!isCacheable(value))
41
+ throw new core_1.MidwayCommonError(`"${getVal(value)}" is not a cacheable value`);
42
+ multi.set(key, getVal(value), 'PX', t);
43
+ }
44
+ await multi.exec();
45
+ }
46
+ else
47
+ await redisCache.mset(args.flatMap(([key, value]) => {
48
+ if (!isCacheable(value))
49
+ throw new Error(`"${getVal(value)}" is not a cacheable value`);
50
+ return [key, getVal(value)];
51
+ }));
52
+ },
53
+ mget: (...args) => redisCache
54
+ .mget(args)
55
+ .then(x => x.map(x => x === null || x === undefined
56
+ ? undefined
57
+ : JSON.parse(x))),
58
+ async mdel(...args) {
59
+ await redisCache.del(args);
60
+ },
61
+ async del(key) {
62
+ await redisCache.del(key);
63
+ },
64
+ ttl: async (key) => redisCache.pttl(key),
65
+ keys: (pattern = '*') => keys(pattern),
66
+ reset: () => {
67
+ throw new core_1.MidwayCommonError('flushdb() is too dangerous, if necessary, please use redisServiceFactory.get(client) to get the instance and call it manually.');
68
+ },
69
+ isCacheable,
70
+ };
71
+ }
72
+ //# sourceMappingURL=store.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midwayjs/cache-manager",
3
- "version": "3.14.0",
3
+ "version": "3.14.4-beta.1",
4
4
  "description": "midway cache manager",
5
5
  "main": "dist/index.js",
6
6
  "typings": "index.d.ts",
@@ -28,14 +28,13 @@
28
28
  "node": ">=12"
29
29
  },
30
30
  "devDependencies": {
31
- "@midwayjs/core": "^3.14.0",
32
- "@midwayjs/mock": "^3.14.0",
33
- "@midwayjs/redis": "^3.14.0",
31
+ "@midwayjs/core": "^3.14.3",
32
+ "@midwayjs/mock": "^3.14.3",
33
+ "@midwayjs/redis": "^3.14.3",
34
34
  "cache-manager-ioredis-yet": "1.2.2"
35
35
  },
36
36
  "dependencies": {
37
- "cache-manager": "5.3.2",
38
- "promise-coalesce": "1.1.1"
39
- },
40
- "gitHead": "67e3a3596ffdb65a413064d30c68f1f7965af282"
37
+ "lodash.clonedeep": "4.5.0",
38
+ "lru-cache": "7.18.3"
39
+ }
41
40
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2013 - Now midwayjs
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.