pm-orchestrator-enhancement
Version:
PM Orchestrator Enhancement - Multi-agent parallel execution system
229 lines • 7.12 kB
JavaScript
"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