versacompiler 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,479 @@
1
+ /**
2
+ * TypeScript Worker Pool - Pool de workers para compilación paralela
3
+ * Reemplaza el worker único con múltiples workers para aprovecha la concurrencia real
4
+ */
5
+ import * as os from 'node:os';
6
+ import * as path from 'node:path';
7
+ import * as process from 'node:process';
8
+ import { Worker } from 'node:worker_threads';
9
+ import { validateTypesWithLanguageService } from './typescript-sync-validator.js';
10
+ /**
11
+ * Pool de workers para compilación TypeScript paralela
12
+ * Distribuye las tareas entre múltiples workers para mayor rendimiento
13
+ */
14
+ export class TypeScriptWorkerPool {
15
+ static instance;
16
+ workers = [];
17
+ poolSize;
18
+ workerPath;
19
+ initPromise = null;
20
+ isInitialized = false; // Configuración optimizada con reciclaje de workers
21
+ TASK_TIMEOUT = 10000; // 10 segundos por tarea
22
+ WORKER_INIT_TIMEOUT = 5000; // 5 segundos para inicializar
23
+ MAX_TASKS_PER_WORKER = 50; // Máximo de tareas por worker antes de reciclaje
24
+ WORKER_MEMORY_CHECK_INTERVAL = 100; // Verificar cada 100 tareas
25
+ // Métricas de rendimiento
26
+ totalTasks = 0;
27
+ completedTasks = 0;
28
+ failedTasks = 0;
29
+ constructor() {
30
+ // Determinar tamaño óptimo del pool
31
+ const cpuCount = os.cpus().length;
32
+ this.poolSize = Math.min(Math.max(cpuCount - 1, 2), 8); // Entre 2 y 8 workers
33
+ this.workerPath = path.join(process.env.PATH_PROY || path.join(process.cwd(), 'src'), 'compiler', 'typescript-worker-thread.cjs');
34
+ }
35
+ /**
36
+ * Obtiene la instancia singleton del Worker Pool
37
+ */
38
+ static getInstance() {
39
+ if (!TypeScriptWorkerPool.instance) {
40
+ TypeScriptWorkerPool.instance = new TypeScriptWorkerPool();
41
+ }
42
+ return TypeScriptWorkerPool.instance;
43
+ } /**
44
+ * Configura el modo de operación del pool
45
+ */
46
+ setMode(mode) {
47
+ // Ajustar configuración según el modo
48
+ switch (mode) {
49
+ case 'batch':
50
+ // Para modo batch, optimizar para throughput
51
+ this.poolSize = Math.min(os.cpus().length, 12);
52
+ break;
53
+ case 'watch':
54
+ // Para modo watch, menos workers pero más responsivos
55
+ this.poolSize = Math.min(Math.max(os.cpus().length / 2, 2), 6);
56
+ break;
57
+ case 'individual':
58
+ // Para individual, pool pequeño
59
+ this.poolSize = Math.min(4, os.cpus().length);
60
+ break;
61
+ }
62
+ }
63
+ /**
64
+ * Inicializa el pool de workers
65
+ */
66
+ async initializePool() {
67
+ if (this.initPromise) {
68
+ return this.initPromise;
69
+ }
70
+ this.initPromise = this._performPoolInitialization();
71
+ return this.initPromise;
72
+ }
73
+ /**
74
+ * Realiza la inicialización del pool de workers
75
+ */ async _performPoolInitialization() {
76
+ try {
77
+ // Verificar que el archivo del worker existe
78
+ const fs = await import('node:fs');
79
+ const exists = fs.existsSync(this.workerPath);
80
+ if (!exists) {
81
+ throw new Error(`Worker thread file not found: ${this.workerPath}`);
82
+ }
83
+ // Crear workers en paralelo
84
+ const workerPromises = Array.from({ length: this.poolSize }, (_, index) => this.createWorker(index));
85
+ this.workers = await Promise.all(workerPromises);
86
+ this.isInitialized = true;
87
+ }
88
+ catch (error) {
89
+ this.isInitialized = false;
90
+ throw error;
91
+ }
92
+ }
93
+ /**
94
+ * Crea un worker individual
95
+ */ async createWorker(workerId) {
96
+ return new Promise((resolve, reject) => {
97
+ try {
98
+ const worker = new Worker(this.workerPath, {
99
+ env: {
100
+ ...process.env,
101
+ NODE_OPTIONS: '',
102
+ WORKER_ID: workerId.toString(),
103
+ },
104
+ });
105
+ const poolWorker = {
106
+ worker,
107
+ id: workerId,
108
+ busy: false,
109
+ pendingTasks: new Map(),
110
+ taskCounter: 0,
111
+ };
112
+ // Configurar listeners
113
+ this.setupWorkerListeners(poolWorker);
114
+ // Timeout para inicialización
115
+ const initTimeout = setTimeout(() => {
116
+ reject(new Error(`Worker ${workerId} initialization timeout`));
117
+ }, this.WORKER_INIT_TIMEOUT);
118
+ // Esperar que el worker esté listo
119
+ const checkReady = () => {
120
+ worker.postMessage({ type: 'ping' });
121
+ };
122
+ worker.on('message', function readyHandler(response) {
123
+ if (response.id === 'worker-ready' ||
124
+ response.message === 'pong') {
125
+ clearTimeout(initTimeout);
126
+ worker.off('message', readyHandler);
127
+ resolve(poolWorker);
128
+ }
129
+ });
130
+ worker.on('error', error => {
131
+ clearTimeout(initTimeout);
132
+ reject(error);
133
+ });
134
+ // Intentar conectar
135
+ checkReady();
136
+ }
137
+ catch (error) {
138
+ reject(error);
139
+ }
140
+ });
141
+ }
142
+ /**
143
+ * Configura los listeners para un worker individual
144
+ */ setupWorkerListeners(poolWorker) {
145
+ const { worker } = poolWorker;
146
+ worker.on('message', (response) => {
147
+ try {
148
+ // Ignorar mensajes de control
149
+ if (response.id === 'worker-ready' ||
150
+ response.message === 'pong') {
151
+ return;
152
+ } // Buscar la tarea pendiente
153
+ const pendingTask = poolWorker.pendingTasks.get(response.id);
154
+ if (!pendingTask) {
155
+ return;
156
+ }
157
+ // Limpiar timeout y eliminar tarea
158
+ clearTimeout(pendingTask.timeout);
159
+ poolWorker.pendingTasks.delete(response.id);
160
+ // Marcar worker como disponible si no tiene más tareas
161
+ if (poolWorker.pendingTasks.size === 0) {
162
+ poolWorker.busy = false;
163
+ }
164
+ // Procesar respuesta
165
+ if (response.success &&
166
+ response.diagnostics !== undefined &&
167
+ response.hasErrors !== undefined) {
168
+ this.completedTasks++;
169
+ pendingTask.resolve({
170
+ diagnostics: response.diagnostics,
171
+ hasErrors: response.hasErrors,
172
+ });
173
+ }
174
+ else {
175
+ this.failedTasks++;
176
+ const errorMessage = response.error || 'Error desconocido del worker';
177
+ pendingTask.reject(new Error(errorMessage));
178
+ }
179
+ }
180
+ catch {
181
+ // Error silencioso - no imprimir cada error
182
+ }
183
+ });
184
+ worker.on('error', async (error) => {
185
+ await this.handleWorkerError(poolWorker, error);
186
+ });
187
+ worker.on('exit', async (code) => {
188
+ await this.handleWorkerExit(poolWorker, code);
189
+ });
190
+ }
191
+ /**
192
+ * Maneja errores de un worker específico con cleanup completo
193
+ */ async handleWorkerError(poolWorker, error) {
194
+ console.warn(`[WorkerPool] Manejando error del worker ${poolWorker.id}:`, error.message);
195
+ // 1. Rechazar todas las tareas pendientes con cleanup de timeouts
196
+ poolWorker.pendingTasks.forEach(task => {
197
+ clearTimeout(task.timeout);
198
+ this.failedTasks++;
199
+ task.reject(new Error(`Worker ${poolWorker.id} failed: ${error.message}`));
200
+ });
201
+ poolWorker.pendingTasks.clear();
202
+ // 2. Terminar worker correctamente para evitar memory leaks
203
+ try {
204
+ poolWorker.worker.removeAllListeners();
205
+ await poolWorker.worker.terminate();
206
+ }
207
+ catch (terminateError) {
208
+ console.error(`[WorkerPool] Error terminando worker ${poolWorker.id}:`, terminateError);
209
+ }
210
+ // 3. Marcar como no disponible
211
+ poolWorker.busy = false;
212
+ // 4. Recrear worker si el pool está activo
213
+ if (this.isInitialized && this.workers.length > 0) {
214
+ try {
215
+ const newWorker = await this.createWorker(poolWorker.id);
216
+ const index = this.workers.findIndex(w => w.id === poolWorker.id);
217
+ if (index !== -1) {
218
+ this.workers[index] = newWorker;
219
+ }
220
+ }
221
+ catch (recreateError) {
222
+ console.error(`[WorkerPool] No se pudo recrear worker ${poolWorker.id}:`, recreateError);
223
+ }
224
+ }
225
+ } /**
226
+ * Maneja la salida inesperada de un worker con cleanup completo
227
+ */
228
+ async handleWorkerExit(poolWorker, code) {
229
+ console.warn(`[WorkerPool] Worker ${poolWorker.id} salió con código ${code}`);
230
+ // 1. Rechazar tareas pendientes con cleanup
231
+ poolWorker.pendingTasks.forEach(task => {
232
+ clearTimeout(task.timeout);
233
+ this.failedTasks++;
234
+ task.reject(new Error(`Worker ${poolWorker.id} exited with code ${code}`));
235
+ });
236
+ poolWorker.pendingTasks.clear();
237
+ poolWorker.busy = false;
238
+ // 2. Limpiar listeners para evitar memory leaks
239
+ try {
240
+ poolWorker.worker.removeAllListeners();
241
+ }
242
+ catch {
243
+ // Error silencioso en cleanup
244
+ }
245
+ // 3. Recrear worker si es necesario y el pool está activo
246
+ if (this.isInitialized && this.workers.length > 0) {
247
+ try {
248
+ await this.recreateWorker(poolWorker);
249
+ }
250
+ catch (recreateError) {
251
+ console.error(`[WorkerPool] Error recreando worker ${poolWorker.id}:`, recreateError);
252
+ }
253
+ }
254
+ }
255
+ /**
256
+ * Recrea un worker que falló
257
+ */ async recreateWorker(failedWorker) {
258
+ try {
259
+ const newWorker = await this.createWorker(failedWorker.id);
260
+ // Reemplazar en el array
261
+ const index = this.workers.findIndex(w => w.id === failedWorker.id);
262
+ if (index !== -1) {
263
+ this.workers[index] = newWorker;
264
+ }
265
+ }
266
+ catch {
267
+ // Error silencioso en recreación
268
+ }
269
+ }
270
+ /**
271
+ * Recicla un worker para prevenir memory leaks
272
+ */
273
+ async recycleWorker(poolWorker) {
274
+ try {
275
+ console.log(`[WorkerPool] Reciclando worker ${poolWorker.id} después de ${poolWorker.taskCounter} tareas`); // 1. Esperar a que termine tareas pendientes (timeout corto)
276
+ const maxWait = 2000; // 2 segundos máximo
277
+ const startTime = Date.now();
278
+ await new Promise(resolve => {
279
+ const checkPending = () => {
280
+ if (poolWorker.pendingTasks.size === 0 ||
281
+ Date.now() - startTime >= maxWait) {
282
+ resolve();
283
+ }
284
+ else {
285
+ setTimeout(checkPending, 100);
286
+ }
287
+ };
288
+ checkPending();
289
+ });
290
+ // 2. Si aún hay tareas pendientes, rechazarlas
291
+ if (poolWorker.pendingTasks.size > 0) {
292
+ poolWorker.pendingTasks.forEach(task => {
293
+ clearTimeout(task.timeout);
294
+ task.reject(new Error('Worker being recycled'));
295
+ });
296
+ poolWorker.pendingTasks.clear();
297
+ }
298
+ // 3. Terminar worker actual
299
+ poolWorker.worker.removeAllListeners();
300
+ await poolWorker.worker.terminate();
301
+ // 4. Crear nuevo worker
302
+ const newWorker = await this.createWorker(poolWorker.id);
303
+ // 5. Reemplazar en el array
304
+ const index = this.workers.findIndex(w => w.id === poolWorker.id);
305
+ if (index !== -1) {
306
+ this.workers[index] = newWorker;
307
+ }
308
+ }
309
+ catch (error) {
310
+ console.error(`[WorkerPool] Error reciclando worker ${poolWorker.id}:`, error);
311
+ }
312
+ }
313
+ /**
314
+ * Encuentra el worker menos ocupado
315
+ */
316
+ findAvailableWorker() {
317
+ // Buscar worker completamente libre
318
+ const freeWorker = this.workers.find(w => !w.busy && w.pendingTasks.size === 0);
319
+ if (freeWorker) {
320
+ return freeWorker;
321
+ }
322
+ // Si no hay workers libres, buscar el menos ocupado
323
+ const leastBusyWorker = this.workers.reduce((least, current) => {
324
+ if (current.pendingTasks.size < least.pendingTasks.size) {
325
+ return current;
326
+ }
327
+ return least;
328
+ });
329
+ // Solo devolver si no está demasiado ocupado
330
+ if (leastBusyWorker.pendingTasks.size < 5) {
331
+ return leastBusyWorker;
332
+ }
333
+ return null; // Todos los workers están muy ocupados
334
+ }
335
+ /**
336
+ * Realiza type checking usando el pool de workers
337
+ */
338
+ async typeCheck(fileName, content, compilerOptions) {
339
+ // Asegurar que el pool esté inicializado
340
+ await this.initializePool();
341
+ if (!this.isInitialized) {
342
+ return this.typeCheckWithSyncFallback(fileName, content, compilerOptions);
343
+ }
344
+ // Buscar worker disponible
345
+ const availableWorker = this.findAvailableWorker();
346
+ if (!availableWorker) {
347
+ return this.typeCheckWithSyncFallback(fileName, content, compilerOptions);
348
+ }
349
+ try {
350
+ this.totalTasks++;
351
+ return await this.typeCheckWithWorker(availableWorker, fileName, content, compilerOptions);
352
+ }
353
+ catch {
354
+ return this.typeCheckWithSyncFallback(fileName, content, compilerOptions);
355
+ }
356
+ } /**
357
+ * Realiza type checking usando un worker específico con reciclaje automático
358
+ */
359
+ async typeCheckWithWorker(poolWorker, fileName, content, compilerOptions) {
360
+ // Verificar si el worker necesita reciclaje por número de tareas
361
+ if (poolWorker.taskCounter >= this.MAX_TASKS_PER_WORKER) {
362
+ await this.recycleWorker(poolWorker);
363
+ }
364
+ return new Promise((resolve, reject) => {
365
+ const taskId = `task-${poolWorker.id}-${++poolWorker.taskCounter}-${Date.now()}`;
366
+ // Marcar worker como ocupado
367
+ poolWorker.busy = true;
368
+ // Configurar timeout para la tarea
369
+ const timeout = setTimeout(() => {
370
+ poolWorker.pendingTasks.delete(taskId);
371
+ if (poolWorker.pendingTasks.size === 0) {
372
+ poolWorker.busy = false;
373
+ }
374
+ reject(new Error(`Timeout en type checking para ${fileName}`));
375
+ }, this.TASK_TIMEOUT);
376
+ // Agregar tarea a la lista de pendientes del worker
377
+ poolWorker.pendingTasks.set(taskId, {
378
+ resolve,
379
+ reject,
380
+ timeout,
381
+ fileName,
382
+ startTime: Date.now(),
383
+ });
384
+ try {
385
+ // Crear mensaje para el worker
386
+ const message = {
387
+ id: taskId,
388
+ fileName,
389
+ content,
390
+ compilerOptions,
391
+ };
392
+ // Enviar mensaje al worker
393
+ poolWorker.worker.postMessage(message);
394
+ }
395
+ catch (error) {
396
+ // Limpiar en caso de error
397
+ clearTimeout(timeout);
398
+ poolWorker.pendingTasks.delete(taskId);
399
+ if (poolWorker.pendingTasks.size === 0) {
400
+ poolWorker.busy = false;
401
+ }
402
+ reject(error);
403
+ }
404
+ });
405
+ }
406
+ /**
407
+ * Fallback síncrono para type checking
408
+ */
409
+ typeCheckWithSyncFallback(fileName, content, compilerOptions) {
410
+ try {
411
+ return validateTypesWithLanguageService(fileName, content, compilerOptions);
412
+ }
413
+ catch {
414
+ return {
415
+ diagnostics: [],
416
+ hasErrors: false,
417
+ };
418
+ }
419
+ }
420
+ /**
421
+ * Cierra todos los workers del pool con cleanup completo
422
+ */ async terminate() {
423
+ console.log('[WorkerPool] Cerrando pool de workers...');
424
+ // 1. Rechazar todas las tareas pendientes con cleanup
425
+ let totalPendingTasks = 0;
426
+ for (const poolWorker of this.workers) {
427
+ totalPendingTasks += poolWorker.pendingTasks.size;
428
+ poolWorker.pendingTasks.forEach(task => {
429
+ clearTimeout(task.timeout);
430
+ task.reject(new Error('Worker pool cerrado'));
431
+ });
432
+ poolWorker.pendingTasks.clear();
433
+ // Limpiar listeners para evitar memory leaks
434
+ try {
435
+ poolWorker.worker.removeAllListeners();
436
+ }
437
+ catch {
438
+ // Error silencioso en cleanup
439
+ }
440
+ }
441
+ if (totalPendingTasks > 0) {
442
+ console.log(`[WorkerPool] Se cancelaron ${totalPendingTasks} tareas pendientes`);
443
+ } // 2. Cerrar todos los workers con manejo de errores
444
+ const terminatePromises = this.workers.map(async (poolWorker) => {
445
+ try {
446
+ await poolWorker.worker.terminate();
447
+ }
448
+ catch (error) {
449
+ console.warn(`[WorkerPool] Error terminando worker ${poolWorker.id}:`, error);
450
+ }
451
+ });
452
+ await Promise.allSettled(terminatePromises);
453
+ // 3. Limpiar estado
454
+ this.workers = [];
455
+ this.isInitialized = false;
456
+ this.initPromise = null;
457
+ console.log(`[WorkerPool] Pool cerrado. Estadísticas finales: ${this.completedTasks} completadas, ${this.failedTasks} fallidas`);
458
+ }
459
+ /**
460
+ * Obtiene estadísticas del pool
461
+ */
462
+ getStats() {
463
+ const busyWorkers = this.workers.filter(w => w.busy).length;
464
+ const totalPendingTasks = this.workers.reduce((sum, w) => sum + w.pendingTasks.size, 0);
465
+ const successRate = this.totalTasks > 0
466
+ ? Math.round((this.completedTasks / this.totalTasks) * 100)
467
+ : 0;
468
+ return {
469
+ poolSize: this.workers.length,
470
+ busyWorkers,
471
+ totalPendingTasks,
472
+ totalTasks: this.totalTasks,
473
+ completedTasks: this.completedTasks,
474
+ failedTasks: this.failedTasks,
475
+ successRate,
476
+ };
477
+ }
478
+ }
479
+ //# sourceMappingURL=typescript-worker-pool.js.map
@@ -16,10 +16,10 @@ export class TypeScriptWorkerManager {
16
16
  pendingTasks = new Map();
17
17
  taskCounter = 0;
18
18
  workerReady = false;
19
- initPromise = null;
20
- // Configuración del worker
21
- WORKER_TIMEOUT = 30000; // 30 segundos timeout (incrementado)
19
+ initPromise = null; // Configuración del worker private readonly WORKER_TIMEOUT = 45000; // 45 segundos timeout (incrementado para manejar concurrencia)
22
20
  MAX_RETRY_ATTEMPTS = 2;
21
+ MAX_CONCURRENT_TASKS = 20; // Aumentar límite de tareas concurrentes
22
+ TASK_TIMEOUT = 15000; // 15 segundos timeout por tarea individual
23
23
  // NUEVOS: Gestión de modo y estado para optimización
24
24
  currentMode = null;
25
25
  constructor() { }
@@ -50,29 +50,38 @@ export class TypeScriptWorkerManager {
50
50
  }
51
51
  this.initPromise = this._performWorkerInitialization();
52
52
  return this.initPromise;
53
- } /**
53
+ }
54
+ /**
54
55
  * Realiza la inicialización del worker thread
55
- */
56
- async _performWorkerInitialization() {
56
+ */ async _performWorkerInitialization() {
57
57
  try {
58
- // Obtener ruta al worker thread (compatible con ES modules y Windows)
59
- const workerPath = path.join(process.env.PATH_PROY || process.cwd(), 'compiler', 'typescript-worker-thread.cjs');
60
- // console.log('[WorkerManager] Inicializando worker en:', workerPath);
58
+ console.log('[WorkerManager] 🚀 Iniciando proceso de inicialización del worker...'); // Obtener ruta al worker thread (compatible con ES modules y Windows)
59
+ const workerPath = path.join(process.env.PATH_PROY || path.join(process.cwd(), 'src'), 'compiler', 'typescript-worker-thread.cjs');
60
+ console.log('[WorkerManager] 📂 Ruta del worker:', workerPath);
61
+ console.log('[WorkerManager] 🌍 PATH_PROY:', process.env.PATH_PROY);
62
+ console.log('[WorkerManager] 📁 CWD:', process.cwd());
63
+ // Verificar que el archivo existe
64
+ const fs = await import('node:fs');
65
+ const exists = fs.existsSync(workerPath);
66
+ console.log('[WorkerManager] 📋 Worker file exists:', exists);
61
67
  // Crear el worker thread sin tsx para evitar dependencias externas
68
+ console.log('[WorkerManager] 🔧 Creando Worker...');
62
69
  this.worker = new Worker(workerPath, {
63
70
  env: {
64
71
  ...process.env,
65
72
  NODE_OPTIONS: '', // Limpiar NODE_OPTIONS para evitar conflictos con tsx
66
73
  },
67
74
  });
75
+ console.log('[WorkerManager] ✅ Worker creado, configurando listeners...');
68
76
  // Configurar listeners del worker
69
77
  this.setupWorkerListeners();
78
+ console.log('[WorkerManager] ⏳ Esperando que el worker esté listo...');
70
79
  // Esperar a que el worker esté listo
71
80
  await this.waitForWorkerReady();
72
- // console.log('[WorkerManager] Worker inicializado exitosamente');
81
+ console.log('[WorkerManager] Worker inicializado exitosamente');
73
82
  }
74
83
  catch (error) {
75
- console.error('[WorkerManager] Error inicializando worker:', error);
84
+ console.error('[WorkerManager] Error inicializando worker:', error);
76
85
  this.worker = null;
77
86
  this.workerReady = false;
78
87
  throw error;
@@ -178,33 +187,55 @@ export class TypeScriptWorkerManager {
178
187
  */
179
188
  generateTaskId() {
180
189
  return `task-${++this.taskCounter}-${Date.now()}`;
181
- } /**
190
+ }
191
+ /**
182
192
  * Realiza type checking usando el worker thread (con fallback síncrono)
183
193
  * @param fileName - Nombre del archivo TypeScript
184
194
  * @param content - Contenido del archivo
185
195
  * @param compilerOptions - Opciones del compilador TypeScript
186
196
  * @returns Resultado de la validación de tipos
187
- */
188
- async typeCheck(fileName, content, compilerOptions) {
197
+ */ async typeCheck(fileName, content, compilerOptions) {
198
+ // Limitar tareas concurrentes para evitar saturación
199
+ if (this.pendingTasks.size >= this.MAX_CONCURRENT_TASKS) {
200
+ return this.typeCheckWithSyncFallback(fileName, content, compilerOptions);
201
+ }
189
202
  // En modo de testing o si hay problemas de inicialización, usar fallback directo
190
203
  if (process.env.NODE_ENV === 'test' || !this.worker) {
204
+ if (!this.worker) {
205
+ try {
206
+ await this.initializeWorker();
207
+ if (this.worker && this.workerReady) {
208
+ console.log('[WorkerManager] ✅ Worker inicializado exitosamente, reintentando...');
209
+ return this.typeCheckWithWorker(fileName, content, compilerOptions);
210
+ }
211
+ }
212
+ catch (error) {
213
+ console.error('[WorkerManager] ❌ Error inicializando worker:', error);
214
+ }
215
+ }
216
+ console.log('[WorkerManager] 🔄 Usando fallback síncrono (test mode o worker no disponible)');
191
217
  return this.typeCheckWithSyncFallback(fileName, content, compilerOptions);
192
218
  }
193
219
  try {
194
- // Intentar usar el worker thread con timeout más corto
220
+ console.log('[WorkerManager] 🚀 Intentando usar worker thread...');
221
+ // Intentar usar el worker thread con timeout más realista
195
222
  const workerPromise = this.typeCheckWithWorker(fileName, content, compilerOptions);
196
223
  const timeoutPromise = new Promise((resolve, reject) => {
197
224
  setTimeout(() => {
225
+ console.log('[WorkerManager] ⏰ Worker timeout, usando fallback');
198
226
  reject(new Error('Worker timeout - usando fallback'));
199
- }, 5000); // 5 segundos max para worker
227
+ }, this.TASK_TIMEOUT); // Usar timeout por tarea más realista
200
228
  });
201
- return await Promise.race([workerPromise, timeoutPromise]);
229
+ console.log('[WorkerManager] ⏳ Esperando respuesta del worker...');
230
+ const result = await Promise.race([workerPromise, timeoutPromise]);
231
+ console.log('[WorkerManager] ✅ Worker completado exitosamente');
232
+ return result;
202
233
  }
203
234
  catch (workerError) {
204
235
  const errorMessage = workerError instanceof Error
205
236
  ? workerError.message
206
237
  : String(workerError);
207
- console.warn('[WorkerManager] Error en worker, usando fallback síncrono:', errorMessage);
238
+ console.warn('[WorkerManager] Error en worker, usando fallback síncrono:', errorMessage);
208
239
  // Fallback a validación síncrona
209
240
  return this.typeCheckWithSyncFallback(fileName, content, compilerOptions);
210
241
  }
@@ -219,12 +250,11 @@ export class TypeScriptWorkerManager {
219
250
  throw new Error('Worker no disponible');
220
251
  }
221
252
  return new Promise((resolve, reject) => {
222
- const taskId = this.generateTaskId();
223
- // Configurar timeout para la tarea
253
+ const taskId = this.generateTaskId(); // Configurar timeout para la tarea
224
254
  const timeout = setTimeout(() => {
225
255
  this.pendingTasks.delete(taskId);
226
256
  reject(new Error(`Timeout en type checking para ${fileName}`));
227
- }, this.WORKER_TIMEOUT);
257
+ }, this.TASK_TIMEOUT);
228
258
  // Agregar tarea a la lista de pendientes
229
259
  this.pendingTasks.set(taskId, {
230
260
  resolve,