mirror of
https://github.com/crystelf/crystelf-core.git
synced 2025-10-14 05:19:19 +00:00
feat:优化
This commit is contained in:
parent
baf92f470a
commit
426fb886ae
@ -4,10 +4,15 @@ import * as fs from 'fs/promises';
|
|||||||
import { PathService } from '../../core/path/path.service';
|
import { PathService } from '../../core/path/path.service';
|
||||||
import { AutoUpdateService } from '../../core/auto-update/auto-update.service';
|
import { AutoUpdateService } from '../../core/auto-update/auto-update.service';
|
||||||
|
|
||||||
|
interface WordCacheEntry {
|
||||||
|
data: string[];
|
||||||
|
timer: NodeJS.Timeout;
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WordsService {
|
export class WordsService {
|
||||||
private readonly logger = new Logger(WordsService.name);
|
private readonly logger = new Logger(WordsService.name);
|
||||||
private wordCache: Record<string, string[]> = {};
|
private wordCache: Map<string, WordCacheEntry> = new Map();
|
||||||
private readonly clearIntervalMs = 240 * 60 * 1000; // 240min
|
private readonly clearIntervalMs = 240 * 60 * 1000; // 240min
|
||||||
private readonly updateMs = 15 * 60 * 1000; // 15min
|
private readonly updateMs = 15 * 60 * 1000; // 15min
|
||||||
|
|
||||||
@ -18,21 +23,12 @@ export class WordsService {
|
|||||||
private readonly autoUpdateService: AutoUpdateService;
|
private readonly autoUpdateService: AutoUpdateService;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.startAutoClear();
|
|
||||||
this.startAutoUpdate();
|
this.startAutoUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private startAutoClear() {
|
|
||||||
setInterval(() => {
|
|
||||||
this.logger.log('清理文案缓存..');
|
|
||||||
this.wordCache = {};
|
|
||||||
}, this.clearIntervalMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private startAutoUpdate() {
|
private startAutoUpdate() {
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
const wordsPath = path.join(this.paths.get('words'), '..');
|
const wordsPath = path.join(this.paths.get('words'), '..');
|
||||||
//const wordsPath = this.paths.get('words');
|
|
||||||
this.logger.log('定时检查文案仓库更新..');
|
this.logger.log('定时检查文案仓库更新..');
|
||||||
const updated = await this.autoUpdateService.checkRepoForUpdates(
|
const updated = await this.autoUpdateService.checkRepoForUpdates(
|
||||||
wordsPath,
|
wordsPath,
|
||||||
@ -40,26 +36,51 @@ export class WordsService {
|
|||||||
);
|
);
|
||||||
if (updated) {
|
if (updated) {
|
||||||
this.logger.log('文案仓库已更新,清理缓存..');
|
this.logger.log('文案仓库已更新,清理缓存..');
|
||||||
this.wordCache = {};
|
this.clearAllCache();
|
||||||
}
|
}
|
||||||
}, this.updateMs);
|
}, this.updateMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private clearAllCache() {
|
||||||
|
for (const [key, entry] of this.wordCache.entries()) {
|
||||||
|
clearTimeout(entry.timer);
|
||||||
|
this.wordCache.delete(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private scheduleCacheClear(key: string) {
|
||||||
|
const existing = this.wordCache.get(key);
|
||||||
|
if (existing) clearTimeout(existing.timer);
|
||||||
|
|
||||||
|
return setTimeout(() => {
|
||||||
|
this.logger.log(`清理单项文案缓存: ${key}`);
|
||||||
|
this.wordCache.delete(key);
|
||||||
|
}, this.clearIntervalMs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从本地加载文案到内存
|
* 从本地加载文案到内存
|
||||||
*/
|
*/
|
||||||
public async loadWord(type: string, name: string): Promise<string[] | null> {
|
public async loadWord(type: string, name: string): Promise<string[] | null> {
|
||||||
const cacheKey = `${type}/${name}`;
|
const safeType = this.safePathSegment(type);
|
||||||
|
const safeName = this.safePathSegment(name);
|
||||||
|
const cacheKey = `${safeType}/${safeName}`;
|
||||||
this.logger.log(`加载文案 ${cacheKey}..`);
|
this.logger.log(`加载文案 ${cacheKey}..`);
|
||||||
if (this.wordCache[cacheKey]) return this.wordCache[cacheKey];
|
const cache = this.wordCache.get(cacheKey);
|
||||||
|
if (cache) return cache.data;
|
||||||
|
|
||||||
const filePath = path.join(this.paths.get('words'), type, `${name}.json`);
|
const filePath = path.join(
|
||||||
|
this.paths.get('words'),
|
||||||
|
safeType,
|
||||||
|
`${safeName}.json`,
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
const content = await fs.readFile(filePath, 'utf-8');
|
const content = await fs.readFile(filePath, { encoding: 'utf-8' });
|
||||||
const parsed = JSON.parse(content);
|
const parsed = JSON.parse(content);
|
||||||
if (Array.isArray(parsed)) {
|
if (Array.isArray(parsed)) {
|
||||||
const texts = parsed.filter((item) => typeof item === 'string');
|
const texts = parsed.filter((item) => typeof item === 'string');
|
||||||
this.wordCache[cacheKey] = texts;
|
const timer = this.scheduleCacheClear(cacheKey);
|
||||||
|
this.wordCache.set(cacheKey, { data: texts, timer });
|
||||||
return texts;
|
return texts;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -73,16 +94,22 @@ export class WordsService {
|
|||||||
* 重载文案
|
* 重载文案
|
||||||
*/
|
*/
|
||||||
public async reloadWord(type: string, name: string): Promise<boolean> {
|
public async reloadWord(type: string, name: string): Promise<boolean> {
|
||||||
const cacheKey = `${type}/${name}`;
|
const safeType = this.safePathSegment(type);
|
||||||
|
const safeName = this.safePathSegment(name);
|
||||||
|
const cacheKey = `${safeType}/${safeName}`;
|
||||||
this.logger.log(`重载文案: ${cacheKey}..`);
|
this.logger.log(`重载文案: ${cacheKey}..`);
|
||||||
const filePath = path.join(this.paths.get('words'), type, `${name}.json`);
|
const filePath = path.join(
|
||||||
|
this.paths.get('words'),
|
||||||
|
safeType,
|
||||||
|
`${safeName}.json`,
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
const content = await fs.readFile(filePath, 'utf-8');
|
const content = await fs.readFile(filePath, { encoding: 'utf-8' });
|
||||||
const parsed = JSON.parse(content);
|
const parsed = JSON.parse(content);
|
||||||
if (Array.isArray(parsed)) {
|
if (Array.isArray(parsed)) {
|
||||||
this.wordCache[cacheKey] = parsed.filter(
|
const texts = parsed.filter((item) => typeof item === 'string');
|
||||||
(item) => typeof item === 'string',
|
const timer = this.scheduleCacheClear(cacheKey);
|
||||||
);
|
this.wordCache.set(cacheKey, { data: texts, timer });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -91,4 +118,9 @@ export class WordsService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private safePathSegment(segment: string): string {
|
||||||
|
// 将不安全字符转义为安全文件名形式
|
||||||
|
return segment.replace(/[\\\/:*?"<>|]/g, '_');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user