# 🚀 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) 