synthia-cache-system
Version:
Synthia Engine Cache System - 核心缓存系统实现,提供多级缓存、版本管理、性能监控等功能
1,546 lines (1,537 loc) • 96.3 kB
JavaScript
"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