UNPKG

@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
"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