优化rss解析缓存

This commit is contained in:
Jerry 2025-05-17 13:29:34 +08:00
parent 38ca20eacd
commit 8fe5b218bc
2 changed files with 56 additions and 21 deletions

View File

@ -37,7 +37,10 @@ export default class RssPlugin extends plugin {
}, },
], ],
}); });
if (!global.__rss_job_scheduled) {
schedule.scheduleJob('*/10 * * * *', () => this.pushFeeds()); schedule.scheduleJob('*/10 * * * *', () => this.pushFeeds());
global.__rss_job_scheduled = true;
}
} }
/** /**
@ -128,10 +131,12 @@ export default class RssPlugin extends plugin {
for (const feed of feeds) { for (const feed of feeds) {
const latest = await rssTools.fetchFeed(feed.url); const latest = await rssTools.fetchFeed(feed.url);
if (!latest || !latest.length) continue; if (!latest || !latest.length) continue;
const newItems = [];
const lastLink = await rssCache.get(feed.url); for (const item of latest) {
const newItems = lastLink ? latest.filter((i) => i.link !== lastLink) : latest; if (!(await rssCache.has(feed.url, item.link))) {
newItems.push(item);
}
}
if (newItems.length) { if (newItems.length) {
await rssCache.set(feed.url, newItems[0].link); await rssCache.set(feed.url, newItems[0].link);

View File

@ -2,9 +2,11 @@ import crypto from 'crypto';
import paths from '../../constants/path.js'; import paths from '../../constants/path.js';
import path from 'path'; import path from 'path';
import fs from 'fs'; import fs from 'fs';
import configControl from '../config/configControl.js';
const redis = global.redis; const redis = global.redis;
const cachePath = path.join(paths.rssCache, 'rss_cache.json'); const cachePath = path.join(paths.rssCache, 'rss_cache.json');
const MAX_CACHE = configControl.get('maxFeed');
const rssCache = { const rssCache = {
/** /**
@ -22,34 +24,56 @@ const rssCache = {
}, },
/** /**
* 从redis中获取数据 * 获取已缓存的 link 数组
* @param url * @param url
* @returns {Promise<*>} * @returns {Promise<any[]|any|*[]>}
*/ */
async get(url) { async get(url) {
const key = this.urlToKey(url); const key = this.urlToKey(url);
return await redis.get(key); const raw = await redis.get(key);
if (!raw) return [];
try {
const parsed = JSON.parse(raw);
if (Array.isArray(parsed)) return parsed;
return [parsed]; // 向后兼容老数据
} catch {
return [raw];
}
}, },
/** /**
* 保存数据至redis和本地 * 判断某条是否已缓存
* @param url
* @param link
* @returns {Promise<boolean>}
*/
async has(url, link) {
const cached = await this.get(url);
return cached.includes(link);
},
/**
* 添加新 link 到缓存
* @param url * @param url
* @param latestLink * @param latestLink
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async set(url, latestLink) { async set(url, latestLink) {
const key = this.urlToKey(url); const key = this.urlToKey(url);
await redis.set(key, latestLink); let cached = await this.get(url);
await this.saveToLocal(url, latestLink); cached = [latestLink, ...cached.filter((l) => l !== latestLink)].slice(0, MAX_CACHE);
await redis.set(key, JSON.stringify(cached));
await this.saveToLocal(url, cached);
}, },
/** /**
* 保存至本地 * 保存到本地文件
* @param url * @param url
* @param latestLink * @param latestLinks
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async saveToLocal(url, latestLink) { async saveToLocal(url, latestLinks) {
let localData = {}; let localData = {};
try { try {
if (fs.existsSync(cachePath)) { if (fs.existsSync(cachePath)) {
@ -58,22 +82,28 @@ const rssCache = {
} catch (err) { } catch (err) {
logger.error(`本地rss缓存读取失败..`, err); logger.error(`本地rss缓存读取失败..`, err);
} }
localData[url] = latestLink; localData[url] = latestLinks;
fs.writeFileSync(cachePath, JSON.stringify(localData, null, 2), 'utf-8'); fs.writeFileSync(cachePath, JSON.stringify(localData, null, 2), 'utf-8');
}, },
/** /**
* 从本地加载数据至redis * 从本地缓存加载到 redis
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async loadLocalToRedis() { async loadLocalToRedis() {
if (!fs.existsSync(cachePath)) return; if (!fs.existsSync(cachePath)) return;
try {
const data = JSON.parse(fs.readFileSync(cachePath, 'utf-8')); const data = JSON.parse(fs.readFileSync(cachePath, 'utf-8'));
for (const [url, link] of Object.entries(data)) { for (const [url, value] of Object.entries(data)) {
const key = this.urlToKey(url); const key = this.urlToKey(url);
await redis.set(key, link); const safeArray = Array.isArray(value) ? value : [value];
await redis.set(key, JSON.stringify(safeArray));
}
logger.info(`[RSS] 本地缓存已加载至 Redis`);
} catch (err) {
logger.error(`[RSS] 加载本地缓存失败`, err);
} }
logger.info(`[RSS]本地缓存已加载至redis..`);
}, },
}; };