UNPKG

cs-element

Version:

Advanced reactive data management library with state machines, blueprints, persistence, compression, networking, and multithreading support

764 lines (634 loc) 25.4 kB
# 🚀 Web Workers и Производительность (Node.js) ⚠️ **Внимание**: WorkerManager доступен только в Node.js окружении через импорт `cs-element/workers/nodejs`. CSElement предоставляет мощную систему Web Workers для выполнения тяжелых операций в фоне без блокировки основного потока. Теперь с реальными реализациями и кроссплатформенной поддержкой! ## 📋 Содержание - [🚀 Web Workers и Производительность](#-web-workers-и-производительность) - [📋 Содержание](#-содержание) - [🔧 Установка зависимостей](#-установка-зависимостей) - [Основы работы с Workers](#основы-работы-с-workers) - [Создание WorkerManager](#создание-workermanager) - [Выполнение операций](#выполнение-операций) - [🔄 Кроссплатформенная поддержка](#-кроссплатформенная-поддержка) - [Пул воркеров](#пул-воркеров) - [Управление жизненным циклом](#управление-жизненным-циклом) - [Типы операций](#типы-операций) - [Сериализация и вычисление различий](#сериализация-и-вычисление-различий) - [⚡ Реальные операции](#-реальные-операции) - [🔍 Мониторинг производительности](#-мониторинг-производительности) - [🧪 Тестирование в различных средах](#-тестирование-в-различных-средах) - [🚀 Полный пример: Система обработки больших данных](#-полный-пример-система-обработки-больших-данных) - [🎯 Заключение](#-заключение) ## 🔧 Установка зависимостей ```bash # Основные зависимости для работы с воркерами npm install uuid # Для Node.js окружения npm install worker_threads # Для тестирования npm install jest @types/jest ``` ## Основы работы с Workers ### Создание WorkerManager ```typescript // ⚠️ Только для Node.js! import { WorkerManager, WorkerConfig, WorkerPool } from 'cs-element/workers/nodejs'; // Базовая конфигурация const workerManager = new WorkerManager(); // Расширенная конфигурация const config: WorkerConfig = { maxConcurrentOperations: 8, timeoutMs: 30000, memoryLimitMB: 512, enableLogging: true, enableProfiling: true, enableCache: true, cacheSize: 100 }; const poolConfig: WorkerPool = { size: navigator.hardwareConcurrency || 4, strategy: 'least-busy', // 'round-robin', 'least-busy', 'random' healthCheck: true, recycleAfter: 1000 }; const advancedManager = new WorkerManager(config, poolConfig); await advancedManager.initialize(); ``` ### Выполнение операций ```typescript // ⚠️ Только для Node.js! import { WorkerOperationType, WorkerMessage } from 'cs-element/workers/nodejs'; // Сериализация элемента const serializeOperation: WorkerMessage = { id: 'serialize-1', type: WorkerOperationType.SERIALIZE_ELEMENT, timestamp: Date.now(), payload: { elementId: 'my-element', options: { includeChildren: true, includeData: true, includeMetadata: true } } }; const serializedData = await workerManager.executeOperation(serializeOperation); // Diff операция const diffOperation: WorkerMessage = { id: 'diff-1', type: WorkerOperationType.COMPUTE_DIFF, timestamp: Date.now(), payload: { sourceElementId: 'element-v1', targetElementId: 'element-v2', algorithm: 'myers' } }; const diffResult = await workerManager.executeOperation(diffOperation); ``` ## 🔄 Кроссплатформенная поддержка WorkerManager теперь поддерживает как Web Workers (браузер), так и Worker Threads (Node.js): ```typescript // Автоматическое определение окружения const workerManager = new WorkerManager({ maxConcurrentOperations: 4, timeoutMs: 30000, enableLogging: true }); await workerManager.initialize(); // В браузере используются Web Workers // В Node.js используются Worker Threads // В тестовой среде используются заглушки console.log('Воркер инициализирован для:', { browser: typeof window !== 'undefined', node: typeof process !== 'undefined', test: typeof jest !== 'undefined' }); ``` ## Пул воркеров ### Управление жизненным циклом ```typescript // Получение статуса пула const poolStatus = workerManager.getPoolStatus(); console.log('Статус пула:', { totalWorkers: poolStatus.totalWorkers, activeWorkers: poolStatus.activeWorkers, queuedOperations: poolStatus.queuedOperations, totalOperations: poolStatus.totalOperations, averageExecutionTime: poolStatus.averageExecutionTime, memoryUsage: poolStatus.memoryUsage }); // Создание дополнительного воркера const newWorker = await workerManager.createWorker(); console.log(`Создан воркер: ${newWorker.id}`); // Завершение воркера await workerManager.terminateWorker(newWorker.id); console.log(`Воркер ${newWorker.id} завершен`); // Проверка здоровья const healthCheck = await workerManager.healthCheck(); console.log('Здоровье воркеров:', healthCheck); ``` ## Типы операций ### Сериализация и вычисление различий ```typescript // Сериализация больших структур const serializeTask = async (elementId: string) => { const operation: WorkerMessage = { id: `serialize-${Date.now()}`, type: WorkerOperationType.SERIALIZE_ELEMENT, timestamp: Date.now(), payload: { elementId, options: { includeChildren: true, includeData: true, includeMetadata: true, compression: true } } }; const result = await workerManager.executeOperation(operation); if (result.success) { console.log(`Сериализация завершена за ${result.executionTime}мс`); return result.result; } else { console.error('Ошибка сериализации:', result.error); throw new Error(result.error); } }; // Трёхстороннее слияние const threeWayMerge = async (baseId: string, sourceId: string, targetId: string) => { const operation: WorkerMessage = { id: `merge-${Date.now()}`, type: WorkerOperationType.THREE_WAY_MERGE, timestamp: Date.now(), payload: { baseElementId: baseId, sourceElementId: sourceId, targetElementId: targetId, strategy: 'auto', options: { conflictResolution: 'auto', autoResolveThreshold: 0.8 } } }; const result = await workerManager.executeOperation(operation); if (result.success) { console.log('Слияние завершено:', result.result.conflicts); return result.result; } else { console.error('Ошибка слияния:', result.error); throw new Error(result.error); } }; ``` ## ⚡ Реальные операции WorkerManager теперь выполняет реальные операции с использованием современных библиотек: ```typescript // Пример обработки больших данных const processLargeDataset = async (dataset: any[]) => { const chunks = []; const chunkSize = 1000; // Разбиваем данные на чанки for (let i = 0; i < dataset.length; i += chunkSize) { chunks.push(dataset.slice(i, i + chunkSize)); } // Обрабатываем каждый чанк в отдельном воркере const operations = chunks.map((chunk, index) => ({ id: `process-chunk-${index}`, type: WorkerOperationType.PROCESS_DATA, timestamp: Date.now(), payload: { data: chunk, processingOptions: { algorithm: 'advanced', parallel: true, optimization: true } } })); // Выполняем операции параллельно const results = await Promise.all( operations.map(op => workerManager.executeOperation(op)) ); // Объединяем результаты const processedData = results .filter(r => r.success) .map(r => r.result) .flat(); console.log(`Обработано записей: ${processedData.length}`); return processedData; }; // Использование const largeDataset = Array(50000).fill(null).map((_, i) => ({ id: i, value: Math.random(), data: `Record ${i}` })); const processed = await processLargeDataset(largeDataset); ``` ## 🔍 Мониторинг производительности ```typescript class WorkerPerformanceMonitor { private workerManager: WorkerManager; private metrics: { operations: Array<{ id: string; type: string; duration: number; success: boolean; timestamp: number; memoryUsage?: number; }>; errors: Array<{ operation: string; error: string; timestamp: number; }>; }; constructor(workerManager: WorkerManager) { this.workerManager = workerManager; this.metrics = { operations: [], errors: [] }; this.setupEventListeners(); } private setupEventListeners(): void { // Отслеживание завершенных операций this.workerManager.on('operation:completed', (data) => { this.recordOperation({ id: data.id, type: data.type, duration: data.executionTime, success: true, timestamp: Date.now(), memoryUsage: data.memoryUsage }); }); // Отслеживание ошибок this.workerManager.on('operation:failed', (data) => { this.recordOperation({ id: data.id, type: data.type, duration: data.executionTime || 0, success: false, timestamp: Date.now() }); this.metrics.errors.push({ operation: data.id, error: data.error, timestamp: Date.now() }); }); } private recordOperation(operation: any): void { this.metrics.operations.push(operation); // Ограничиваем размер истории if (this.metrics.operations.length > 1000) { this.metrics.operations = this.metrics.operations.slice(-1000); } } getPerformanceReport(): { summary: { totalOperations: number; successRate: number; averageExecutionTime: number; operationsPerSecond: number; memoryUsage: number; }; recommendations: string[]; topSlowOperations: Array<{ id: string; type: string; duration: number; }>; } { const recentOps = this.metrics.operations .filter(op => Date.now() - op.timestamp < 300000); // Последние 5 минут const successfulOps = recentOps.filter(op => op.success); const totalDuration = recentOps.reduce((sum, op) => sum + op.duration, 0); const summary = { totalOperations: recentOps.length, successRate: recentOps.length > 0 ? successfulOps.length / recentOps.length : 0, averageExecutionTime: recentOps.length > 0 ? totalDuration / recentOps.length : 0, operationsPerSecond: recentOps.length / 300, // За 5 минут memoryUsage: recentOps.reduce((sum, op) => sum + (op.memoryUsage || 0), 0) / recentOps.length }; const recommendations = []; if (summary.successRate < 0.95) { recommendations.push('Высокий процент ошибок, проверьте логи'); } if (summary.averageExecutionTime > 5000) { recommendations.push('Высокое время выполнения, рассмотрите оптимизацию'); } if (summary.memoryUsage > 256) { recommendations.push('Высокое потребление памяти, рассмотрите батчинг'); } const topSlowOperations = recentOps .sort((a, b) => b.duration - a.duration) .slice(0, 5) .map(op => ({ id: op.id, type: op.type, duration: op.duration })); return { summary, recommendations, topSlowOperations }; } exportMetrics(): string { return JSON.stringify({ timestamp: new Date().toISOString(), metrics: this.metrics, report: this.getPerformanceReport() }, null, 2); } } // Использование монитора const monitor = new WorkerPerformanceMonitor(workerManager); // Получение отчета через 5 минут setTimeout(() => { const report = monitor.getPerformanceReport(); console.log('📊 Отчет о производительности:', report); if (report.recommendations.length > 0) { console.log('💡 Рекомендации:', report.recommendations); } }, 300000); ``` ## 🧪 Тестирование в различных средах WorkerManager адаптируется к различным средам выполнения: ```typescript // Тестирование в Jest describe('WorkerManager', () => { let workerManager: WorkerManager; beforeEach(async () => { workerManager = new WorkerManager({ maxConcurrentOperations: 2, timeoutMs: 5000, enableLogging: false // Отключаем в тестах }); await workerManager.initialize(); }); afterEach(async () => { await workerManager.terminate(); }); test('должен выполнять операции в тестовой среде', async () => { const operation: WorkerMessage = { id: 'test-operation', type: WorkerOperationType.SERIALIZE_ELEMENT, timestamp: Date.now(), payload: { elementId: 'test-element', options: { includeData: true } } }; const result = await workerManager.executeOperation(operation); expect(result.success).toBe(true); expect(result.result).toBeDefined(); expect(result.executionTime).toBeGreaterThan(0); }); test('должен обрабатывать ошибки корректно', async () => { const operation: WorkerMessage = { id: 'error-operation', type: 'INVALID_OPERATION' as any, timestamp: Date.now(), payload: {} }; const result = await workerManager.executeOperation(operation); expect(result.success).toBe(false); expect(result.error).toBeDefined(); }); }); // Настройка для разных окружений class EnvironmentAwareWorkerManager extends WorkerManager { constructor(config?: WorkerConfig, poolConfig?: WorkerPool) { super(config, poolConfig); this.adaptToEnvironment(); } private adaptToEnvironment(): void { // Браузер if (typeof window !== 'undefined') { console.log('🌐 Инициализация для браузера'); this.setupWebWorkers(); } // Node.js else if (typeof process !== 'undefined' && process.versions?.node) { console.log('🖥️ Инициализация для Node.js'); this.setupWorkerThreads(); } // Тестовая среда else if (typeof jest !== 'undefined') { console.log('🧪 Инициализация для тестов'); this.setupMockWorkers(); } } private setupWebWorkers(): void { // Настройка Web Workers для браузера console.log('Настройка Web Workers'); } private setupWorkerThreads(): void { // Настройка Worker Threads для Node.js console.log('Настройка Worker Threads'); } private setupMockWorkers(): void { // Настройка заглушек для тестов console.log('Настройка Mock Workers'); } } ``` ## 🚀 Полный пример: Система обработки больших данных ```typescript // ⚠️ Только для Node.js! import { WorkerManager, WorkerOperationType } from 'cs-element/workers/nodejs'; class BigDataProcessor { private workerManager: WorkerManager; private monitor: WorkerPerformanceMonitor; private processingQueue: Array<{ id: string; data: any; priority: 'low' | 'medium' | 'high'; callback: (result: any) => void; }> = []; constructor() { this.workerManager = new WorkerManager({ maxConcurrentOperations: navigator.hardwareConcurrency || 4, timeoutMs: 60000, enableLogging: true, enableProfiling: true, enableCache: true, cacheSize: 200 }); this.monitor = new WorkerPerformanceMonitor(this.workerManager); } async initialize(): Promise<void> { await this.workerManager.initialize(); this.startProcessingQueue(); console.log('🚀 Система обработки больших данных запущена'); } async processDataset( dataset: any[], options: { algorithm: 'standard' | 'advanced' | 'ml'; batchSize: number; priority: 'low' | 'medium' | 'high'; } ): Promise<any[]> { const { algorithm, batchSize, priority } = options; // Разбиваем данные на батчи const batches = this.createBatches(dataset, batchSize); console.log(`📊 Обработка ${dataset.length} записей в ${batches.length} батчах`); // Создаем операции для каждого батча const operations = batches.map((batch, index) => ({ id: `batch-${Date.now()}-${index}`, type: WorkerOperationType.PROCESS_DATA, timestamp: Date.now(), payload: { data: batch, algorithm, batchIndex: index, totalBatches: batches.length } })); // Выполняем операции с учетом приоритета const results = await this.executeBatchOperations(operations, priority); // Объединяем результаты const processedData = results .filter(r => r.success) .sort((a, b) => a.result.batchIndex - b.result.batchIndex) .map(r => r.result.data) .flat(); console.log(`✅ Обработано ${processedData.length} записей`); return processedData; } private createBatches(data: any[], batchSize: number): any[][] { const batches = []; for (let i = 0; i < data.length; i += batchSize) { batches.push(data.slice(i, i + batchSize)); } return batches; } private async executeBatchOperations( operations: any[], priority: 'low' | 'medium' | 'high' ): Promise<any[]> { // Сортируем операции по приоритету const sortedOps = operations.sort((a, b) => { const priorityOrder = { high: 3, medium: 2, low: 1 }; return priorityOrder[priority] - priorityOrder[priority]; }); // Выполняем операции с ограничением параллелизма const maxParallel = this.workerManager.getPoolStatus().totalWorkers; const results = []; for (let i = 0; i < sortedOps.length; i += maxParallel) { const batch = sortedOps.slice(i, i + maxParallel); const batchResults = await Promise.all( batch.map(op => this.workerManager.executeOperation(op)) ); results.push(...batchResults); // Показываем прогресс const progress = Math.round(((i + batch.length) / sortedOps.length) * 100); console.log(`📈 Прогресс: ${progress}%`); } return results; } private startProcessingQueue(): void { setInterval(() => { if (this.processingQueue.length > 0) { const item = this.processingQueue.shift(); if (item) { this.processQueueItem(item); } } }, 100); } private async processQueueItem(item: any): Promise<void> { try { const result = await this.processDataset(item.data, { algorithm: 'standard', batchSize: 1000, priority: item.priority }); item.callback(result); } catch (error) { console.error(`❌ Ошибка обработки ${item.id}:`, error); item.callback({ error: error.message }); } } addToQueue( id: string, data: any, priority: 'low' | 'medium' | 'high', callback: (result: any) => void ): void { this.processingQueue.push({ id, data, priority, callback }); console.log(`📥 Добавлено в очередь: ${id} (приоритет: ${priority})`); } getStatus(): { queue: number; workers: any; performance: any; } { return { queue: this.processingQueue.length, workers: this.workerManager.getPoolStatus(), performance: this.monitor.getPerformanceReport() }; } async shutdown(): Promise<void> { console.log('🛑 Завершение работы системы...'); await this.workerManager.terminate(); console.log('✅ Система завершена'); } } // Использование async function main() { const processor = new BigDataProcessor(); await processor.initialize(); // Генерируем тестовые данные const testData = Array(100000).fill(null).map((_, i) => ({ id: i, value: Math.random() * 1000, category: ['A', 'B', 'C'][Math.floor(Math.random() * 3)], timestamp: Date.now() - Math.random() * 86400000, metadata: { source: 'test', processed: false, tags: [`tag-${i % 10}`] } })); console.log('🎯 Начинаем обработку данных...'); // Обрабатываем данные const processed = await processor.processDataset(testData, { algorithm: 'advanced', batchSize: 5000, priority: 'high' }); console.log(`✅ Обработано записей: ${processed.length}`); // Получаем статистику const status = processor.getStatus(); console.log('📊 Статистика:', status); // Экспортируем метрики const metrics = processor.monitor.exportMetrics(); console.log('📈 Метрики производительности сохранены'); // Завершаем работу await processor.shutdown(); } // Запуск main().catch(console.error); ``` ## 🎯 Заключение WorkerManager в CSElement теперь предоставляет: - **🔄 Реальную многопоточность** с поддержкой Web Workers и Worker Threads - **⚡ Высокую производительность** с пулом воркеров и кэшированием - **🌐 Кроссплатформенность** (браузер, Node.js, тестовая среда) - **📊 Мониторинг производительности** с детальной аналитикой - **🔧 Гибкую настройку** под различные сценарии использования - **🧪 Полную поддержку тестирования** с заглушками для Jest Все заглушки заменены на реальные реализации, система готова для производственного использования! **Следующие разделы:** - [Транзакции и блокировки](./09-transactions-and-locks.md) - [Персистентность и адаптеры](./10-persistence-and-adapters.md) - [Система состояний](./11-state-machine.md) - [Diff Engine](./12-diff-engine.md) - [Blueprint система](./13-blueprint-system.md) **Следующий раздел:** [Транзакции и блокировки →](09-transactions-and-locks.md)