UNPKG

pm-orchestrator-enhancement

Version:

PM Orchestrator Enhancement - Multi-agent parallel execution system

229 lines 7.12 kB
"use strict"; /** * File Cache Module * * TTLベースのファイル内容キャッシュ機能を提供します。 */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.FileCache = void 0; const fs = __importStar(require("fs")); const path = __importStar(require("path")); const crypto = __importStar(require("crypto")); class FileCache { constructor(defaultTTL = 300000) { this.cache = new Map(); this.defaultTTL = defaultTTL; } /** * ファイル内容を取得(キャッシュまたは読み込み) */ get(filePath, ttl) { const absolutePath = path.resolve(filePath); const cacheKey = this.getCacheKey(absolutePath); // キャッシュをチェック const cached = this.cache.get(cacheKey); if (cached && this.isValid(cached)) { // ファイルが変更されていないかチェック if (this.hasFileChanged(absolutePath, cached.hash)) { // 変更されている場合は再読み込み return this.load(absolutePath, ttl); } return cached.content; } // キャッシュにない、または期限切れの場合は読み込み return this.load(absolutePath, ttl); } /** * ファイルを読み込んでキャッシュ */ load(filePath, ttl) { const absolutePath = path.resolve(filePath); if (!fs.existsSync(absolutePath)) { return null; } try { const content = fs.readFileSync(absolutePath, 'utf-8'); const hash = this.calculateHash(content); const effectiveTTL = ttl ?? this.defaultTTL; const entry = { content, hash, cachedAt: new Date(), expiresAt: new Date(Date.now() + effectiveTTL), filePath: absolutePath }; const cacheKey = this.getCacheKey(absolutePath); this.cache.set(cacheKey, entry); return content; } catch (error) { console.error(`Failed to read file: ${absolutePath}`, error); return null; } } /** * キャッシュを無効化 */ invalidate(filePath) { const absolutePath = path.resolve(filePath); const cacheKey = this.getCacheKey(absolutePath); return this.cache.delete(cacheKey); } /** * 全てのキャッシュをクリア */ clear() { this.cache.clear(); } /** * 期限切れエントリをクリーンアップ */ cleanup() { const now = new Date(); let removed = 0; for (const [key, entry] of this.cache.entries()) { if (entry.expiresAt < now) { this.cache.delete(key); removed++; } } return removed; } /** * キャッシュエントリが有効かチェック */ isValid(entry) { return entry.expiresAt > new Date(); } /** * ファイルが変更されたかチェック */ hasFileChanged(filePath, cachedHash) { if (!fs.existsSync(filePath)) { return true; } try { const content = fs.readFileSync(filePath, 'utf-8'); const currentHash = this.calculateHash(content); return currentHash !== cachedHash; } catch (error) { return true; } } /** * コンテンツのハッシュを計算 */ calculateHash(content) { return crypto.createHash('sha256').update(content).digest('hex'); } /** * キャッシュキーを生成 */ getCacheKey(filePath) { return filePath; } /** * キャッシュサイズを取得 */ size() { return this.cache.size; } /** * キャッシュ統計を取得 */ getStats() { const now = new Date(); let valid = 0; let expired = 0; let totalSize = 0; for (const entry of this.cache.values()) { if (entry.expiresAt > now) { valid++; } else { expired++; } totalSize += entry.content.length; } return { total: this.cache.size, valid, expired, totalSize }; } /** * 複数ファイルを一括読み込み */ loadMultiple(filePaths, ttl) { const results = new Map(); for (const filePath of filePaths) { const content = this.get(filePath, ttl); if (content !== null) { results.set(filePath, content); } } return results; } /** * ファイルパターンに一致するファイルをキャッシュ */ preload(directory, pattern, ttl) { let loaded = 0; const loadDirectory = (dir) => { if (!fs.existsSync(dir)) { return; } const entries = fs.readdirSync(dir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { loadDirectory(fullPath); } else if (pattern.test(entry.name)) { if (this.load(fullPath, ttl) !== null) { loaded++; } } } }; loadDirectory(directory); return loaded; } } exports.FileCache = FileCache; //# sourceMappingURL=file-cache.js.map