Update caching solution

This commit is contained in:
Henry 2019-01-30 10:12:22 +00:00
parent 47778c187d
commit af00264e92
5 changed files with 29 additions and 49 deletions

View File

@ -270,17 +270,11 @@ By default there is a global caching period set in `lib/config.js`, some sources
- Save to cache:
```js
ctx.cache.set((key: string), (value: string), (time: number), (persistent: boolean)); // time is the caching period in seconds. When persistent is set to true, the cache will refresh its expiry time upon every re-request (Under Redis this means the cache will never expire).
ctx.cache.set((key: string), (value: string), (time: number)); // time is the caching period in seconds.
```
- Access the cache:
::: tip tips
Since Redis caches with `persistent = true` will never expire, parameter `persistent` for `Get()` only has effect on LRU memory cache, it serves no purpose for Redis.
:::
```js
const value = await ctx.cache.get((key: string));
```
@ -291,14 +285,14 @@ Given the update frequency is known, set the appropriate caching period to reuse
```js
const key = 'daily' + story.id; // story.id is the unique identifier of each article
ctx.cache.set(key, item.description, 24 * 60 * 60, true); // set the LRU memeroy caching period to 24 hours * 60 minutes * 60 seconds = 86,400 seconds = 1 day
ctx.cache.set(key, item.description, 24 * 60 * 60); // set the caching period to 24 hours * 60 minutes * 60 seconds = 86,400 seconds = 1 day
```
When the identical requests come in, reuse the cache
```js
const key = 'daily' + story.id;
const value = await ctx.cache.get(key, true); // query the LRU memory cache to find the unique identifier
const value = await ctx.cache.get(key); // query the cache to find the unique identifier
if (value) {
// return the cached data
item.description = value; // assign the cached data

View File

@ -267,17 +267,11 @@ sidebar: auto
- 添加缓存:
```js
ctx.cache.set((key: string), (value: string), (time: number), (persistent: boolean)); // time 为缓存时间。单位为秒。persistent 为 true 则为缓存自动延长过期时间 (Redis 下则为永不过期)。
ctx.cache.set((key: string), (value: string), (time: number)); // time 为缓存时间。单位为秒。
```
- 获取缓存:
::: tip 提示
 由于 Redis 下 `persistent = true` 的缓存不会过期,`Get()` 下 `persistent` 参数仅适用于 LRU memory 缓存,对于 Redis 不会有任何效果。
:::
```js
const value = await ctx.cache.get((key: string));
```
@ -288,14 +282,14 @@ const value = await ctx.cache.get((key: string));
```js
const key = 'daily' + story.id; // story.id 为知乎日报返回的文章唯一识别符
ctx.cache.set(key, item.description, 24 * 60 * 60, true); // 设置 LRU memory 缓存时间为 24小时 * 60分钟 * 60秒 = 86400秒 = 1天
ctx.cache.set(key, item.description, 24 * 60 * 60); // 设置缓存时间为 24小时 * 60分钟 * 60秒 = 86400秒 = 1天
```
当同样的请求被发起时,优先使用未过期的缓存:
```js
const key = 'daily' + story.id;
const value = await ctx.cache.get(key, true); // 从 LRU memory 缓存中查询是否已存在该文章唯一识别符
const value = await ctx.cache.get(key); // 从缓存中查询是否已存在该文章唯一识别符
if (value) {
// 查询返回未过期缓存
item.description = value; // 直接赋值

View File

@ -94,11 +94,11 @@ if (config.cacheType === 'memory') {
set: () => null,
};
}
app.context.cache.tryGet = async function(key, getValueFunc, maxAge = 24 * 60 * 60, persistent = false) {
let v = await this.get(key, persistent);
app.context.cache.tryGet = async function(key, getValueFunc, maxAge = 24 * 60 * 60) {
let v = await this.get(key);
if (!v) {
v = await getValueFunc();
this.set(key, v, maxAge, persistent);
this.set(key, v, maxAge);
} else {
let parsed;
try {

View File

@ -15,28 +15,24 @@ module.exports = function(options = {}) {
ignoreQuery = false,
} = options;
const temporaryCache = new lru({
const pageCache = new lru({
maxAge: expire * 1000,
max: maxLength,
});
const persistentCache = new lru({
const routeCache = new lru({
maxAge: expire * 1000,
max: maxLength,
updateAgeOnGet: true,
});
options.app.context.cache = {
get: (key, persistent = false) => {
get: (key) => {
if (key) {
if (persistent) {
return persistentCache.get(key);
} else {
return temporaryCache.get(key);
}
return routeCache.get(key);
}
},
set: (key, value, maxAge, persistent = false) => {
set: (key, value, maxAge) => {
if (!value || value === 'undefined') {
value = '';
}
@ -44,11 +40,7 @@ module.exports = function(options = {}) {
value = JSON.stringify(value);
}
if (key) {
if (persistent) {
return persistentCache.set(key, value, maxAge * 1000);
} else {
return temporaryCache.set(key, value, maxAge * 1000);
}
return routeCache.set(key, value, maxAge * 1000);
}
},
};
@ -91,13 +83,13 @@ module.exports = function(options = {}) {
*/
async function getCache(ctx, key, tkey) {
let type;
const value = temporaryCache.get(key);
const value = pageCache.get(key);
let ok = false;
if (value) {
ctx.response.status = 200;
type = temporaryCache.get(tkey) || 'text/html';
type = pageCache.get(tkey) || 'text/html';
// can happen if user specified return_buffers: true in redis options
if (Buffer.isBuffer(type)) {
type = type.toString();
@ -130,7 +122,7 @@ module.exports = function(options = {}) {
if (Buffer.byteLength(body) > maxLength) {
return;
}
temporaryCache.set(key, body);
pageCache.set(key, body);
await cacheType(ctx, tkey);
}
@ -141,7 +133,7 @@ module.exports = function(options = {}) {
async function cacheType(ctx, tkey) {
const type = ctx.response.headers['content-type'];
if (type) {
temporaryCache.set(tkey, type);
pageCache.set(tkey, type);
}
}
};

View File

@ -42,14 +42,18 @@ module.exports = function(options = {}) {
});
options.app.context.cache = {
/* eslint-disable no-unused-vars */
get: async (key, persistent = false) => {
/* eslint-enable no-unused-vars */
get: async (key) => {
if (key) {
return await redisClient.get(key);
const value = await redisClient.get(key);
if (value) {
let ttl = redisClient.ttl(key);
ttl = ttl > expire ? ttl : expire * 2;
await redisClient.setex(key, ttl, value);
}
return value;
}
},
set: async (key, value, maxAge, persistent = false) => {
set: async (key, value, maxAge) => {
if (!value || value === 'undefined') {
value = '';
}
@ -57,11 +61,7 @@ module.exports = function(options = {}) {
value = JSON.stringify(value);
}
if (key) {
if (persistent) {
await redisClient.expire(key, value);
} else {
await redisClient.setex(key, maxAge, value);
}
await redisClient.setex(key, maxAge, value);
}
},
};