-
Notifications
You must be signed in to change notification settings - Fork 578
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: new cache manager component (#3492)
* fix(deps): update dependency ws to v8.16.0 (#3524) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency axios to v1.6.3 (#3523) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore: add cache code * feat: add cache-manager and cache-manager-redis * fix: store options * chore: upgrade cache-manager * chore: sync cache-manager * fix: typings * fix: test --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
- Loading branch information
1 parent
c1ed3a2
commit af82070
Showing
49 changed files
with
1,488 additions
and
5 deletions.
There are no files selected for viewing
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# midway cache manager redis store | ||
|
||
[![Package Quality](http://npm.packagequality.com/shield/midway-core.svg)](http://packagequality.com/#?package=midway-core) | ||
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/midwayjs/midway/pulls) | ||
|
||
this is a sub package for midway. | ||
|
||
Document: [https://midwayjs.org](https://midwayjs.org) | ||
|
||
## License | ||
|
||
[MIT]((http://github.com/midwayjs/midway/blob/master/LICENSE)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module.exports = { | ||
preset: 'ts-jest', | ||
testEnvironment: 'node', | ||
testPathIgnorePatterns: ['<rootDir>/test/fixtures'], | ||
coveragePathIgnorePatterns: ['<rootDir>/test/', '<rootDir>/dist/'], | ||
setupFilesAfterEnv: ['./jest.setup.js'], | ||
coverageProvider: 'v8', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
process.env.MIDWAY_TS_MODE = 'true'; | ||
jest.setTimeout(30000); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
{ | ||
"name": "@midwayjs/cache-manager-redis", | ||
"version": "3.13.5", | ||
"description": "midway redis store for cache manager", | ||
"main": "dist/index.js", | ||
"typings": "dist/index.d.ts", | ||
"scripts": { | ||
"build": "tsc", | ||
"test": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand", | ||
"cov": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand --coverage --forceExit" | ||
}, | ||
"author": "", | ||
"files": [ | ||
"dist/**/*.js", | ||
"dist/**/*.d.ts" | ||
], | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "[email protected]:midwayjs/midway.git" | ||
}, | ||
"keywords": [ | ||
"midway", | ||
"cache", | ||
"store", | ||
"redis" | ||
], | ||
"engines": { | ||
"node": ">=12" | ||
}, | ||
"devDependencies": { | ||
"@midwayjs/core": "^3.13.5", | ||
"@midwayjs/cache-manager": "^3.13.5", | ||
"@midwayjs/mock": "^3.13.5", | ||
"cache-manager": "5.3.1" | ||
}, | ||
"dependencies": { | ||
"@midwayjs/redis": "^3.13.5" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { IMidwayContainer } from '@midwayjs/core'; | ||
import { RedisServiceFactory } from '@midwayjs/redis'; | ||
import { Config } from 'cache-manager'; | ||
import { createRedisStore } from './store'; | ||
|
||
export function createStore(instanceName: string) { | ||
return async (options: Config, container: IMidwayContainer) => { | ||
const redisServiceFactory = await container.getAsync(RedisServiceFactory); | ||
const redisInstance = redisServiceFactory.get(instanceName); | ||
return createRedisStore(redisInstance, options); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import type { Config, Store } from 'cache-manager'; | ||
import { Redis } from '@midwayjs/redis'; | ||
import { MidwayCommonError } from '@midwayjs/core'; | ||
|
||
const getVal = (value: unknown) => JSON.stringify(value) || '"undefined"'; | ||
export interface RedisStore extends Store { | ||
readonly isCacheable: (value: unknown) => boolean; | ||
} | ||
|
||
export function createRedisStore(redisCache: Redis, options?: Config) { | ||
const isCacheable = | ||
options?.isCacheable || (value => value !== undefined && value !== null); | ||
|
||
const keys = (pattern: string) => redisCache.keys(pattern); | ||
|
||
return { | ||
async get<T>(key: string) { | ||
const val = await redisCache.get(key); | ||
if (val === undefined || val === null) return undefined; | ||
else return JSON.parse(val) as T; | ||
}, | ||
async set(key, value, ttl) { | ||
if (!isCacheable(value)) | ||
throw new MidwayCommonError(`"${value}" is not a cacheable value`); | ||
const t = ttl === undefined ? options?.ttl : ttl; | ||
if (t !== undefined && t !== 0) | ||
await redisCache.set(key, getVal(value), 'PX', t); | ||
else await redisCache.set(key, getVal(value)); | ||
}, | ||
async mset(args, ttl) { | ||
const t = ttl === undefined ? options?.ttl : ttl; | ||
if (t !== undefined && t !== 0) { | ||
const multi = redisCache.multi(); | ||
for (const [key, value] of args) { | ||
if (!isCacheable(value)) | ||
throw new MidwayCommonError( | ||
`"${getVal(value)}" is not a cacheable value` | ||
); | ||
multi.set(key, getVal(value), 'PX', t); | ||
} | ||
await multi.exec(); | ||
} else | ||
await redisCache.mset( | ||
args.flatMap(([key, value]) => { | ||
if (!isCacheable(value)) | ||
throw new Error(`"${getVal(value)}" is not a cacheable value`); | ||
return [key, getVal(value)] as [string, string]; | ||
}) | ||
); | ||
}, | ||
mget: (...args) => | ||
redisCache | ||
.mget(args) | ||
.then(x => | ||
x.map(x => | ||
x === null || x === undefined | ||
? undefined | ||
: (JSON.parse(x) as unknown) | ||
) | ||
), | ||
async mdel(...args) { | ||
await redisCache.del(args); | ||
}, | ||
async del(key) { | ||
await redisCache.del(key); | ||
}, | ||
ttl: async key => redisCache.pttl(key), | ||
keys: (pattern = '*') => keys(pattern), | ||
reset: () => { | ||
throw new MidwayCommonError( | ||
'flushdb() is too dangerous, if necessary, please use redisServiceFactory.get(client) to get the instance and call it manually.' | ||
); | ||
}, | ||
isCacheable, | ||
} as RedisStore; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import * as cacheManager from '@midwayjs/cache-manager'; | ||
import * as redis from '@midwayjs/redis'; | ||
import { createLightApp, close } from '@midwayjs/mock'; | ||
import { createStore } from '../src'; | ||
import { CachingFactory } from '@midwayjs/cache-manager'; | ||
|
||
describe('cache-manager-redis', () => { | ||
it('should test single caching', async () => { | ||
const app = await createLightApp('', { | ||
imports: [ | ||
cacheManager, | ||
redis, | ||
], | ||
globalConfig: { | ||
cacheManager: { | ||
client: { | ||
store: createStore('default'), | ||
options: { | ||
ttl: 10, | ||
} | ||
} | ||
}, | ||
redis: { | ||
client: { | ||
port: 6379, | ||
host: '127.0.0.1', | ||
} | ||
} | ||
}, | ||
}); | ||
|
||
const cachingFactory = await app.getApplicationContext().getAsync(CachingFactory); | ||
const caching = cachingFactory.getCaching('default'); | ||
await caching.set('foo', 'bar', 1000); | ||
const result = await caching.get('foo'); | ||
expect(result).toEqual('bar'); | ||
|
||
|
||
try { | ||
await caching.reset(); | ||
} catch (e) { | ||
expect(e.message).toMatch('flushdb() is too dangerous'); | ||
} | ||
|
||
await close(app); | ||
}); | ||
|
||
it('should test multi caching', async () => { | ||
const app = await createLightApp('', { | ||
imports: [ | ||
redis, | ||
cacheManager, | ||
], | ||
globalConfig: { | ||
cacheManager: { | ||
client: { | ||
store: [ | ||
{ | ||
store: createStore('default'), | ||
options: { | ||
ttl: 10, | ||
} | ||
} | ||
] | ||
} | ||
}, | ||
redis: { | ||
client: { | ||
port: 6379, | ||
host: '127.0.0.1', | ||
} | ||
} | ||
} | ||
}); | ||
|
||
|
||
const cachingFactory = await app.getApplicationContext().getAsync(CachingFactory); | ||
const caching = cachingFactory.getMultiCaching('default'); | ||
await caching.mset([['foo', 'bar']], 5); | ||
|
||
const result = await caching.mget('foo'); | ||
expect(result).toEqual(['bar']); | ||
|
||
// mdel | ||
await caching.mdel('foo'); | ||
const result2 = await caching.mget('foo'); | ||
expect(result2).toEqual([undefined]); | ||
|
||
await close(app); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"compileOnSave": true, | ||
"compilerOptions": { | ||
"rootDir": "src", | ||
"outDir": "dist" | ||
}, | ||
"include": [ | ||
"./src/**/*.ts" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"extends": ["../../typedoc.base.json"], | ||
"entryPoints": ["src/index.ts"] | ||
} |
Oops, something went wrong.