vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
756 lines (755 loc) • 32.6 kB
JavaScript
import { EventEmitter } from 'events';
import { promises as fs } from 'fs';
const { writeFile, unlink } = fs;
import { join } from 'path';
import { getVibeTaskManagerOutputDir } from '../utils/config-loader.js';
import { ErrorFactory, createErrorContext } from '../utils/enhanced-errors.js';
import { createSuccess, createFailure } from './unified-lifecycle-manager.js';
import logger from '../../../logger.js';
export function createStorageId(id) {
if (!id || id.trim().length === 0) {
throw new Error('Storage ID cannot be empty');
}
return id;
}
export function createTransactionId(id) {
if (!id || id.trim().length === 0) {
throw new Error('Transaction ID cannot be empty');
}
return id;
}
export function createBackupId(id) {
if (!id || id.trim().length === 0) {
throw new Error('Backup ID cannot be empty');
}
return id;
}
export function createCacheKey(key) {
if (!key || key.trim().length === 0) {
throw new Error('Cache key cannot be empty');
}
return key;
}
export class UnifiedStorageEngine extends EventEmitter {
static instance = null;
config;
dataDirectory;
initialized = false;
cache = new Map();
transactions = new Map();
backups = new Map();
taskIndex = { tasks: [], lastUpdated: '', version: '1.0.0' };
projectIndex = { projects: [], lastUpdated: '', version: '1.0.0' };
dependencyIndex = { dependencies: [], lastUpdated: '', version: '1.0.0' };
epicIndex = { epics: [], lastUpdated: '', version: '1.0.0' };
operationCount = 0;
operationsByType = new Map();
operationsByEntity = new Map();
totalResponseTime = 0;
cacheHits = 0;
cacheRequests = 0;
backupTimer = null;
cacheCleanupTimer = null;
metricsTimer = null;
constructor(config) {
super();
this.config = config;
this.dataDirectory = config.dataDirectory;
['create', 'read', 'update', 'delete', 'list', 'search'].forEach(op => {
this.operationsByType.set(op, 0);
});
['task', 'project', 'dependency', 'epic', 'graph'].forEach(entity => {
this.operationsByEntity.set(entity, 0);
});
logger.info('Unified Storage Engine initialized');
}
static getInstance(config) {
if (!UnifiedStorageEngine.instance) {
if (!config) {
throw new Error('Configuration required for first initialization');
}
UnifiedStorageEngine.instance = new UnifiedStorageEngine(config);
}
return UnifiedStorageEngine.instance;
}
static resetInstance() {
if (UnifiedStorageEngine.instance) {
UnifiedStorageEngine.instance.dispose();
UnifiedStorageEngine.instance = null;
}
}
async initialize() {
if (this.initialized) {
return createSuccess(undefined);
}
try {
await this.createDirectoryStructure();
await this.loadIndexes();
this.startBackgroundProcesses();
this.initialized = true;
this.emit('initialized');
logger.info('Storage engine initialized successfully');
return createSuccess(undefined);
}
catch (error) {
return createFailure(ErrorFactory.createError('system', `Failed to initialize storage engine: ${error instanceof Error ? error.message : 'Unknown error'}`, createErrorContext('UnifiedStorageEngine', 'initialize').build(), { cause: error instanceof Error ? error : undefined }));
}
}
async createDirectoryStructure() {
const directories = [
this.dataDirectory,
join(this.dataDirectory, 'tasks'),
join(this.dataDirectory, 'projects'),
join(this.dataDirectory, 'dependencies'),
join(this.dataDirectory, 'epics'),
join(this.dataDirectory, 'graphs'),
join(this.dataDirectory, 'indexes'),
join(this.dataDirectory, 'backups'),
join(this.dataDirectory, 'cache'),
join(this.dataDirectory, 'logs')
];
for (const dir of directories) {
await fs.mkdir(dir, { recursive: true });
}
}
async loadIndexes() {
const indexDir = join(this.dataDirectory, 'indexes');
try {
const taskIndexPath = join(indexDir, 'tasks.json');
if (await this.fileExists(taskIndexPath)) {
const taskIndexData = await fs.readFile(taskIndexPath, 'utf-8');
this.taskIndex = JSON.parse(taskIndexData);
}
const projectIndexPath = join(indexDir, 'projects.json');
if (await this.fileExists(projectIndexPath)) {
const projectIndexData = await fs.readFile(projectIndexPath, 'utf-8');
this.projectIndex = JSON.parse(projectIndexData);
}
const dependencyIndexPath = join(indexDir, 'dependencies.json');
if (await this.fileExists(dependencyIndexPath)) {
const dependencyIndexData = await fs.readFile(dependencyIndexPath, 'utf-8');
this.dependencyIndex = JSON.parse(dependencyIndexData);
}
const epicIndexPath = join(indexDir, 'epics.json');
if (await this.fileExists(epicIndexPath)) {
const epicIndexData = await fs.readFile(epicIndexPath, 'utf-8');
this.epicIndex = JSON.parse(epicIndexData);
}
logger.info('Storage indexes loaded successfully');
}
catch (error) {
logger.warn('Failed to load some indexes, using defaults:', error);
}
}
startBackgroundProcesses() {
if (this.config.backup.enabled) {
this.backupTimer = setInterval(() => {
this.performBackup().catch(error => {
logger.error('Backup process failed:', error);
});
}, this.config.backup.intervalMinutes * 60 * 1000);
}
if (this.config.cache.enabled) {
this.cacheCleanupTimer = setInterval(() => {
this.cleanupCache();
}, 60 * 1000);
}
if (this.config.monitoring.enableMetrics) {
this.metricsTimer = setInterval(() => {
this.collectMetrics();
}, this.config.monitoring.metricsInterval * 1000);
}
logger.info('Background processes started');
}
async createTask(task) {
const startTime = Date.now();
try {
if (await this.taskExists(task.id)) {
return createFailure(ErrorFactory.createError('validation', `Task already exists: ${task.id}`, createErrorContext('UnifiedStorageEngine', 'createTask')
.metadata({ taskId: task.id })
.build()));
}
const taskDir = join(this.dataDirectory, 'tasks');
await fs.mkdir(taskDir, { recursive: true });
const taskPath = join(taskDir, `${task.id}.json`);
await fs.writeFile(taskPath, JSON.stringify(task, null, 2), 'utf-8');
this.taskIndex.tasks.push({
id: task.id,
title: task.title,
status: task.status,
priority: task.priority,
projectId: task.projectId,
epicId: task.epicId,
estimatedHours: task.estimatedHours,
createdAt: task.createdAt,
updatedAt: task.updatedAt
});
await this.saveTaskIndex();
if (this.config.cache.enabled) {
const cacheKey = createCacheKey(`task:${task.id}`);
this.setCache(cacheKey, task);
}
this.trackOperation('create', 'task', Date.now() - startTime);
this.emit('taskCreated', task);
logger.info(`Task created: ${task.id}`);
return createSuccess(task);
}
catch (error) {
return createFailure(ErrorFactory.createError('system', `Failed to create task: ${error instanceof Error ? error.message : 'Unknown error'}`, createErrorContext('UnifiedStorageEngine', 'createTask')
.metadata({ taskId: task.id })
.build(), { cause: error instanceof Error ? error : undefined }));
}
}
async getTask(taskId) {
const startTime = Date.now();
try {
if (this.config.cache.enabled) {
const cacheKey = createCacheKey(`task:${taskId}`);
const cached = this.getCache(cacheKey);
if (cached) {
this.trackOperation('read', 'task', Date.now() - startTime);
this.cacheHits++;
return createSuccess(cached);
}
this.cacheRequests++;
}
const taskPath = join(this.dataDirectory, 'tasks', `${taskId}.json`);
if (!await this.fileExists(taskPath)) {
return createFailure(ErrorFactory.createError('validation', `Task not found: ${taskId}`, createErrorContext('UnifiedStorageEngine', 'getTask')
.metadata({ taskId })
.build()));
}
const taskData = await fs.readFile(taskPath, 'utf-8');
const task = JSON.parse(taskData);
if (this.config.cache.enabled) {
const cacheKey = createCacheKey(`task:${taskId}`);
this.setCache(cacheKey, task);
}
this.trackOperation('read', 'task', Date.now() - startTime);
return createSuccess(task);
}
catch (error) {
return createFailure(ErrorFactory.createError('system', `Failed to get task: ${error instanceof Error ? error.message : 'Unknown error'}`, createErrorContext('UnifiedStorageEngine', 'getTask')
.metadata({ taskId })
.build(), { cause: error instanceof Error ? error : undefined }));
}
}
async updateTask(taskId, updates) {
const startTime = Date.now();
try {
const getResult = await this.getTask(taskId);
if (!getResult.success) {
return getResult;
}
const existingTask = getResult.data;
const updatedTask = {
...existingTask,
...updates,
id: taskId,
updatedAt: new Date()
};
const taskPath = join(this.dataDirectory, 'tasks', `${taskId}.json`);
await fs.writeFile(taskPath, JSON.stringify(updatedTask, null, 2), 'utf-8');
const indexEntry = this.taskIndex.tasks.find(t => t.id === taskId);
if (indexEntry) {
Object.assign(indexEntry, {
title: updatedTask.title,
status: updatedTask.status,
priority: updatedTask.priority,
projectId: updatedTask.projectId,
epicId: updatedTask.epicId,
estimatedHours: updatedTask.estimatedHours,
updatedAt: updatedTask.updatedAt
});
await this.saveTaskIndex();
}
if (this.config.cache.enabled) {
const cacheKey = createCacheKey(`task:${taskId}`);
this.setCache(cacheKey, updatedTask);
}
this.trackOperation('update', 'task', Date.now() - startTime);
this.emit('taskUpdated', updatedTask);
logger.info(`Task updated: ${taskId}`);
return createSuccess(updatedTask);
}
catch (error) {
return createFailure(ErrorFactory.createError('system', `Failed to update task: ${error instanceof Error ? error.message : 'Unknown error'}`, createErrorContext('UnifiedStorageEngine', 'updateTask')
.metadata({ taskId })
.build(), { cause: error instanceof Error ? error : undefined }));
}
}
async deleteTask(taskId) {
const startTime = Date.now();
try {
if (!await this.taskExists(taskId)) {
return createFailure(ErrorFactory.createError('validation', `Task not found: ${taskId}`, createErrorContext('UnifiedStorageEngine', 'deleteTask')
.metadata({ taskId })
.build()));
}
const taskPath = join(this.dataDirectory, 'tasks', `${taskId}.json`);
await fs.unlink(taskPath);
this.taskIndex.tasks = this.taskIndex.tasks.filter(t => t.id !== taskId);
await this.saveTaskIndex();
if (this.config.cache.enabled) {
const cacheKey = createCacheKey(`task:${taskId}`);
this.cache.delete(cacheKey);
}
this.trackOperation('delete', 'task', Date.now() - startTime);
this.emit('taskDeleted', { taskId });
logger.info(`Task deleted: ${taskId}`);
return createSuccess(undefined);
}
catch (error) {
return createFailure(ErrorFactory.createError('system', `Failed to delete task: ${error instanceof Error ? error.message : 'Unknown error'}`, createErrorContext('UnifiedStorageEngine', 'deleteTask')
.metadata({ taskId })
.build(), { cause: error instanceof Error ? error : undefined }));
}
}
async listTasks(projectId) {
const startTime = Date.now();
try {
let tasks = this.taskIndex.tasks;
if (projectId) {
tasks = tasks.filter(t => t.projectId === projectId);
}
const fullTasks = [];
for (const taskSummary of tasks) {
const taskResult = await this.getTask(taskSummary.id);
if (taskResult.success) {
fullTasks.push(taskResult.data);
}
}
this.trackOperation('list', 'task', Date.now() - startTime);
return createSuccess(fullTasks);
}
catch (error) {
return createFailure(ErrorFactory.createError('system', `Failed to list tasks: ${error instanceof Error ? error.message : 'Unknown error'}`, createErrorContext('UnifiedStorageEngine', 'listTasks')
.metadata({ projectId })
.build(), { cause: error instanceof Error ? error : undefined }));
}
}
async taskExists(taskId) {
const taskPath = join(this.dataDirectory, 'tasks', `${taskId}.json`);
return this.fileExists(taskPath);
}
async createProject(project) {
const startTime = Date.now();
try {
if (await this.projectExists(project.id)) {
return createFailure(ErrorFactory.createError('validation', `Project already exists: ${project.id}`, createErrorContext('UnifiedStorageEngine', 'createProject')
.metadata({ projectId: project.id })
.build()));
}
const projectDir = join(this.dataDirectory, 'projects');
await fs.mkdir(projectDir, { recursive: true });
const projectPath = join(projectDir, `${project.id}.json`);
await fs.writeFile(projectPath, JSON.stringify(project, null, 2), 'utf-8');
this.projectIndex.projects.push({
id: project.id,
name: project.name,
createdAt: project.metadata.createdAt,
updatedAt: project.metadata.updatedAt
});
await this.saveProjectIndex();
if (this.config.cache.enabled) {
const cacheKey = createCacheKey(`project:${project.id}`);
this.setCache(cacheKey, project);
}
this.trackOperation('create', 'project', Date.now() - startTime);
this.emit('projectCreated', project);
logger.info(`Project created: ${project.id}`);
return createSuccess(project);
}
catch (error) {
return createFailure(ErrorFactory.createError('system', `Failed to create project: ${error instanceof Error ? error.message : 'Unknown error'}`, createErrorContext('UnifiedStorageEngine', 'createProject')
.metadata({ projectId: project.id })
.build(), { cause: error instanceof Error ? error : undefined }));
}
}
async getProject(projectId) {
const startTime = Date.now();
try {
if (this.config.cache.enabled) {
const cacheKey = createCacheKey(`project:${projectId}`);
const cached = this.getCache(cacheKey);
if (cached) {
this.trackOperation('read', 'project', Date.now() - startTime);
this.cacheHits++;
return createSuccess(cached);
}
this.cacheRequests++;
}
const projectPath = join(this.dataDirectory, 'projects', `${projectId}.json`);
if (!await this.fileExists(projectPath)) {
return createFailure(ErrorFactory.createError('validation', `Project not found: ${projectId}`, createErrorContext('UnifiedStorageEngine', 'getProject')
.metadata({ projectId })
.build()));
}
const projectData = await fs.readFile(projectPath, 'utf-8');
const project = JSON.parse(projectData);
if (this.config.cache.enabled) {
const cacheKey = createCacheKey(`project:${projectId}`);
this.setCache(cacheKey, project);
}
this.trackOperation('read', 'project', Date.now() - startTime);
return createSuccess(project);
}
catch (error) {
return createFailure(ErrorFactory.createError('system', `Failed to get project: ${error instanceof Error ? error.message : 'Unknown error'}`, createErrorContext('UnifiedStorageEngine', 'getProject')
.metadata({ projectId })
.build(), { cause: error instanceof Error ? error : undefined }));
}
}
async projectExists(projectId) {
const projectPath = join(this.dataDirectory, 'projects', `${projectId}.json`);
return this.fileExists(projectPath);
}
async updateProject(projectId, updates) {
try {
const existingResult = await this.getProject(projectId);
if (!existingResult.success) {
return existingResult;
}
const updatedProject = {
...existingResult.data,
...updates,
metadata: {
...existingResult.data.metadata,
...updates.metadata,
updatedAt: new Date()
}
};
const projectPath = join(this.dataDirectory, 'projects', `${projectId}.json`);
await writeFile(projectPath, JSON.stringify(updatedProject, null, 2), 'utf-8');
const cacheKey = createCacheKey(`project:${projectId}`);
this.setCache(cacheKey, updatedProject);
const existingIndex = this.projectIndex.projects.findIndex(p => p.id === projectId);
const projectIndexEntry = {
id: projectId,
name: updatedProject.name,
createdAt: updatedProject.metadata.createdAt,
updatedAt: updatedProject.metadata.updatedAt
};
if (existingIndex >= 0) {
this.projectIndex.projects[existingIndex] = projectIndexEntry;
}
else {
this.projectIndex.projects.push(projectIndexEntry);
}
await this.saveProjectIndex();
logger.info({ projectId, updates }, 'Project updated successfully');
return createSuccess(updatedProject);
}
catch (error) {
const enhancedError = ErrorFactory.createError('system', `Failed to update project: ${error instanceof Error ? error.message : 'Unknown error'}`, createErrorContext('UnifiedStorageEngine', 'updateProject').build(), { cause: error instanceof Error ? error : undefined });
logger.error({ error: enhancedError, projectId }, 'Failed to update project');
return createFailure(enhancedError);
}
}
async deleteProject(projectId) {
try {
const exists = await this.projectExists(projectId);
if (!exists) {
const error = ErrorFactory.createError('validation', `Project not found: ${projectId}`, createErrorContext('UnifiedStorageEngine', 'deleteProject').build());
return createFailure(error);
}
const projectPath = join(this.dataDirectory, 'projects', `${projectId}.json`);
await unlink(projectPath);
const cacheKey = createCacheKey(`project:${projectId}`);
this.cache.delete(cacheKey);
this.projectIndex.projects = this.projectIndex.projects.filter(p => p.id !== projectId);
await this.saveProjectIndex();
logger.info({ projectId }, 'Project deleted successfully');
return createSuccess(undefined);
}
catch (error) {
const enhancedError = ErrorFactory.createError('system', `Failed to delete project: ${error instanceof Error ? error.message : 'Unknown error'}`, createErrorContext('UnifiedStorageEngine', 'deleteProject').build(), { cause: error instanceof Error ? error : undefined });
logger.error({ error: enhancedError, projectId }, 'Failed to delete project');
return createFailure(enhancedError);
}
}
async listProjects() {
try {
const projects = [];
for (const projectEntry of this.projectIndex.projects) {
const projectId = projectEntry.id;
const projectResult = await this.getProject(projectId);
if (projectResult.success) {
projects.push(projectResult.data);
}
}
return createSuccess(projects);
}
catch (error) {
const enhancedError = ErrorFactory.createError('system', `Failed to list projects: ${error instanceof Error ? error.message : 'Unknown error'}`, createErrorContext('UnifiedStorageEngine', 'listProjects').build(), { cause: error instanceof Error ? error : undefined });
logger.error({ error: enhancedError }, 'Failed to list projects');
return createFailure(enhancedError);
}
}
setCache(key, value) {
if (!this.config.cache.enabled)
return;
const now = new Date();
const expiresAt = new Date(now.getTime() + this.config.cache.ttlSeconds * 1000);
const entry = {
key,
value,
createdAt: now,
expiresAt,
accessCount: 0,
lastAccessed: now,
size: JSON.stringify(value).length,
compressed: false
};
this.cache.set(key, entry);
if (this.cache.size > this.config.cache.maxSize) {
this.evictOldestCacheEntries();
}
}
getCache(key) {
if (!this.config.cache.enabled)
return null;
const entry = this.cache.get(key);
if (!entry)
return null;
if (entry.expiresAt < new Date()) {
this.cache.delete(key);
return null;
}
entry.accessCount++;
entry.lastAccessed = new Date();
return entry.value;
}
cleanupCache() {
const now = new Date();
const expiredKeys = [];
for (const [key, entry] of this.cache.entries()) {
if (entry.expiresAt < now) {
expiredKeys.push(key);
}
}
for (const key of expiredKeys) {
this.cache.delete(key);
}
if (expiredKeys.length > 0) {
logger.debug(`Cleaned up ${expiredKeys.length} expired cache entries`);
}
}
evictOldestCacheEntries() {
const entries = Array.from(this.cache.entries());
entries.sort((a, b) => a[1].lastAccessed.getTime() - b[1].lastAccessed.getTime());
const toEvict = Math.ceil(this.cache.size * 0.1);
for (let i = 0; i < toEvict && i < entries.length; i++) {
this.cache.delete(entries[i][0]);
}
logger.debug(`Evicted ${toEvict} cache entries due to size limit`);
}
async performBackup() {
try {
const backupId = createBackupId(`backup_${Date.now()}`);
const backupDir = join(this.dataDirectory, 'backups', backupId);
await fs.mkdir(backupDir, { recursive: true });
const dataDirs = ['tasks', 'projects', 'dependencies', 'epics', 'graphs', 'indexes'];
for (const dir of dataDirs) {
const sourceDir = join(this.dataDirectory, dir);
const targetDir = join(backupDir, dir);
await this.copyDirectory(sourceDir, targetDir);
}
const backup = {
id: backupId,
createdAt: new Date(),
size: await this.getDirectorySize(backupDir),
entities: ['task', 'project', 'dependency', 'epic', 'graph'],
compressed: false,
encrypted: false,
checksum: await this.calculateChecksum(backupDir),
metadata: {
version: '1.0.0',
creator: 'UnifiedStorageEngine',
description: 'Automated backup'
}
};
this.backups.set(backupId, backup);
await this.cleanupOldBackups();
this.emit('backupCreated', backup);
logger.info(`Backup created: ${backupId}`);
}
catch (error) {
logger.error('Backup failed:', error);
this.emit('backupFailed', error);
}
}
async cleanupOldBackups() {
const backups = Array.from(this.backups.values());
backups.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
if (backups.length > this.config.backup.maxBackups) {
const toDelete = backups.slice(this.config.backup.maxBackups);
for (const backup of toDelete) {
try {
const backupDir = join(this.dataDirectory, 'backups', backup.id);
await this.removeDirectory(backupDir);
this.backups.delete(backup.id);
logger.info(`Old backup deleted: ${backup.id}`);
}
catch (error) {
logger.error(`Failed to delete backup ${backup.id}:`, error);
}
}
}
}
async saveTaskIndex() {
this.taskIndex.lastUpdated = new Date().toISOString();
const indexDir = join(this.dataDirectory, 'indexes');
await fs.mkdir(indexDir, { recursive: true });
const indexPath = join(indexDir, 'tasks.json');
await fs.writeFile(indexPath, JSON.stringify(this.taskIndex, null, 2), 'utf-8');
}
async saveProjectIndex() {
this.projectIndex.lastUpdated = new Date().toISOString();
const indexDir = join(this.dataDirectory, 'indexes');
await fs.mkdir(indexDir, { recursive: true });
const indexPath = join(indexDir, 'projects.json');
await fs.writeFile(indexPath, JSON.stringify(this.projectIndex, null, 2), 'utf-8');
}
async fileExists(path) {
try {
await fs.access(path);
return true;
}
catch {
return false;
}
}
async copyDirectory(source, target) {
await fs.mkdir(target, { recursive: true });
const entries = await fs.readdir(source, { withFileTypes: true });
for (const entry of entries) {
const sourcePath = join(source, entry.name);
const targetPath = join(target, entry.name);
if (entry.isDirectory()) {
await this.copyDirectory(sourcePath, targetPath);
}
else {
await fs.copyFile(sourcePath, targetPath);
}
}
}
async removeDirectory(path) {
try {
await fs.rm(path, { recursive: true, force: true });
}
catch (error) {
logger.error(`Failed to remove directory ${path}:`, error);
}
}
async getDirectorySize(path) {
let size = 0;
try {
const entries = await fs.readdir(path, { withFileTypes: true });
for (const entry of entries) {
const entryPath = join(path, entry.name);
if (entry.isDirectory()) {
size += await this.getDirectorySize(entryPath);
}
else {
const stats = await fs.stat(entryPath);
size += stats.size;
}
}
}
catch (error) {
logger.error(`Failed to calculate directory size for ${path}:`, error);
}
return size;
}
async calculateChecksum(path) {
const size = await this.getDirectorySize(path);
return `checksum_${size}_${Date.now()}`;
}
trackOperation(operation, entity, responseTime) {
this.operationCount++;
this.operationsByType.set(operation, (this.operationsByType.get(operation) || 0) + 1);
this.operationsByEntity.set(entity, (this.operationsByEntity.get(entity) || 0) + 1);
this.totalResponseTime += responseTime;
}
collectMetrics() {
const stats = {
totalOperations: this.operationCount,
operationsByType: Object.fromEntries(this.operationsByType),
operationsByEntity: Object.fromEntries(this.operationsByEntity),
averageResponseTime: this.operationCount > 0 ? this.totalResponseTime / this.operationCount : 0,
cacheHitRate: this.cacheRequests > 0 ? this.cacheHits / this.cacheRequests : 0,
storageSize: 0,
activeTransactions: this.transactions.size,
totalBackups: this.backups.size,
errorRate: 0
};
this.emit('metricsCollected', stats);
}
getStatistics() {
return {
totalOperations: this.operationCount,
operationsByType: Object.fromEntries(this.operationsByType),
operationsByEntity: Object.fromEntries(this.operationsByEntity),
averageResponseTime: this.operationCount > 0 ? this.totalResponseTime / this.operationCount : 0,
cacheHitRate: this.cacheRequests > 0 ? this.cacheHits / this.cacheRequests : 0,
storageSize: 0,
activeTransactions: this.transactions.size,
totalBackups: this.backups.size,
errorRate: 0
};
}
dispose() {
if (this.backupTimer) {
clearInterval(this.backupTimer);
this.backupTimer = null;
}
if (this.cacheCleanupTimer) {
clearInterval(this.cacheCleanupTimer);
this.cacheCleanupTimer = null;
}
if (this.metricsTimer) {
clearInterval(this.metricsTimer);
this.metricsTimer = null;
}
this.cache.clear();
this.transactions.clear();
this.backups.clear();
this.removeAllListeners();
this.initialized = false;
logger.info('Unified Storage Engine disposed');
}
}
export function createDefaultStorageConfig() {
return {
dataDirectory: getVibeTaskManagerOutputDir(),
format: 'json',
cache: {
enabled: true,
maxSize: 1000,
ttlSeconds: 3600,
compressionEnabled: false,
persistToDisk: false
},
backup: {
enabled: true,
intervalMinutes: 60,
maxBackups: 10,
compressionEnabled: true,
encryptionEnabled: false,
remoteBackupEnabled: false
},
performance: {
batchSize: 100,
maxConcurrentOperations: 10,
enableCompression: false,
enableEncryption: false
},
monitoring: {
enableMetrics: true,
metricsInterval: 60,
enableAuditLog: true,
enablePerformanceTracking: true
}
};
}