UNPKG

synthia-cache-system

Version:

Synthia Engine Cache System - 核心缓存系统实现,提供多级缓存、版本管理、性能监控等功能

1,546 lines (1,537 loc) 96.3 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/plugin.ts var plugin_exports = {}; __export(plugin_exports, { default: () => plugin_default, getCacheManager: () => getCacheManager, getEnhancedCacheManager: () => getEnhancedCacheManager, getMetricsCollector: () => getMetricsCollector, getStrategyManager: () => getStrategyManager, getVersionManager: () => getVersionManager, setCacheConfig: () => setCacheConfig }); module.exports = __toCommonJS(plugin_exports); var import_chalk10 = __toESM(require("chalk")); var import_ora10 = __toESM(require("ora")); // src/hot-start-optimizer.ts var import_chalk9 = __toESM(require("chalk")); var import_ora9 = __toESM(require("ora")); // src/local-cache.ts var import_fs_extra = __toESM(require("fs-extra")); var import_path = require("path"); var import_chalk = __toESM(require("chalk")); var import_ora = __toESM(require("ora")); var LocalCache = class { constructor(cacheDir = ".synthia-cache", config) { this.spinner = (0, import_ora.default)(); this.stats = { totalItems: 0, totalSize: 0, hits: 0, misses: 0, hitRate: 0, avgAccessTime: 0, topItems: [] }; this.cacheDir = cacheDir; this.config = { dir: cacheDir, maxSize: 100 * 1024 * 1024, // 100MB ttl: 7 * 24 * 60 * 60 * 1e3, // 7天 compression: false, ...config }; this.ensureCacheDir(); this.loadStats(); } /** * 设置缓存 */ async set(key, value, meta = {}) { this.spinner.start(`\u8BBE\u7F6E\u672C\u5730\u7F13\u5B58: ${key}`); try { const startTime = Date.now(); const cacheItem = { key, value, meta: { hash: meta.hash || this.calculateObjectHash(value), size: meta.size || JSON.stringify(value).length, expiresAt: meta.expiresAt || Date.now() + this.config.ttl, dependencies: meta.dependencies || [], tags: meta.tags || [], version: meta.version || "1.0.0" }, createdAt: Date.now(), lastAccessedAt: Date.now(), accessCount: 0 }; const cachePath = this.getCachePath(key); import_fs_extra.default.writeFileSync(cachePath, JSON.stringify(cacheItem, null, 2)); this.updateStats("set", key, Date.now() - startTime, true); this.spinner.succeed(`\u672C\u5730\u7F13\u5B58\u8BBE\u7F6E\u5B8C\u6210: ${key}`); } catch (error) { this.spinner.fail(`\u672C\u5730\u7F13\u5B58\u8BBE\u7F6E\u5931\u8D25: ${key}`); console.error(import_chalk.default.red("\u7F13\u5B58\u9519\u8BEF:"), error); this.updateStats( "set", key, 0, false, error instanceof Error ? error.message : "Unknown error" ); } } /** * 获取缓存 */ async get(key) { this.spinner.start(`\u83B7\u53D6\u672C\u5730\u7F13\u5B58: ${key}`); try { const startTime = Date.now(); const cachePath = this.getCachePath(key); if (!import_fs_extra.default.existsSync(cachePath)) { this.spinner.warn(`\u7F13\u5B58\u4E0D\u5B58\u5728: ${key}`); this.updateStats("get", key, Date.now() - startTime, false); return null; } const cacheItem = JSON.parse( import_fs_extra.default.readFileSync(cachePath, "utf-8") ); if (cacheItem.meta.expiresAt < Date.now()) { this.spinner.warn(`\u7F13\u5B58\u5DF2\u8FC7\u671F: ${key}`); await this.delete(key); this.updateStats("get", key, Date.now() - startTime, false); return null; } cacheItem.lastAccessedAt = Date.now(); cacheItem.accessCount++; import_fs_extra.default.writeFileSync(cachePath, JSON.stringify(cacheItem, null, 2)); this.spinner.succeed(`\u672C\u5730\u7F13\u5B58\u83B7\u53D6\u6210\u529F: ${key}`); this.updateStats("get", key, Date.now() - startTime, true); return cacheItem; } catch (error) { this.spinner.fail(`\u672C\u5730\u7F13\u5B58\u83B7\u53D6\u5931\u8D25: ${key}`); console.error(import_chalk.default.red("\u7F13\u5B58\u9519\u8BEF:"), error); this.updateStats( "get", key, 0, false, error instanceof Error ? error.message : "Unknown error" ); return null; } } /** * 删除缓存 */ async delete(key) { try { const startTime = Date.now(); const cachePath = this.getCachePath(key); if (import_fs_extra.default.existsSync(cachePath)) { require("fs").unlinkSync(cachePath); this.updateStats("delete", key, Date.now() - startTime, true); console.log(import_chalk.default.green(`\u7F13\u5B58\u5DF2\u5220\u9664: ${key}`)); } else { this.updateStats("delete", key, Date.now() - startTime, false); } } catch (error) { console.error(import_chalk.default.red("\u5220\u9664\u7F13\u5B58\u5931\u8D25:"), error); this.updateStats( "delete", key, 0, false, error instanceof Error ? error.message : "Unknown error" ); } } /** * 清空所有缓存 */ async clear() { this.spinner.start("\u6E05\u7A7A\u672C\u5730\u7F13\u5B58..."); try { const startTime = Date.now(); if (import_fs_extra.default.existsSync(this.cacheDir)) { const files = import_fs_extra.default.readdirSync(this.cacheDir); for (const file of files) { const filePath = (0, import_path.join)(this.cacheDir, file); const stats = import_fs_extra.default.statSync(filePath); if (stats.isFile()) { require("fs").unlinkSync(filePath); } else if (stats.isDirectory()) { require("fs").rmSync(filePath, { recursive: true, force: true }); } } } this.stats = { totalItems: 0, totalSize: 0, hits: 0, misses: 0, hitRate: 0, avgAccessTime: 0, topItems: [] }; this.saveStats(); this.spinner.succeed("\u672C\u5730\u7F13\u5B58\u5DF2\u6E05\u7A7A"); this.updateStats("clear", "", Date.now() - startTime, true); } catch (error) { this.spinner.fail("\u6E05\u7A7A\u672C\u5730\u7F13\u5B58\u5931\u8D25"); console.error(import_chalk.default.red("\u6E05\u7A7A\u9519\u8BEF:"), error); this.updateStats( "clear", "", 0, false, error instanceof Error ? error.message : "Unknown error" ); } } /** * 检查缓存是否存在 */ async has(key) { const cachePath = this.getCachePath(key); return import_fs_extra.default.existsSync(cachePath); } /** * 获取缓存统计信息 */ async getStats() { await this.refreshStats(); return { ...this.stats }; } /** * 获取所有缓存键 */ async keys() { if (!import_fs_extra.default.existsSync(this.cacheDir)) { return []; } const files = import_fs_extra.default.readdirSync(this.cacheDir); return files.filter((file) => file.endsWith(".cache")).map((file) => file.replace(".cache", "")); } /** * 获取缓存大小 */ async size() { await this.refreshStats(); return this.stats.totalSize; } /** * 获取缓存路径 */ getCachePath(key) { return (0, import_path.join)(this.cacheDir, `${key}.cache`); } /** * 确保缓存目录存在 */ ensureCacheDir() { if (!import_fs_extra.default.existsSync(this.cacheDir)) { import_fs_extra.default.mkdirSync(this.cacheDir, { recursive: true }); } } /** * 更新统计信息 */ updateStats(type, _key, duration, success, _error) { if (type === "get") { if (success) { this.stats.hits++; } else { this.stats.misses++; } } const total = this.stats.hits + this.stats.misses; this.stats.hitRate = total > 0 ? this.stats.hits / total : 0; if (type === "get" && success) { const totalTime = this.stats.avgAccessTime * (this.stats.hits - 1) + duration; this.stats.avgAccessTime = totalTime / this.stats.hits; } this.saveStats(); } /** * 刷新统计信息 */ async refreshStats() { if (!import_fs_extra.default.existsSync(this.cacheDir)) { return; } const files = import_fs_extra.default.readdirSync(this.cacheDir); const cacheFiles = files.filter((file) => file.endsWith(".cache")); let totalSize = 0; const topItems = []; for (const file of cacheFiles) { try { const cachePath = (0, import_path.join)(this.cacheDir, file); const cacheItem = JSON.parse( import_fs_extra.default.readFileSync(cachePath, "utf-8") ); totalSize += cacheItem.meta.size; topItems.push({ key: cacheItem.key, accessCount: cacheItem.accessCount, size: cacheItem.meta.size }); } catch (error) { continue; } } this.stats.totalItems = cacheFiles.length; this.stats.totalSize = totalSize; this.stats.topItems = topItems.sort((a, b) => b.accessCount - a.accessCount).slice(0, 10); } /** * 加载统计信息 */ loadStats() { const statsPath = (0, import_path.join)(this.cacheDir, ".stats.json"); if (import_fs_extra.default.existsSync(statsPath)) { try { const statsData = JSON.parse(import_fs_extra.default.readFileSync(statsPath, "utf-8")); this.stats = { ...this.stats, ...statsData }; } catch (error) { } } } /** * 保存统计信息 */ saveStats() { const statsPath = (0, import_path.join)(this.cacheDir, ".stats.json"); import_fs_extra.default.writeFileSync(statsPath, JSON.stringify(this.stats, null, 2)); } /** * 计算对象哈希 */ calculateObjectHash(obj) { const hash = require("crypto").createHash("sha256"); hash.update(JSON.stringify(obj)); return hash.digest("hex"); } }; // src/cloud-cache.ts var import_client_s3 = require("@aws-sdk/client-s3"); var import_crypto = require("crypto"); var import_chalk2 = __toESM(require("chalk")); var import_ora2 = __toESM(require("ora")); var CloudCache = class { constructor(config) { this.spinner = (0, import_ora2.default)(); this.bucket = config.bucket; this.prefix = "synthia-cache/"; this.client = new import_client_s3.S3Client({ region: config.region, credentials: { accessKeyId: config.accessKeyId, secretAccessKey: config.accessKeySecret }, endpoint: config.endpoint }); } /** * 获取缓存 */ async get(key) { this.spinner.start(`\u4ECE\u4E91\u7AEF\u83B7\u53D6\u7F13\u5B58: ${key}`); try { const objectKey = this.getObjectKey(key); const command = new import_client_s3.GetObjectCommand({ Bucket: this.bucket, Key: objectKey }); const response = await this.client.send(command); if (!response.Body) { this.spinner.warn(`\u4E91\u7AEF\u7F13\u5B58\u4E0D\u5B58\u5728: ${key}`); return null; } const chunks = []; const reader = response.Body.transformToWebStream().getReader(); while (true) { const { done, value } = await reader.read(); if (done) break; chunks.push(value); } const buffer = Buffer.concat(chunks); const data = JSON.parse(buffer.toString()); this.spinner.succeed(`\u4E91\u7AEF\u7F13\u5B58\u83B7\u53D6\u6210\u529F: ${key}`); return data; } catch (error) { this.spinner.fail(`\u4E91\u7AEF\u7F13\u5B58\u83B7\u53D6\u5931\u8D25: ${key}`); console.error(import_chalk2.default.red("\u4E91\u7AEF\u7F13\u5B58\u9519\u8BEF:"), error); return null; } } /** * 设置缓存 */ async set(key, value, meta) { this.spinner.start(`\u8BBE\u7F6E\u4E91\u7AEF\u7F13\u5B58: ${key}`); try { const cacheItem = { key, value, meta: { hash: meta.hash || this.calculateHash(value), size: meta.size || JSON.stringify(value).length, expiresAt: meta.expiresAt || Date.now() + 7 * 24 * 60 * 60 * 1e3, // 7天 dependencies: meta.dependencies || [], tags: meta.tags || [], version: meta.version || "1.0.0" }, createdAt: Date.now(), lastAccessedAt: Date.now(), accessCount: 0 }; const objectKey = this.getObjectKey(key); const command = new import_client_s3.PutObjectCommand({ Bucket: this.bucket, Key: objectKey, Body: JSON.stringify(cacheItem), ContentType: "application/json", Metadata: { "synthia-cache-key": key, "synthia-cache-version": cacheItem.meta.version, "synthia-cache-hash": cacheItem.meta.hash } }); await this.client.send(command); this.spinner.succeed(`\u4E91\u7AEF\u7F13\u5B58\u8BBE\u7F6E\u5B8C\u6210: ${key}`); } catch (error) { this.spinner.fail(`\u4E91\u7AEF\u7F13\u5B58\u8BBE\u7F6E\u5931\u8D25: ${key}`); console.error(import_chalk2.default.red("\u4E91\u7AEF\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 删除缓存 */ async delete(key) { this.spinner.start(`\u5220\u9664\u4E91\u7AEF\u7F13\u5B58: ${key}`); try { const objectKey = this.getObjectKey(key); const command = new import_client_s3.DeleteObjectCommand({ Bucket: this.bucket, Key: objectKey }); await this.client.send(command); this.spinner.succeed(`\u4E91\u7AEF\u7F13\u5B58\u5220\u9664\u5B8C\u6210: ${key}`); } catch (error) { this.spinner.fail(`\u4E91\u7AEF\u7F13\u5B58\u5220\u9664\u5931\u8D25: ${key}`); console.error(import_chalk2.default.red("\u4E91\u7AEF\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 清空缓存 */ async clear() { this.spinner.start("\u6E05\u7A7A\u4E91\u7AEF\u7F13\u5B58..."); try { const command = new import_client_s3.ListObjectsV2Command({ Bucket: this.bucket, Prefix: this.prefix }); const response = await this.client.send(command); if (response.Contents) { const deletePromises = response.Contents.map( (obj) => this.client.send( new import_client_s3.DeleteObjectCommand({ Bucket: this.bucket, Key: obj.Key }) ) ); await Promise.all(deletePromises); } this.spinner.succeed("\u4E91\u7AEF\u7F13\u5B58\u5DF2\u6E05\u7A7A"); } catch (error) { this.spinner.fail("\u6E05\u7A7A\u4E91\u7AEF\u7F13\u5B58\u5931\u8D25"); console.error(import_chalk2.default.red("\u4E91\u7AEF\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 检查缓存是否存在 */ async has(key) { try { const objectKey = this.getObjectKey(key); const command = new import_client_s3.HeadObjectCommand({ Bucket: this.bucket, Key: objectKey }); await this.client.send(command); return true; } catch (error) { return false; } } /** * 获取缓存统计信息 */ async getStats() { this.spinner.start("\u83B7\u53D6\u4E91\u7AEF\u7F13\u5B58\u7EDF\u8BA1..."); try { const command = new import_client_s3.ListObjectsV2Command({ Bucket: this.bucket, Prefix: this.prefix }); const response = await this.client.send(command); let totalItems = 0; let totalSize = 0; const topItems = []; if (response.Contents) { totalItems = response.Contents.length; totalSize = response.Contents.reduce( (sum, obj) => sum + (obj.Size || 0), 0 ); const sortedItems = response.Contents.sort( (a, b) => (b.Size || 0) - (a.Size || 0) ).slice(0, 10); for (const item of sortedItems) { if (item.Key) { const key = this.extractKeyFromObjectKey(item.Key); topItems.push({ key, accessCount: 0, // 云端无法获取访问次数 size: item.Size || 0 }); } } } const stats = { totalItems, totalSize, hits: 0, // 云端无法统计命中率 misses: 0, hitRate: 0, avgAccessTime: 0, topItems }; this.spinner.succeed("\u4E91\u7AEF\u7F13\u5B58\u7EDF\u8BA1\u83B7\u53D6\u5B8C\u6210"); return stats; } catch (error) { this.spinner.fail("\u83B7\u53D6\u4E91\u7AEF\u7F13\u5B58\u7EDF\u8BA1\u5931\u8D25"); console.error(import_chalk2.default.red("\u4E91\u7AEF\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 获取所有缓存键 */ async keys() { try { const command = new import_client_s3.ListObjectsV2Command({ Bucket: this.bucket, Prefix: this.prefix }); const response = await this.client.send(command); if (!response.Contents) { return []; } return response.Contents.map((obj) => obj.Key).filter((key) => key !== void 0).map((key) => this.extractKeyFromObjectKey(key)); } catch (error) { console.error(import_chalk2.default.red("\u83B7\u53D6\u7F13\u5B58\u952E\u5931\u8D25:"), error); return []; } } /** * 获取缓存大小 */ async size() { const stats = await this.getStats(); return stats.totalSize; } /** * 同步到云端 */ async sync(key) { this.spinner.start(`\u540C\u6B65\u7F13\u5B58\u5230\u4E91\u7AEF: ${key}`); try { this.spinner.succeed(`\u7F13\u5B58\u540C\u6B65\u5B8C\u6210: ${key}`); } catch (error) { this.spinner.fail(`\u7F13\u5B58\u540C\u6B65\u5931\u8D25: ${key}`); console.error(import_chalk2.default.red("\u540C\u6B65\u9519\u8BEF:"), error); throw error; } } /** * 从云端拉取 */ async pull(key) { return this.get(key); } /** * 批量同步 */ async batchSync(keys) { this.spinner.start(`\u6279\u91CF\u540C\u6B65 ${keys.length} \u4E2A\u7F13\u5B58\u5230\u4E91\u7AEF...`); try { const syncPromises = keys.map((key) => this.sync(key)); await Promise.all(syncPromises); this.spinner.succeed(`\u6279\u91CF\u540C\u6B65\u5B8C\u6210: ${keys.length} \u4E2A\u7F13\u5B58`); } catch (error) { this.spinner.fail("\u6279\u91CF\u540C\u6B65\u5931\u8D25"); console.error(import_chalk2.default.red("\u6279\u91CF\u540C\u6B65\u9519\u8BEF:"), error); throw error; } } /** * 获取对象键 */ getObjectKey(key) { return `${this.prefix}${key}.json`; } /** * 从对象键提取缓存键 */ extractKeyFromObjectKey(objectKey) { return objectKey.replace(this.prefix, "").replace(".json", ""); } /** * 计算哈希值 */ calculateHash(value) { const hash = (0, import_crypto.createHash)("sha256"); hash.update(JSON.stringify(value)); return hash.digest("hex"); } }; // src/hash-manager.ts var import_crypto2 = require("crypto"); var import_fs_extra2 = __toESM(require("fs-extra")); // src/cache-manager.ts var import_chalk3 = __toESM(require("chalk")); var import_ora3 = __toESM(require("ora")); var SynthiaCacheManager = class { constructor(config) { this.spinner = (0, import_ora3.default)(); this.config = config; this.localCache = new LocalCache(config.local.dir, config.local); if (config.cloud.enabled) { this.cloudCache = new CloudCache(config.cloud); } } /** * 获取缓存 */ async get(key) { this.spinner.start(`\u83B7\u53D6\u7F13\u5B58: ${key}`); try { if (this.config.strategy.localFirst) { const localItem = await this.localCache.get(key); if (localItem) { this.spinner.succeed(`\u672C\u5730\u7F13\u5B58\u547D\u4E2D: ${key}`); return localItem.value; } if (this.cloudCache) { const cloudItem = await this.cloudCache.get(key); if (cloudItem) { await this.localCache.set(key, cloudItem.value, cloudItem.meta); this.spinner.succeed(`\u4E91\u7AEF\u7F13\u5B58\u547D\u4E2D\u5E76\u540C\u6B65\u5230\u672C\u5730: ${key}`); return cloudItem.value; } } } else { if (this.cloudCache) { const cloudItem = await this.cloudCache.get(key); if (cloudItem) { await this.localCache.set(key, cloudItem.value, cloudItem.meta); this.spinner.succeed(`\u4E91\u7AEF\u7F13\u5B58\u547D\u4E2D\u5E76\u540C\u6B65\u5230\u672C\u5730: ${key}`); return cloudItem.value; } } const localItem = await this.localCache.get(key); if (localItem) { this.spinner.succeed(`\u672C\u5730\u7F13\u5B58\u547D\u4E2D: ${key}`); return localItem.value; } } this.spinner.warn(`\u7F13\u5B58\u672A\u547D\u4E2D: ${key}`); return null; } catch (error) { this.spinner.fail(`\u83B7\u53D6\u7F13\u5B58\u5931\u8D25: ${key}`); console.error(import_chalk3.default.red("\u7F13\u5B58\u9519\u8BEF:"), error); return null; } } /** * 设置缓存 */ async set(key, value, options = {}) { this.spinner.start(`\u8BBE\u7F6E\u7F13\u5B58: ${key}`); try { await this.localCache.set(key, value, options); if (this.cloudCache && this.config.strategy.autoSync) { await this.cloudCache.set(key, value, options); } this.spinner.succeed(`\u7F13\u5B58\u8BBE\u7F6E\u5B8C\u6210: ${key}`); } catch (error) { this.spinner.fail(`\u7F13\u5B58\u8BBE\u7F6E\u5931\u8D25: ${key}`); console.error(import_chalk3.default.red("\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 批量设置缓存 */ async setBatch(items) { this.spinner.start(`\u6279\u91CF\u8BBE\u7F6E\u7F13\u5B58 (${items.length} \u9879)`); try { const localPromises = items.map( (item) => this.localCache.set(item.key, item.value, item.options || {}) ); await Promise.all(localPromises); if (this.cloudCache && this.config.strategy.autoSync) { const cloudPromises = items.map( (item) => this.cloudCache.set(item.key, item.value, item.options || {}) ); await Promise.all(cloudPromises); } this.spinner.succeed(`\u6279\u91CF\u7F13\u5B58\u8BBE\u7F6E\u5B8C\u6210 (${items.length} \u9879)`); } catch (error) { this.spinner.fail(`\u6279\u91CF\u7F13\u5B58\u8BBE\u7F6E\u5931\u8D25`); console.error(import_chalk3.default.red("\u6279\u91CF\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 事务性设置缓存 */ async setTransaction(operations) { this.spinner.start(`\u6267\u884C\u7F13\u5B58\u4E8B\u52A1 (${operations.length} \u4E2A\u64CD\u4F5C)`); try { for (const operation of operations) { if (operation.type === "set") { await this.localCache.set( operation.key, operation.value, operation.options || {} ); } else if (operation.type === "delete") { await this.localCache.delete(operation.key); } } if (this.cloudCache && this.config.strategy.autoSync) { for (const operation of operations) { if (operation.type === "set") { await this.cloudCache.set( operation.key, operation.value, operation.options || {} ); } else if (operation.type === "delete") { await this.cloudCache.delete(operation.key); } } } this.spinner.succeed(`\u7F13\u5B58\u4E8B\u52A1\u6267\u884C\u5B8C\u6210 (${operations.length} \u4E2A\u64CD\u4F5C)`); } catch (error) { this.spinner.fail(`\u7F13\u5B58\u4E8B\u52A1\u6267\u884C\u5931\u8D25`); console.error(import_chalk3.default.red("\u4E8B\u52A1\u9519\u8BEF:"), error); throw error; } } /** * 批量获取缓存 */ async getBatch(keys) { this.spinner.start(`\u6279\u91CF\u83B7\u53D6\u7F13\u5B58 (${keys.length} \u9879)`); try { const results = /* @__PURE__ */ new Map(); const localPromises = keys.map(async (key) => { const item = await this.localCache.get(key); if (item) { results.set(key, item.value); } return { key, item }; }); const localResults = await Promise.all(localPromises); if (this.cloudCache) { const missedKeys = localResults.filter((result) => !result.item).map((result) => result.key); if (missedKeys.length > 0) { const cloudPromises = missedKeys.map(async (key) => { const item = await this.cloudCache.get(key); if (item) { await this.localCache.set(key, item.value, item.meta); results.set(key, item.value); } return { key, item }; }); await Promise.all(cloudPromises); } } this.spinner.succeed( `\u6279\u91CF\u7F13\u5B58\u83B7\u53D6\u5B8C\u6210 (${keys.length} \u9879, \u547D\u4E2D ${results.size} \u9879)` ); return results; } catch (error) { this.spinner.fail(`\u6279\u91CF\u7F13\u5B58\u83B7\u53D6\u5931\u8D25`); console.error(import_chalk3.default.red("\u6279\u91CF\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 删除缓存 */ async delete(key) { this.spinner.start(`\u5220\u9664\u7F13\u5B58: ${key}`); try { await this.localCache.delete(key); if (this.cloudCache) { await this.cloudCache.delete(key); } this.spinner.succeed(`\u7F13\u5B58\u5220\u9664\u5B8C\u6210: ${key}`); } catch (error) { this.spinner.fail(`\u5220\u9664\u7F13\u5B58\u5931\u8D25: ${key}`); console.error(import_chalk3.default.red("\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 批量删除缓存 */ async deleteBatch(keys) { this.spinner.start(`\u6279\u91CF\u5220\u9664\u7F13\u5B58 (${keys.length} \u9879)`); try { const localPromises = keys.map((key) => this.localCache.delete(key)); await Promise.all(localPromises); if (this.cloudCache && this.config.strategy.autoSync) { const cloudPromises = keys.map((key) => this.cloudCache.delete(key)); await Promise.all(cloudPromises); } this.spinner.succeed(`\u6279\u91CF\u7F13\u5B58\u5220\u9664\u5B8C\u6210 (${keys.length} \u9879)`); } catch (error) { this.spinner.fail(`\u6279\u91CF\u7F13\u5B58\u5220\u9664\u5931\u8D25`); console.error(import_chalk3.default.red("\u6279\u91CF\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 清空缓存 */ async clear() { this.spinner.start("\u6E05\u7A7A\u6240\u6709\u7F13\u5B58..."); try { await this.localCache.clear(); if (this.cloudCache) { await this.cloudCache.clear(); } this.spinner.succeed("\u6240\u6709\u7F13\u5B58\u5DF2\u6E05\u7A7A"); } catch (error) { this.spinner.fail("\u6E05\u7A7A\u7F13\u5B58\u5931\u8D25"); console.error(import_chalk3.default.red("\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 获取缓存统计 */ async getStats() { this.spinner.start("\u83B7\u53D6\u7F13\u5B58\u7EDF\u8BA1..."); try { const localStats = await this.localCache.getStats(); if (this.cloudCache) { const cloudStats = await this.cloudCache.getStats(); const combinedStats = { totalItems: localStats.totalItems + cloudStats.totalItems, totalSize: localStats.totalSize + cloudStats.totalSize, hits: localStats.hits + cloudStats.hits, misses: localStats.misses + cloudStats.misses, hitRate: localStats.hitRate, // 使用本地命中率 avgAccessTime: localStats.avgAccessTime, // 使用本地平均时间 topItems: [...localStats.topItems, ...cloudStats.topItems].sort((a, b) => b.accessCount - a.accessCount).slice(0, 10) }; this.spinner.succeed("\u7F13\u5B58\u7EDF\u8BA1\u83B7\u53D6\u5B8C\u6210"); return combinedStats; } this.spinner.succeed("\u672C\u5730\u7F13\u5B58\u7EDF\u8BA1\u83B7\u53D6\u5B8C\u6210"); return localStats; } catch (error) { this.spinner.fail("\u83B7\u53D6\u7F13\u5B58\u7EDF\u8BA1\u5931\u8D25"); console.error(import_chalk3.default.red("\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 预热缓存 */ async warmup(keys) { this.spinner.start(`\u9884\u70ED ${keys.length} \u4E2A\u7F13\u5B58...`); try { const warmupPromises = keys.map(async (key) => { try { await this.get(key); } catch (error) { console.warn(import_chalk3.default.yellow(`\u9884\u70ED\u7F13\u5B58\u5931\u8D25: ${key}`), error); } }); await Promise.all(warmupPromises); this.spinner.succeed(`\u7F13\u5B58\u9884\u70ED\u5B8C\u6210: ${keys.length} \u4E2A`); } catch (error) { this.spinner.fail("\u7F13\u5B58\u9884\u70ED\u5931\u8D25"); console.error(import_chalk3.default.red("\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 清理过期缓存 */ async cleanup() { this.spinner.start("\u6E05\u7406\u8FC7\u671F\u7F13\u5B58..."); try { const keys = await this.localCache.keys(); let cleanedCount = 0; for (const key of keys) { const item = await this.localCache.get(key); if (!item) { await this.localCache.delete(key); cleanedCount++; } } this.spinner.succeed(`\u8FC7\u671F\u7F13\u5B58\u6E05\u7406\u5B8C\u6210: ${cleanedCount} \u4E2A`); } catch (error) { this.spinner.fail("\u6E05\u7406\u8FC7\u671F\u7F13\u5B58\u5931\u8D25"); console.error(import_chalk3.default.red("\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 导出缓存 */ async export() { this.spinner.start("\u5BFC\u51FA\u7F13\u5B58..."); try { const keys = await this.localCache.keys(); const exportData = { version: "1.0.0", timestamp: Date.now(), config: this.config, items: [] }; for (const key of keys) { const item = await this.localCache.get(key); if (item) { exportData.items.push({ key, item }); } } const buffer = Buffer.from(JSON.stringify(exportData, null, 2)); this.spinner.succeed(`\u7F13\u5B58\u5BFC\u51FA\u5B8C\u6210: ${buffer.length} \u5B57\u8282`); return buffer; } catch (error) { this.spinner.fail("\u5BFC\u51FA\u7F13\u5B58\u5931\u8D25"); console.error(import_chalk3.default.red("\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } /** * 导入缓存 */ async import(data) { this.spinner.start("\u5BFC\u5165\u7F13\u5B58..."); try { const importData = JSON.parse(data.toString()); if (importData.version !== "1.0.0") { throw new Error(`\u4E0D\u652F\u6301\u7684\u7F13\u5B58\u7248\u672C: ${importData.version}`); } let importedCount = 0; for (const { key, item } of importData.items) { await this.localCache.set(key, item.value, item.meta); importedCount++; } this.spinner.succeed(`\u7F13\u5B58\u5BFC\u5165\u5B8C\u6210: ${importedCount} \u4E2A`); } catch (error) { this.spinner.fail("\u5BFC\u5165\u7F13\u5B58\u5931\u8D25"); console.error(import_chalk3.default.red("\u7F13\u5B58\u9519\u8BEF:"), error); throw error; } } }; // src/cache-version-manager.ts var import_fs_extra3 = __toESM(require("fs-extra")); var import_path2 = require("path"); var import_crypto3 = require("crypto"); var import_chalk4 = __toESM(require("chalk")); var import_ora4 = __toESM(require("ora")); var CacheVersionManager = class { constructor(versionDir = ".synthia-cache/versions") { this.dependencyGraph = /* @__PURE__ */ new Map(); this.versionHistory = /* @__PURE__ */ new Map(); this.spinner = (0, import_ora4.default)(); this.versionDir = versionDir; this.ensureVersionDir(); this.loadDependencyGraph(); this.loadVersionHistory(); } /** * 计算文件或内容的哈希值 */ calculateHash(content) { const hash = (0, import_crypto3.createHash)("sha256"); hash.update(content); return hash.digest("hex"); } /** * 计算文件哈希值 */ calculateFileHash(filePath) { try { const content = import_fs_extra3.default.readFileSync(filePath, "utf-8"); return this.calculateHash(content); } catch (error) { console.warn(import_chalk4.default.yellow(`\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6 ${filePath}: ${error}`)); return ""; } } /** * 计算依赖文件的哈希值 */ calculateDependenciesHash(dependencies) { const hashes = dependencies.map((dep) => this.calculateFileHash(dep)).filter(Boolean); return this.calculateHash(hashes.join("|")); } /** * 检查缓存是否有效 */ isCacheValid(key, dependencies, currentHash) { const cacheMeta = this.getCacheMeta(key); if (!cacheMeta) { return false; } if (cacheMeta.expiresAt < Date.now()) { return false; } const currentDepsHash = this.calculateDependenciesHash(dependencies); if (cacheMeta.dependenciesHash !== currentDepsHash) { return false; } if (currentHash && cacheMeta.hash !== currentHash) { return false; } return true; } /** * 更新缓存版本信息 */ updateCacheVersion(key, value, dependencies, tags = [], version = "1.0.0") { const hash = this.calculateHash(JSON.stringify(value)); const dependenciesHash = this.calculateDependenciesHash(dependencies); const size = JSON.stringify(value).length; const meta = { hash, size, expiresAt: Date.now() + 7 * 24 * 60 * 60 * 1e3, // 7天 dependencies, tags, version, dependenciesHash, createdAt: Date.now(), lastModified: Date.now() }; this.saveCacheMeta(key, meta); this.updateDependencyGraph(key, dependencies); this.updateVersionHistory(key, hash); return meta; } /** * 获取受影响的缓存键 */ getAffectedCacheKeys(changedFiles) { const affectedKeys = /* @__PURE__ */ new Set(); for (const file of changedFiles) { for (const [key, deps] of this.dependencyGraph.entries()) { if (deps.has(file)) { affectedKeys.add(key); } } } return Array.from(affectedKeys); } /** * 清理无效的缓存版本 */ cleanupInvalidVersions() { this.spinner.start("\u6E05\u7406\u65E0\u6548\u7684\u7F13\u5B58\u7248\u672C..."); try { let cleanedCount = 0; const currentTime = Date.now(); for (const [key, versions] of this.versionHistory.entries()) { const cacheMeta = this.getCacheMeta(key); if (!cacheMeta) { continue; } const validVersions = /* @__PURE__ */ new Set([cacheMeta.hash]); const cleanedVersions = versions.filter((version) => { if (validVersions.has(version)) { return true; } const versionPath = this.getVersionPath(key, version); if (import_fs_extra3.default.existsSync(versionPath)) { const stats = require("fs").statSync(versionPath); const age = currentTime - stats.mtime.getTime(); if (age > 30 * 24 * 60 * 60 * 1e3) { require("fs").unlinkSync(versionPath); cleanedCount++; return false; } } return true; }); if (cleanedVersions.length !== versions.length) { this.versionHistory.set(key, cleanedVersions); } } this.saveVersionHistory(); this.spinner.succeed(`\u6E05\u7406\u5B8C\u6210\uFF0C\u5220\u9664\u4E86 ${cleanedCount} \u4E2A\u65E0\u6548\u7248\u672C`); } catch (error) { this.spinner.fail("\u6E05\u7406\u65E0\u6548\u7248\u672C\u5931\u8D25"); console.error(import_chalk4.default.red("\u6E05\u7406\u9519\u8BEF:"), error); } } /** * 获取缓存统计信息 */ getVersionStats() { const totalKeys = this.versionHistory.size; const totalVersions = Array.from(this.versionHistory.values()).reduce( (sum, versions) => sum + versions.length, 0 ); const dependencyGraphSize = this.dependencyGraph.size; const averageVersionsPerKey = totalKeys > 0 ? totalVersions / totalKeys : 0; return { totalKeys, totalVersions, dependencyGraphSize, averageVersionsPerKey }; } /** * 导出版本信息 */ exportVersionInfo() { const versionInfo = { dependencyGraph: Object.fromEntries(this.dependencyGraph), versionHistory: Object.fromEntries(this.versionHistory), timestamp: Date.now() }; return Buffer.from(JSON.stringify(versionInfo, null, 2)); } /** * 导入版本信息 */ importVersionInfo(data) { try { const versionInfo = JSON.parse(data.toString()); this.dependencyGraph = new Map( Object.entries(versionInfo.dependencyGraph) ); this.versionHistory = new Map(Object.entries(versionInfo.versionHistory)); this.saveDependencyGraph(); this.saveVersionHistory(); console.log(import_chalk4.default.green("\u7248\u672C\u4FE1\u606F\u5BFC\u5165\u6210\u529F")); } catch (error) { console.error(import_chalk4.default.red("\u7248\u672C\u4FE1\u606F\u5BFC\u5165\u5931\u8D25:"), error); throw error; } } /** * 获取缓存元信息 */ getCacheMeta(key) { const metaPath = (0, import_path2.join)(this.versionDir, `${key}.meta.json`); if (!import_fs_extra3.default.existsSync(metaPath)) { return null; } try { return JSON.parse(import_fs_extra3.default.readFileSync(metaPath, "utf-8")); } catch (error) { return null; } } /** * 保存缓存元信息 */ saveCacheMeta(key, meta) { const metaPath = (0, import_path2.join)(this.versionDir, `${key}.meta.json`); import_fs_extra3.default.writeFileSync(metaPath, JSON.stringify(meta, null, 2)); } /** * 更新依赖图 */ updateDependencyGraph(key, dependencies) { this.dependencyGraph.set(key, new Set(dependencies)); this.saveDependencyGraph(); } /** * 更新版本历史 */ updateVersionHistory(key, hash) { const versions = this.versionHistory.get(key) || []; if (!versions.includes(hash)) { versions.push(hash); this.versionHistory.set(key, versions); this.saveVersionHistory(); } } /** * 获取版本路径 */ getVersionPath(key, version) { return (0, import_path2.join)(this.versionDir, `${key}.${version}.cache`); } /** * 确保版本目录存在 */ ensureVersionDir() { if (!import_fs_extra3.default.existsSync(this.versionDir)) { import_fs_extra3.default.mkdirSync(this.versionDir, { recursive: true }); } } /** * 加载依赖图 */ loadDependencyGraph() { const graphPath = (0, import_path2.join)(this.versionDir, "dependency-graph.json"); if (import_fs_extra3.default.existsSync(graphPath)) { try { const graphData = JSON.parse(import_fs_extra3.default.readFileSync(graphPath, "utf-8")); this.dependencyGraph = new Map(Object.entries(graphData)); } catch (error) { console.warn(import_chalk4.default.yellow("\u65E0\u6CD5\u52A0\u8F7D\u4F9D\u8D56\u56FE\uFF0C\u5C06\u91CD\u65B0\u521B\u5EFA")); } } } /** * 保存依赖图 */ saveDependencyGraph() { const graphPath = (0, import_path2.join)(this.versionDir, "dependency-graph.json"); const graphData = Object.fromEntries(this.dependencyGraph); import_fs_extra3.default.writeFileSync(graphPath, JSON.stringify(graphData, null, 2)); } /** * 加载版本历史 */ loadVersionHistory() { const historyPath = (0, import_path2.join)(this.versionDir, "version-history.json"); if (import_fs_extra3.default.existsSync(historyPath)) { try { const historyData = JSON.parse(import_fs_extra3.default.readFileSync(historyPath, "utf-8")); this.versionHistory = new Map(Object.entries(historyData)); } catch (error) { console.warn(import_chalk4.default.yellow("\u65E0\u6CD5\u52A0\u8F7D\u7248\u672C\u5386\u53F2\uFF0C\u5C06\u91CD\u65B0\u521B\u5EFA")); } } } /** * 保存版本历史 */ saveVersionHistory() { const historyPath = (0, import_path2.join)(this.versionDir, "version-history.json"); const historyData = Object.fromEntries(this.versionHistory); import_fs_extra3.default.writeFileSync(historyPath, JSON.stringify(historyData, null, 2)); } }; // src/cache-compressor.ts var import_zlib = require("zlib"); var import_util = require("util"); var import_chalk5 = __toESM(require("chalk")); var import_ora5 = __toESM(require("ora")); var gzipAsync = (0, import_util.promisify)(import_zlib.gzip); var gunzipAsync = (0, import_util.promisify)(import_zlib.gunzip); // src/cache-strategy-manager.ts var import_chalk6 = __toESM(require("chalk")); var import_ora6 = __toESM(require("ora")); var CacheStrategyManager = class { constructor(cacheManager2) { this.spinner = (0, import_ora6.default)(); this.cleanupThresholds = { maxSize: 500 * 1024 * 1024, // 500MB maxItems: 1e4, maxAge: 30 * 24 * 60 * 60 * 1e3, // 30天 lowHitRate: 0.3 // 30% }; this.cacheManager = cacheManager2; } /** * 预热缓存 */ async warmup(keys) { this.spinner.start(`\u9884\u70ED\u7F13\u5B58 (${keys.length} \u9879)...`); try { const startTime = Date.now(); let successCount = 0; let failCount = 0; const promises = keys.map(async (key) => { try { const value = await this.cacheManager.get(key); if (value) { successCount++; } else { failCount++; } } catch (error) { failCount++; console.warn(import_chalk6.default.yellow(`\u9884\u70ED\u7F13\u5B58\u5931\u8D25: ${key}`), error); } }); await Promise.all(promises); const duration = Date.now() - startTime; this.spinner.succeed( `\u7F13\u5B58\u9884\u70ED\u5B8C\u6210 (${successCount} \u6210\u529F, ${failCount} \u5931\u8D25, ${duration}ms)` ); } catch (error) { this.spinner.fail("\u7F13\u5B58\u9884\u70ED\u5931\u8D25"); console.error(import_chalk6.default.red("\u9884\u70ED\u9519\u8BEF:"), error); throw error; } } /** * 智能清理缓存 */ async smartCleanup() { this.spinner.start("\u6267\u884C\u667A\u80FD\u7F13\u5B58\u6E05\u7406..."); try { const stats = await this.cacheManager.getStats(); const cleanupStrategy = this.selectCleanupStrategy(stats); let cleanedItems = 0; let freedSpace = 0; switch (cleanupStrategy.type) { case "size-based": const sizeResult = await this.cleanupBySize( cleanupStrategy.threshold ); cleanedItems = sizeResult.cleanedItems; freedSpace = sizeResult.freedSpace; break; case "age-based": const ageResult = await this.cleanupByAge(cleanupStrategy.threshold); cleanedItems = ageResult.cleanedItems; freedSpace = ageResult.freedSpace; break; case "hit-rate-based": const hitRateResult = await this.cleanupByHitRate( cleanupStrategy.threshold ); cleanedItems = hitRateResult.cleanedItems; freedSpace = hitRateResult.freedSpace; break; case "frequency-based": const freqResult = await this.cleanupByFrequency( cleanupStrategy.threshold ); cleanedItems = freqResult.cleanedItems; freedSpace = freqResult.freedSpace; break; } this.spinner.succeed( `\u667A\u80FD\u6E05\u7406\u5B8C\u6210 (${cleanedItems} \u9879, ${this.formatBytes(freedSpace)})` ); return { cleanedItems, freedSpace, strategy: cleanupStrategy.type }; } catch (error) { this.spinner.fail("\u667A\u80FD\u6E05\u7406\u5931\u8D25"); console.error(import_chalk6.default.red("\u6E05\u7406\u9519\u8BEF:"), error); throw error; } } /** * 清理过期缓存 */ async cleanupExpired() { this.spinner.start("\u6E05\u7406\u8FC7\u671F\u7F13\u5B58..."); try { let cleanedItems = 0; let freedSpace = 0; await this.cacheManager.cleanup(); this.spinner.succeed("\u8FC7\u671F\u7F13\u5B58\u6E05\u7406\u5B8C\u6210"); return { cleanedItems, freedSpace }; } catch (error) { this.spinner.fail("\u8FC7\u671F\u7F13\u5B58\u6E05\u7406\u5931\u8D25"); console.error(import_chalk6.default.red("\u6E05\u7406\u9519\u8BEF:"), error); throw error; } } /** * 优化缓存策略 */ async optimizeStrategy() { this.spinner.start("\u5206\u6790\u7F13\u5B58\u7B56\u7565..."); try { const stats = await this.cacheManager.getStats(); const recommendations = []; let estimatedImprovement = 0; if (stats.hitRate < 0.5) { recommendations.push("\u547D\u4E2D\u7387\u8F83\u4F4E\uFF0C\u5EFA\u8BAE\u589E\u52A0\u7F13\u5B58\u9884\u70ED"); estimatedImprovement += 0.1; } if (stats.totalSize > this.cleanupThresholds.maxSize) { recommendations.push("\u7F13\u5B58\u5927\u5C0F\u8FC7\u5927\uFF0C\u5EFA\u8BAE\u542F\u7528\u667A\u80FD\u6E05\u7406"); estimatedImprovement += 0.05; } if (stats.topItems.length > 0) { const topItemAccessCount = stats.topItems[0].accessCount; const avgAccessCount = stats.topItems.reduce( (sum, item) => sum + item.accessCount, 0 ) / stats.topItems.length; if (topItemAccessCount > avgAccessCount * 3) { recommendations.push("\u8BBF\u95EE\u6A21\u5F0F\u4E0D\u5747\u5300\uFF0C\u5EFA\u8BAE\u4F18\u5316\u7F13\u5B58\u952E\u5206\u5E03"); estimatedImprovement += 0.08; } } if (stats.avgAccessTime > 100) { recommendations.push("\u5E73\u5747\u8BBF\u95EE\u65F6\u95F4\u8FC7\u957F\uFF0C\u5EFA\u8BAE\u4F18\u5316\u7F13\u5B58\u5B58\u50A8"); estimatedImprovement += 0.12; } this.spinner.succeed(`\u7B56\u7565\u5206\u6790\u5B8C\u6210 (${recommendations.length} \u6761\u5EFA\u8BAE)`); return { recommendations, estimatedImprovement: Math.min(estimatedImprovement, 0.3) // 最多30%的改进 }; } catch (error) { this.spinner.fail("\u7B56\u7565\u5206\u6790\u5931\u8D25"); console.error(import_chalk6.default.red("\u5206\u6790\u9519\u8BEF:"), error); throw error; } } /** * 批量预热缓存 */ async batchWarmup(warmupGroups) { this.spinner.start(`\u6279\u91CF\u9884\u70ED\u7F13\u5B58 (${warmupGroups.length} \u7EC4)...`); try { const sortedGroups = warmupGroups.sort((a, b) => { const priorityOrder = { high: 3, medium: 2, low: 1 }; return priorityOrder[b.priority] - priorityOrder[a.priority]; }); for (const group of sortedGroups) { const timeout = group.timeout || 3e4; try { await Promise.race([ this.warmup(group.keys), new Promise( (_, reject) => setTimeout(() => reject(new Error("\u9884\u70ED\u8D85\u65F6")), timeout) ) ]); } catch (error) { console.warn(import_chalk6.default.yellow(`\u9884\u70ED\u7EC4\u5931\u8D25 (${group.priority}):`), error); } } this.spinner.succeed("\u6279\u91CF\u9884\u70ED\u5B8C\u6210"); } catch (error) { this.spinner.fail("\u6279\u91CF\u9884\u70ED\u5931\u8D25"); console.error(import_chalk6.default.red("\u6279\u91CF\u9884\u70ED\u9519\u8BEF:"), error); throw error; } } /** * 选择清理策略 */ selectCleanupStrategy(stats) { if (stats.totalSize > this.cleanupThresholds.maxSize) { return { type: "size-based", threshold: this.cleanupThresholds.maxSize * 0.8 // 清理到80% }; } if (stats.hitRate < this.cleanupThresholds.lowHitRate) { return { type: "hit-rate-based", threshold: this.cleanupThresholds.lowHitRate }; } if (stats.topItems.length > 0) { const avgAccessCount = stats.topItems.reduce((sum, item) => sum + item.accessCount, 0) / stats.topItems.length; return { type: "frequency-based", threshold: avgAccessCount * 0.5 // 清理访问次数低于平均值50%的缓存 }; } return { type: "age-based", threshold: this.cleanupThresholds.maxAge }; } /** * 基于大小的清理 */ async cleanupBySize(_threshold) { return { cleanedItems: 0, freedSpace: 0 }; } /** * 基于年龄的清理 */ async cleanupByAge(_threshold) { return { cleanedItems: 0, freedSpace: 0 }; } /** * 基于命中率的清理 */ async cleanupByHitRate(_threshold) { return { cleanedItems: 0, freedSpace: 0 }; } /** * 基于访问频率的清理 */ async cleanupByFrequency(_threshold) { return { cleanedItems: 0, freedSpace: 0 }; } /** * 格式化字节大小 */ formatBytes(bytes) { if (by