feat(core): caching enhancements (#9227)

* fix(core): redis cache ignore `maxAge` when refreshing

memory cache do not have such a problem

Signed-off-by: Rongrong <15956627+Rongronggg9@users.noreply.github.com>

* feat(core): make `cache.tryGet()` refreshing selectable

Signed-off-by: Rongrong <15956627+Rongronggg9@users.noreply.github.com>

* docs: `ctx.cache.tryGet()` update

Signed-off-by: Rongrong <15956627+Rongronggg9@users.noreply.github.com>
This commit is contained in:
Rongrong 2022-03-19 02:13:15 +08:00 committed by GitHub
parent 933080a1f5
commit 41910802f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 21 additions and 6 deletions

View File

@ -291,7 +291,7 @@ const description = await ctx.cache.tryGet(link, async () => {
});
```
The implementation of tryGet can be seen [here](https://github.com/DIYgod/RSSHub/blob/master/lib/middleware/cache/index.js#L58). The first parameter is the cache key, the second parameter is the cache data acquisition method, and the third parameter is the cache time, it should not be passed in normally. The cache time defaults to [CACHE_CONTENT_EXPIRE](/en/install/#cache-configurations), and each time accessing the cache will recalculate the expiration time
The implementation of tryGet can be seen [here](https://github.com/DIYgod/RSSHub/blob/master/lib/middleware/cache/index.js#L58). The 1st parameter is the cache key; the 2nd parameter is the cache data acquisition method (executed when cache miss); the 3rd parameter is the cache time, it should not be passed in normally and defaults to [CACHE_CONTENT_EXPIRE](/en/install/#cache-configurations); the 4th parameter determines whether to recalculate the expiration time ("renew" the cache) when the current attempt cache hits, `true` is on, `false` is off, default is on
---

View File

@ -292,7 +292,7 @@ const description = await ctx.cache.tryGet(link, async () => {
});
```
tryGet 的实现可以看[这里](https://github.com/DIYgod/RSSHub/blob/master/lib/middleware/cache/index.js#L58),第一个参数为缓存的 key第二个参数为缓存数据获取方法第三个参数为缓存时间,正常情况不应该传入,缓存时间默认为 [CACHE_CONTENT_EXPIRE](/install/#缓存配置),且每次访问缓存会重新计算过期时间
tryGet 的实现可以看[这里](https://github.com/DIYgod/RSSHub/blob/master/lib/middleware/cache/index.js#L58)。第一个参数为缓存的 key第二个参数为缓存未命中时的数据获取方法第三个参数为缓存时间,正常情况不应该传入,缓存时间默认为 [CACHE_CONTENT_EXPIRE](/install/#缓存配置);第四个参数为控制本次尝试缓存命中时是否需要重新计算过期时间(给缓存「续期」)的开关,`true` 为打开,`false` 为关闭,默认为打开
* * *

View File

@ -55,8 +55,8 @@ module.exports = function (app) {
const { get, set, status } = cacheModule;
app.context.cache = {
...cacheModule,
tryGet: async (key, getValueFunc, maxAge = config.cache.contentExpire) => {
let v = await get(key);
tryGet: async (key, getValueFunc, maxAge = config.cache.contentExpire, refresh = true) => {
let v = await get(key, refresh);
if (!v) {
v = await getValueFunc();
set(key, v, maxAge);

View File

@ -18,12 +18,26 @@ redisClient.on('connect', () => {
logger.info('Redis connected.');
});
const getCacheTtlKey = (key) => {
if (key.startsWith('cacheTtl:')) {
throw Error('"cacheTtl:" prefix is reserved for the internal usage, please change your cache key'); // blocking any attempt to get/set the cacheTtl
}
return `cacheTtl:${key}`;
};
module.exports = {
get: async (key, refresh = true) => {
if (key && status.available) {
let value = await redisClient.get(key);
const cacheTtlKey = getCacheTtlKey(key);
let [value, cacheTtl] = await redisClient.mget(key, cacheTtlKey);
if (value && refresh) {
redisClient.expire(key, config.cache.contentExpire);
if (!cacheTtl) {
cacheTtl = config.cache.contentExpire;
redisClient.set(cacheTtlKey, cacheTtl, 'EX', cacheTtl);
} else {
redisClient.expire(cacheTtlKey, cacheTtl);
}
redisClient.expire(key, cacheTtl);
value = value + '';
}
return value;
@ -40,6 +54,7 @@ module.exports = {
value = JSON.stringify(value);
}
if (key) {
redisClient.set(getCacheTtlKey(key), maxAge, 'EX', maxAge);
return redisClient.set(key, value, 'EX', maxAge); // setMode: https://redis.io/commands/set
}
},