@mdfriday/foundry
Version:
The core engine of MDFriday. Convert Markdown and shortcodes into fully themed static sites – Hugo-style, powered by TypeScript.
175 lines • 5.18 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.globalBuildCache = exports.ConcurrentCache = void 0;
exports.createCache = createCache;
const log_1 = require("../log");
const log = (0, log_1.getDomainLogger)('content', { component: 'cache' });
/**
* 并发安全的缓存实现,专为站点构建场景优化
* 支持多个页面并发访问时避免重复创建相同对象
*/
class ConcurrentCache {
constructor() {
this.cache = new Map();
this.pendingPromises = new Map();
this.deletedKeys = new Set();
// 简化构造函数,移除重试相关参数
}
/**
* Get value from cache
*/
get(key) {
return this.cache.get(key);
}
/**
* Set value in cache
*/
set(key, value) {
// 如果key已被标记为删除,则不设置缓存
if (!this.deletedKeys.has(key)) {
this.cache.set(key, value);
}
// 清理对应的pending promise和删除标记
this.pendingPromises.delete(key);
this.deletedKeys.delete(key);
}
/**
* Check if key exists in cache
*/
has(key) {
return this.cache.has(key);
}
/**
* Check if key is currently being created
*/
isPending(key) {
return this.pendingPromises.has(key);
}
/**
* Remove key from cache
*/
delete(key) {
// 标记key为已删除
this.deletedKeys.add(key);
this.pendingPromises.delete(key);
return this.cache.delete(key);
}
/**
* Clear all cache entries and pending promises
*/
clear() {
this.cache.clear();
this.pendingPromises.clear();
this.deletedKeys.clear();
}
/**
* Get cache size
*/
size() {
return this.cache.size;
}
/**
* Get pending promises count
*/
pendingCount() {
return this.pendingPromises.size;
}
/**
* 并发安全的获取或创建值
* 如果多个并发请求访问同一个key,只会创建一次
*/
async getOrCreate(key, create) {
// 1. 首先检查缓存
const cached = this.cache.get(key);
if (cached !== undefined) {
return cached;
}
// 2. 检查是否有正在进行的创建过程
const pending = this.pendingPromises.get(key);
if (pending) {
return await pending;
}
// 3. 创建新的promise并缓存它
return this.createAndCache(key, create);
}
/**
* 创建并缓存值
*/
async createAndCache(key, create) {
const promise = this.executeCreate(key, create);
this.pendingPromises.set(key, promise);
try {
const value = await promise;
// 检查在创建过程中key是否被删除了
if (!this.deletedKeys.has(key)) {
this.set(key, value);
return value;
}
else {
// key已被删除,不缓存结果但清理删除标记
this.deletedKeys.delete(key);
this.pendingPromises.delete(key);
return value;
}
}
catch (error) {
// 创建失败时清理pending promise
this.pendingPromises.delete(key);
log.error(`Failed to create value for key ${String(key)} : ${error}`);
throw error;
}
}
/**
* 执行创建函数,包装错误处理
*/
async executeCreate(key, create) {
try {
return await create(key);
}
catch (error) {
// 包装原始错误,添加更多上下文
const errorMessage = error instanceof Error ? error.message : String(error);
const wrappedError = new Error(`Cache creation failed for key ${String(key)}: ${errorMessage}`);
if (error instanceof Error && error.stack) {
wrappedError.stack = error.stack;
// 添加原始错误信息到wrappedError上,但不使用cause属性
wrappedError.originalError = error;
}
throw wrappedError;
}
}
/**
* 获取缓存统计信息
*/
getStats() {
return {
size: this.cache.size,
pendingCount: this.pendingPromises.size,
keys: Array.from(this.cache.keys()),
pendingKeys: Array.from(this.pendingPromises.keys())
};
}
/**
* 批量预加载数据
*/
async preload(entries) {
const promises = entries
.filter(({ key }) => !this.has(key) && !this.isPending(key))
.map(({ key, create }) => this.getOrCreate(key, create));
if (promises.length > 0) {
await Promise.allSettled(promises);
}
}
}
exports.ConcurrentCache = ConcurrentCache;
/**
* 创建一个新的并发缓存实例
*/
function createCache() {
return new ConcurrentCache();
}
/**
* 全局缓存实例,用于站点构建时的数据共享
*/
exports.globalBuildCache = new ConcurrentCache();
//# sourceMappingURL=cache.js.map