@arela/uploader 1.0.23 → 1.1.0

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.
Files changed (85) hide show
  1. package/docs/AUTO_PROCESSING_PIPELINE.md +258 -0
  2. package/docs/COMPLETE_USAGE_GUIDE.md +1363 -0
  3. package/docs/DATABASESERVICE_IMPROVEMENTS.md +546 -0
  4. package/docs/PASO_2_TEST_RESULTS.md +298 -0
  5. package/docs/PASO_3_PLAN.md +385 -0
  6. package/docs/PHASE_1_FILE_DETECTION.md +366 -0
  7. package/docs/PHASE_2_API_INTEGRATION.md +426 -0
  8. package/docs/PHASE_3_DATABASE_MANAGEMENT.md +480 -0
  9. package/docs/PHASE_4_FILE_OPERATIONS.md +448 -0
  10. package/docs/PHASE_5_WATCH_MODE.md +450 -0
  11. package/docs/PHASE_6_SIGNAL_HANDLING.md +472 -0
  12. package/docs/PHASE_7_ADVANCED_FEATURES.md +560 -0
  13. package/docs/PLAN_WATCH_FEATURE.md +417 -0
  14. package/docs/README.md +480 -0
  15. package/docs/SCHEMA_ALIGNMENT_SUMMARY.md +301 -0
  16. package/docs/SMARTWATCH_DATABASE_REFACTORING.md +181 -0
  17. package/docs/SMART_WATCH_DATABASE_CHANGES.md +502 -0
  18. package/docs/TESTING_WATCH_MODE.md +212 -0
  19. package/docs/WATCHER_API_IMPLEMENTATION.md +520 -0
  20. package/docs/WATCHER_API_INTEGRATION.md +562 -0
  21. package/docs/WATCHER_SETUP_GUIDE.md +614 -0
  22. package/docs/WATCH_ARCHITECTURE.md +395 -0
  23. package/docs/WATCH_AUTO_PIPELINE.md +334 -0
  24. package/docs/WATCH_CONFIGURATION.md +267 -0
  25. package/docs/WATCH_USAGE_GUIDE.md +567 -0
  26. package/docs/commands.md +14 -0
  27. package/package.json +1 -1
  28. package/scripts/scoring-compare.js +243 -0
  29. package/scripts/scoring-phase4-check.js +96 -0
  30. package/src/commands/IdentifyCommand.js +36 -0
  31. package/src/config/config.js +2 -2
  32. package/src/file-detection.js +71 -4
  33. package/src/scoring/db-matcher-adapter.js +98 -0
  34. package/src/scoring/matchers-seed.js +386 -0
  35. package/src/scoring/scoring-engine.js +246 -0
  36. package/src/services/ScanApiService.js +14 -0
  37. package/tests/unit/scoring-engine.test.js +221 -0
  38. package/.vscode/settings.json +0 -1
  39. package/coverage/IdentifyCommand.js.html +0 -1462
  40. package/coverage/PropagateCommand.js.html +0 -1507
  41. package/coverage/PushCommand.js.html +0 -1504
  42. package/coverage/ScanCommand.js.html +0 -1654
  43. package/coverage/UploadCommand.js.html +0 -1846
  44. package/coverage/WatchCommand.js.html +0 -4111
  45. package/coverage/base.css +0 -224
  46. package/coverage/block-navigation.js +0 -87
  47. package/coverage/favicon.png +0 -0
  48. package/coverage/index.html +0 -191
  49. package/coverage/lcov-report/IdentifyCommand.js.html +0 -1462
  50. package/coverage/lcov-report/PropagateCommand.js.html +0 -1507
  51. package/coverage/lcov-report/PushCommand.js.html +0 -1504
  52. package/coverage/lcov-report/ScanCommand.js.html +0 -1654
  53. package/coverage/lcov-report/UploadCommand.js.html +0 -1846
  54. package/coverage/lcov-report/WatchCommand.js.html +0 -4111
  55. package/coverage/lcov-report/base.css +0 -224
  56. package/coverage/lcov-report/block-navigation.js +0 -87
  57. package/coverage/lcov-report/favicon.png +0 -0
  58. package/coverage/lcov-report/index.html +0 -191
  59. package/coverage/lcov-report/prettify.css +0 -1
  60. package/coverage/lcov-report/prettify.js +0 -2
  61. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  62. package/coverage/lcov-report/sorter.js +0 -210
  63. package/coverage/lcov.info +0 -1937
  64. package/coverage/prettify.css +0 -1
  65. package/coverage/prettify.js +0 -2
  66. package/coverage/sort-arrow-sprite.png +0 -0
  67. package/coverage/sorter.js +0 -210
  68. package/docs/API_ENDPOINTS_FOR_DETECTION.md +0 -647
  69. package/docs/API_RETRY_MECHANISM.md +0 -338
  70. package/docs/ARELA_IDENTIFY_IMPLEMENTATION.md +0 -489
  71. package/docs/ARELA_IDENTIFY_QUICKREF.md +0 -186
  72. package/docs/ARELA_PROPAGATE_IMPLEMENTATION.md +0 -581
  73. package/docs/ARELA_PROPAGATE_QUICKREF.md +0 -272
  74. package/docs/ARELA_PUSH_IMPLEMENTATION.md +0 -577
  75. package/docs/ARELA_PUSH_QUICKREF.md +0 -322
  76. package/docs/ARELA_SCAN_IMPLEMENTATION.md +0 -373
  77. package/docs/ARELA_SCAN_QUICKREF.md +0 -139
  78. package/docs/CROSS_PLATFORM_PATH_HANDLING.md +0 -597
  79. package/docs/DETECTION_ATTEMPT_TRACKING.md +0 -414
  80. package/docs/MIGRATION_UPLOADER_TO_FILE_STATS.md +0 -1020
  81. package/docs/MULTI_LEVEL_DIRECTORY_SCANNING.md +0 -494
  82. package/docs/QUICK_REFERENCE_API_DETECTION.md +0 -264
  83. package/docs/REFACTORING_SUMMARY_DETECT_PEDIMENTOS.md +0 -200
  84. package/docs/STATS_COMMAND_SEQUENCE_DIAGRAM.md +0 -287
  85. package/docs/STATS_COMMAND_SIMPLE.md +0 -93
@@ -0,0 +1,301 @@
1
+ # Schema Alignment: arela-uploader ↔ arela-api
2
+
3
+ ## 📋 Resumen Ejecutivo
4
+
5
+ Se han realizado cambios para alinear el schema de BD entre ambas aplicaciones, adoptando un **patrón dual-status** que respeta las responsabilidades de cada sistema:
6
+
7
+ - **arela-uploader**: Gestiona `status` (ciclo de detección)
8
+ - **arela-api**: Gestiona `processing_status` (ciclo de procesamiento/upload)
9
+
10
+ ---
11
+
12
+ ## 🔄 Cambios Realizados
13
+
14
+ ### 1. **Nueva Migración: `002_align_with_arela_api_schema.sql`**
15
+
16
+ **Ubicación:** `/supabase/migrations/002_align_with_arela_api_schema.sql`
17
+
18
+ **Cambios:**
19
+ - ✅ Convierte `created_at` a `TIMESTAMP WITH TIME ZONE`
20
+ - ✅ Agrega `updated_at` (reemplaza `modified_at` gradualmente)
21
+ - ✅ Agrega `deleted_at` (soft delete, de BaseEntity)
22
+ - ✅ Agrega columnas de audit: `created_by`, `updated_by`, `deleted_by`
23
+ - ✅ Agrega `seq` (auto-increment de TypeORM)
24
+ - ✅ Agrega columnas de queue:
25
+ - `processing_status` (default: 'PENDING')
26
+ - `upload_attempts` (default: 0)
27
+ - `depends_on_path`
28
+ - `pedimento_detected_at`
29
+ - `last_error`
30
+ - `file_order`
31
+ - ✅ Crea 15 índices para optimizar queries
32
+ - ✅ Elimina tablas no usadas:
33
+ - `error_tracking`
34
+ - `upload_logs`
35
+ - `performance_metrics`
36
+ - `watch_sessions`
37
+
38
+ **Ejecución:**
39
+ ```bash
40
+ # En arela-uploader:
41
+ npm run migration:run
42
+ ```
43
+
44
+ ---
45
+
46
+ ### 2. **DatabaseService.js - Actualización de Inserts**
47
+
48
+ **Cambios realizados:**
49
+
50
+ #### En `insertStatsToUploaderTable()`:
51
+ ```javascript
52
+ // ANTES:
53
+ const record = {
54
+ status: 'stats',
55
+ created_at: new Date().toISOString(),
56
+ modified_at: stats.mtime.toISOString(),
57
+ };
58
+
59
+ // DESPUÉS:
60
+ const record = {
61
+ status: 'stats', // ← Interno (arela-uploader)
62
+ processing_status: 'PENDING', // ← NUEVO (para arela-api)
63
+ upload_attempts: 0, // ← NUEVO
64
+ created_at: new Date().toISOString(),
65
+ updated_at: new Date().toISOString(), // ← NUEVO (junto con modified_at)
66
+ modified_at: stats.mtime.toISOString(),
67
+ };
68
+ ```
69
+
70
+ #### En `insertStatsOnlyToUploaderTable()`:
71
+ ```javascript
72
+ // ANTES:
73
+ const record = {
74
+ status: 'fs-stats',
75
+ created_at: new Date().toISOString(),
76
+ modified_at: stats.mtime.toISOString(),
77
+ };
78
+
79
+ // DESPUÉS:
80
+ const record = {
81
+ status: 'fs-stats', // ← Interno (arela-uploader)
82
+ processing_status: 'PENDING', // ← NUEVO (para arela-api)
83
+ upload_attempts: 0, // ← NUEVO
84
+ created_at: new Date().toISOString(),
85
+ updated_at: new Date().toISOString(), // ← NUEVO
86
+ modified_at: stats.mtime.toISOString(),
87
+ };
88
+ ```
89
+
90
+ ---
91
+
92
+ ### 3. **SmartWatchDatabaseService.js - Agregar updated_at**
93
+
94
+ **En `markPedimentoDetected()`:**
95
+ ```javascript
96
+ // ANTES:
97
+ await supabase.from('uploader').update({
98
+ pedimento_detected_at: new Date().toISOString(),
99
+ processing_status: 'READY_TO_UPLOAD',
100
+ })
101
+
102
+ // DESPUÉS:
103
+ await supabase.from('uploader').update({
104
+ pedimento_detected_at: new Date().toISOString(),
105
+ processing_status: 'READY_TO_UPLOAD',
106
+ updated_at: new Date().toISOString(), // ← NUEVO
107
+ })
108
+ ```
109
+
110
+ ---
111
+
112
+ ## 📊 Matriz de Responsabilidades - AHORA SINCRONIZADO
113
+
114
+ ```
115
+ ┌─────────────────────────────────────────────────────────────────┐
116
+ │ TABLA UPLOADER (Shared) │
117
+ ├─────────────────────────────────────────────────────────────────┤
118
+ │ Columna │ Controlado por │ Valores/Default │
119
+ ├────────────────────┼───────────────────┼──────────────────────┤
120
+ │ id │ System (UUID) │ uuid_generate_v4() │
121
+ │ seq │ System (TypeORM) │ SERIAL (auto-inc) │
122
+ │ │ │ │
123
+ │ filename │ arela-uploader │ basename of file │
124
+ │ original_path (PK) │ arela-uploader │ full path (unique) │
125
+ │ file_extension │ arela-uploader │ .pdf, .xml, etc │
126
+ │ size │ arela-uploader │ bytes │
127
+ │ │ │ │
128
+ │ document_type │ arela-uploader │ pedimento, etc │
129
+ │ num_pedimento │ arela-uploader │ RFC number │
130
+ │ is_like_simplif │ arela-uploader │ boolean │
131
+ │ year │ arela-uploader │ 2025, 2024, etc │
132
+ │ arela_path │ arela-uploader │ /2025/RFC/file.pdf │
133
+ │ rfc │ arela-uploader │ RFC number │
134
+ │ │ │ │
135
+ │ status ⭐ │ arela-uploader │ stats, detected, │
136
+ │ │ │ detection-error, │
137
+ │ │ │ unsupported, etc │
138
+ │ │ │ │
139
+ │ processing_status │ arela-api │ PENDING, │
140
+ │ ⭐ (NEW) │ │ READY_TO_UPLOAD, │
141
+ │ │ │ PROCESSING, │
142
+ │ │ │ UPLOADED, FAILED │
143
+ │ │ │ [DEFAULT: PENDING] │
144
+ │ │ │ │
145
+ │ upload_attempts │ arela-api │ 0, 1, 2, 3... │
146
+ │ (NEW) │ │ [DEFAULT: 0] │
147
+ │ │ │ │
148
+ │ last_error │ arela-api │ error message string │
149
+ │ (NEW) │ │ [NULLABLE] │
150
+ │ │ │ │
151
+ │ depends_on_path │ arela-uploader │ /path/to/pedimento │
152
+ │ (NEW) │ │ [NULLABLE] │
153
+ │ │ │ │
154
+ │ pedimento_detecte │ arela-uploader │ timestamp when │
155
+ │ d_at (NEW) │ │ pedimento found │
156
+ │ │ │ [NULLABLE] │
157
+ │ │ │ │
158
+ │ file_order │ arela-api │ display/processing │
159
+ │ (NEW) │ │ order [NULLABLE] │
160
+ │ │ │ │
161
+ │ created_at │ System (audit) │ TIMESTAMP WITH TZ │
162
+ │ updated_at │ System (audit) │ TIMESTAMP WITH TZ │
163
+ │ (NEW) │ │ │
164
+ │ deleted_at │ System (soft-del) │ TIMESTAMP WITH TZ │
165
+ │ (NEW) │ │ [NULLABLE] │
166
+ │ │ │ │
167
+ │ created_by │ System (audit) │ user_id string │
168
+ │ (NEW) │ │ [NULLABLE] │
169
+ │ │ │ │
170
+ │ updated_by │ System (audit) │ user_id string │
171
+ │ (NEW) │ │ [NULLABLE] │
172
+ │ │ │ │
173
+ │ deleted_by │ System (audit) │ user_id string │
174
+ │ (NEW) │ │ [NULLABLE] │
175
+ │ │ │ │
176
+ │ message │ arela-uploader │ error/status message │
177
+ │ modified_at │ arela-uploader │ file mtime (legacy) │
178
+ │ metadata │ Both (flexible) │ JSON (flexible) │
179
+ └────────────────────┴───────────────────┴──────────────────────┘
180
+ ```
181
+
182
+ ---
183
+
184
+ ## 🔄 Flujo de Datos - Dual Status
185
+
186
+ ### Ejemplo 1: Archivo Normal
187
+ ```
188
+ Archivo detectado por arela-uploader
189
+ ├─ status: 'detected' (arela-uploader)
190
+ └─ processing_status: 'PENDING' (arela-api, default)
191
+
192
+ Archivo procesado por arela-api
193
+ ├─ status: 'detected' (sin cambios)
194
+ └─ processing_status: 'READY_TO_UPLOAD'
195
+
196
+ Archivo en carga
197
+ ├─ status: 'detected'
198
+ ├─ processing_status: 'PROCESSING'
199
+ └─ upload_attempts: 1
200
+
201
+ Carga exitosa
202
+ ├─ status: 'detected'
203
+ ├─ processing_status: 'UPLOADED'
204
+ └─ uploaded_at: [timestamp]
205
+
206
+ Carga fallida
207
+ ├─ status: 'detected'
208
+ ├─ processing_status: 'FAILED'
209
+ ├─ upload_attempts: 3
210
+ └─ last_error: 'Network timeout'
211
+ ```
212
+
213
+ ### Ejemplo 2: Archivo sin Detección
214
+ ```
215
+ Archivo pero sin pedimento válido
216
+ ├─ status: 'not-detected' (arela-uploader)
217
+ └─ processing_status: 'PENDING' (arela-api)
218
+
219
+ (Permanece en PENDING indefinidamente o se archiva)
220
+ ```
221
+
222
+ ---
223
+
224
+ ## 📈 Ventajas del Dual-Status Pattern
225
+
226
+ 1. **Separación de responsabilidades clara:**
227
+ - `status` = interno de detección (arela-uploader)
228
+ - `processing_status` = para queue/api (arela-api)
229
+
230
+ 2. **Sin conflictos:**
231
+ - Cada sistema actualiza su propia columna
232
+ - No hay race conditions
233
+ - Ambos leen sin problemas
234
+
235
+ 3. **Compatible con SmartWatchDatabaseService:**
236
+ - Ya estaba usando `processing_status`
237
+ - Ahora funciona con la BD correctamente
238
+
239
+ 4. **Completo para arela-api:**
240
+ - Puede calcular `/stats` desde `processing_status`
241
+ - Puede calcular `/health` desde `processing_status + upload_attempts`
242
+ - Puede calcular `/progress` desde conteos
243
+
244
+ 5. **Auditía y Debugging:**
245
+ - `updated_at` para saber cuándo cambió estado
246
+ - `created_by`, `updated_by` para quién lo cambió
247
+ - `last_error` para debugging de fallos
248
+ - `upload_attempts` para reintentos
249
+
250
+ ---
251
+
252
+ ## ✅ Checklist de Verificación
253
+
254
+ ### En arela-uploader:
255
+ - [ ] Ejecutar: `npm run migration:run`
256
+ - [ ] Verificar que `insertStatsToUploaderTable()` ahora incluye `processing_status`
257
+ - [ ] Verificar que `insertStatsOnlyToUploaderTable()` ahora incluye `processing_status`
258
+ - [ ] Verificar que `SmartWatchDatabaseService` usa `updated_at`
259
+ - [ ] Tests pasan: `npm test`
260
+ - [ ] Ejecutar un watch mode y verificar que inserta `processing_status: 'PENDING'`
261
+
262
+ ### En arela-api:
263
+ - [ ] Con `synchronize: true`, TypeORM sincronizará automáticamente
264
+ - [ ] Verificar que `Uploader.entity.ts` tenga todas columnas
265
+ - [ ] Endpoints funcionan:
266
+ - [ ] `GET /stats` → cuenta `processing_status`
267
+ - [ ] `GET /health` → calcula desde `processing_status`
268
+ - [ ] `GET /progress` → calcula % desde UPLOADED/TOTAL
269
+ - [ ] `GET /failed` → filtra `processing_status='FAILED'`
270
+ - [ ] `POST /retry` → actualiza a `processing_status='PENDING'`
271
+
272
+ ### Integración:
273
+ - [ ] Ambas BD leen/escriben correctamente
274
+ - [ ] Sin conflictos en updates
275
+ - [ ] Frontend recibe datos consistentes
276
+
277
+ ---
278
+
279
+ ## 🚀 Próximos Pasos
280
+
281
+ ### Fase 1 (Ahora - v1.0 Estable)
282
+ - ✅ Dual-status implementado
283
+ - ✅ Migración creada
284
+ - ✅ DatabaseService actualizado
285
+ - ✅ SmartWatchDatabaseService listo
286
+
287
+ ### Fase 2 (Futuro - Mejoras)
288
+ - Gradualmente migrar `modified_at` → `updated_at` en arela-uploader
289
+ - Implementar triggers en BD para audit automático
290
+ - Agregar `file_order` para control de procesamiento
291
+ - Soft deletes con `deleted_at` si se necesita
292
+
293
+ ---
294
+
295
+ ## 📝 Notas
296
+
297
+ - `modified_at` se mantiene por compatibilidad hacia atrás con arela-uploader
298
+ - `updated_at` coexiste y es el estándar de BaseEntity
299
+ - TypeORM con `synchronize: true` en arela-api mantendrá sincronizadas las nuevas columnas
300
+ - Todos los valores por defecto están sincronizados entre migración SQL y Entity de TypeORM
301
+
@@ -0,0 +1,181 @@
1
+ # SmartWatchDatabaseService - Refactoring Guide
2
+
3
+ ## 📋 Overview
4
+
5
+ Se ha extraído la funcionalidad de Smart Watch Queue del `DatabaseService` (que tenía >2600 líneas) a un nuevo servicio especializado `SmartWatchDatabaseService` (~500 líneas).
6
+
7
+ ### Cambios realizados:
8
+
9
+ **DatabaseService.js**
10
+ - ✅ Reducido de 2664 a 2183 líneas (-481 líneas)
11
+ - ✅ Agregados métodos públicos: `getSupabaseClient()` y `queryWithRetry()` para inyección de dependencias
12
+ - ✅ Mantiene toda la funcionalidad existente intacta (sin breaking changes)
13
+
14
+ **SmartWatchDatabaseService.js** (NUEVO)
15
+ - ✅ 13 métodos especializados para manejo de cola inteligente
16
+ - ✅ Usa DatabaseService como dependencia inyectada
17
+ - ✅ Modular y reutilizable
18
+
19
+ ## 🔌 Cómo integrar en WatchService
20
+
21
+ ### Opción 1: Inyección en constructor (Recomendado)
22
+
23
+ ```javascript
24
+ import { databaseService } from './DatabaseService.js';
25
+ import SmartWatchDatabaseService from './SmartWatchDatabaseService.js';
26
+
27
+ export class WatchService {
28
+ constructor() {
29
+ // ... otros inicializadores
30
+ this.smartWatchDb = new SmartWatchDatabaseService(databaseService);
31
+ }
32
+
33
+ async handleNewFile(filePath) {
34
+ const isPedimento = await this.#isPedimentoSimplificado(filePath);
35
+ const parentDir = path.dirname(filePath);
36
+
37
+ if (isPedimento) {
38
+ // Insertamos pedimento y actualizamos pendientes automáticamente
39
+ await this.smartWatchDb.markPedimentoDetected(parentDir, filePath);
40
+ } else {
41
+ // Insertamos archivo como PENDING
42
+ await this.smartWatchDb.insertFileToUploader(filePath, {
43
+ processingStatus: 'PENDING',
44
+ dependsOnPath: parentDir,
45
+ size: fs.statSync(filePath).size,
46
+ fileExtension: path.extname(filePath).slice(1)
47
+ });
48
+ }
49
+ }
50
+ }
51
+ ```
52
+
53
+ ### Opción 2: Inyección estática en singleton
54
+
55
+ ```javascript
56
+ // smartWatchDatabaseService.js
57
+ import { databaseService } from './DatabaseService.js';
58
+ import SmartWatchDatabaseService from './SmartWatchDatabaseService.js';
59
+
60
+ export const smartWatchDatabaseService = new SmartWatchDatabaseService(databaseService);
61
+ export default smartWatchDatabaseService;
62
+ ```
63
+
64
+ Luego en WatchService:
65
+
66
+ ```javascript
67
+ import smartWatchDatabaseService from './smartWatchDatabaseService.js';
68
+
69
+ export class WatchService {
70
+ async handleNewFile(filePath) {
71
+ // ... usar smartWatchDatabaseService.insertFileToUploader()
72
+ }
73
+ }
74
+ ```
75
+
76
+ ## 📚 Métodos Disponibles
77
+
78
+ | Método | Descripción | Parámetros |
79
+ |--------|-------------|-----------|
80
+ | `insertFileToUploader()` | Inserta archivo con estado inicial | `filePath, options` |
81
+ | `getPendingFilesInDirectory()` | Obtiene PENDING en directorio | `dirPath` |
82
+ | `getFilesWithStatus()` | Obtiene archivos por status | `statuses[], limit` |
83
+ | `updateFileStatus()` | Actualiza estado del archivo | `filePath, updates` |
84
+ | `markPedimentoDetected()` | Marca pedimento (auto-update) | `dirPath, pedimentoPath` |
85
+ | `getExpiredWaitingFiles()` | Obtiene archivos huérfanos | `maxWaitTimeSeconds` |
86
+ | `getProcessingStats()` | Estadísticas por status | - |
87
+ | `getFailedFilesForRetry()` | Archivos fallidos para reintentar | `maxAttempts` |
88
+ | `retryFile()` | Reinicia un archivo fallido | `filePath` |
89
+ | `retryFailedFiles()` | Reinicia múltiples archivos | `limit, maxAttempts` |
90
+ | `getOverallProgress()` | Progreso con ETA | - |
91
+ | `getFileDetails()` | Detalles de un archivo | `filePath` |
92
+ | `searchFiles()` | Búsqueda avanzada | `filters` |
93
+
94
+ ## 🔄 Arquitectura
95
+
96
+ ```
97
+ WatchService (monitorea archivos)
98
+
99
+ SmartWatchDatabaseService (gestiona cola)
100
+
101
+ DatabaseService (acceso a DB)
102
+
103
+ Supabase
104
+ ```
105
+
106
+ ## 🧪 Ejemplo Completo
107
+
108
+ ```javascript
109
+ import SmartWatchDatabaseService from './SmartWatchDatabaseService.js';
110
+ import { databaseService } from './DatabaseService.js';
111
+
112
+ class MyService {
113
+ constructor() {
114
+ this.smartWatchDb = new SmartWatchDatabaseService(databaseService);
115
+ }
116
+
117
+ async processNewFile(filePath) {
118
+ // 1. Insertar archivo
119
+ const file = await this.smartWatchDb.insertFileToUploader(filePath, {
120
+ processingStatus: 'PENDING',
121
+ dependsOnPath: path.dirname(filePath)
122
+ });
123
+ console.log(`📝 Archivo registrado: ${file.filename}`);
124
+
125
+ // 2. Monitorear progreso
126
+ const stats = await this.smartWatchDb.getProcessingStats();
127
+ console.log(`📊 Stats: ${stats.pending} pending, ${stats.readyToUpload} ready`);
128
+
129
+ // 3. Cuando se detecta pedimento
130
+ await this.smartWatchDb.markPedimentoDetected(
131
+ path.dirname(filePath),
132
+ pedimentoPath
133
+ );
134
+ // ↑ Automáticamente actualiza PENDING → READY_TO_UPLOAD
135
+
136
+ // 4. Procesar archivos listos
137
+ const ready = await this.smartWatchDb.getFilesWithStatus(['READY_TO_UPLOAD'], 10);
138
+ for (const file of ready) {
139
+ // Procesar...
140
+ await this.smartWatchDb.updateFileStatus(file.original_path, {
141
+ processing_status: 'UPLOADED'
142
+ });
143
+ }
144
+
145
+ // 5. Manejar reintentos
146
+ const result = await this.smartWatchDb.retryFailedFiles(5, 3);
147
+ console.log(`🔄 Retried: ${result.retried}, Skipped: ${result.skipped}`);
148
+
149
+ // 6. Obtener progreso global
150
+ const progress = await this.smartWatchDb.getOverallProgress();
151
+ console.log(`Progress: ${progress.percentComplete}% - ETA: ${progress.estimatedTimeRemaining}`);
152
+ }
153
+ }
154
+ ```
155
+
156
+ ## ⚙️ Configuración de Retry
157
+
158
+ Todos los métodos incluyen retry automático con exponential backoff:
159
+ - **Máximo de reintentos**: 3 (configurable)
160
+ - **Backoff inicial**: 1 segundo
161
+ - **Backoff máximo**: 30 segundos
162
+ - **Incremento**: Exponencial (2^n)
163
+
164
+ Los errores retriables incluyen:
165
+ - Timeouts
166
+ - Errores de conexión
167
+ - Errores de declaración cancelada
168
+
169
+ ## 🚀 Próximos Pasos
170
+
171
+ 1. Integrar `SmartWatchDatabaseService` en `WatchService`
172
+ 2. Usar métodos de cola en el flujo de detección de archivos
173
+ 3. Implementar UI de monitoreo usando `getProcessingStats()` y `getOverallProgress()`
174
+ 4. Crear endpoints REST en arela-api para acceso a estadísticas
175
+
176
+ ## 📝 Notas
177
+
178
+ - Los métodos usan la instancia privada de Supabase del DatabaseService
179
+ - No hay breaking changes en DatabaseService
180
+ - Los métodos privados de DatabaseService (#queryWithRetry, #getSupabaseClient) ahora tienen wrappers públicos
181
+ - Compatible con todas las versiones de Supabase JS client (v1.x y v2.x)