@arela/uploader 1.0.24 → 1.1.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.
- package/docs/AUTO_PROCESSING_PIPELINE.md +258 -0
- package/docs/COMPLETE_USAGE_GUIDE.md +1363 -0
- package/docs/DATABASESERVICE_IMPROVEMENTS.md +546 -0
- package/docs/PASO_2_TEST_RESULTS.md +298 -0
- package/docs/PASO_3_PLAN.md +385 -0
- package/docs/PHASE_1_FILE_DETECTION.md +366 -0
- package/docs/PHASE_2_API_INTEGRATION.md +426 -0
- package/docs/PHASE_3_DATABASE_MANAGEMENT.md +480 -0
- package/docs/PHASE_4_FILE_OPERATIONS.md +448 -0
- package/docs/PHASE_5_WATCH_MODE.md +450 -0
- package/docs/PHASE_6_SIGNAL_HANDLING.md +472 -0
- package/docs/PHASE_7_ADVANCED_FEATURES.md +560 -0
- package/docs/PLAN_WATCH_FEATURE.md +417 -0
- package/docs/README.md +480 -0
- package/docs/SCHEMA_ALIGNMENT_SUMMARY.md +301 -0
- package/docs/SMARTWATCH_DATABASE_REFACTORING.md +181 -0
- package/docs/SMART_WATCH_DATABASE_CHANGES.md +502 -0
- package/docs/TESTING_WATCH_MODE.md +212 -0
- package/docs/WATCHER_API_IMPLEMENTATION.md +520 -0
- package/docs/WATCHER_API_INTEGRATION.md +562 -0
- package/docs/WATCHER_SETUP_GUIDE.md +614 -0
- package/docs/WATCH_ARCHITECTURE.md +395 -0
- package/docs/WATCH_AUTO_PIPELINE.md +334 -0
- package/docs/WATCH_CONFIGURATION.md +267 -0
- package/docs/WATCH_USAGE_GUIDE.md +567 -0
- package/docs/commands.md +14 -0
- package/package.json +1 -1
- package/src/commands/IdentifyCommand.js +11 -0
- package/src/config/config.js +2 -2
- package/src/file-detection.js +42 -1
- package/src/scoring/scoring-engine.js +40 -7
- package/src/services/LoggingService.js +5 -3
- package/.vscode/settings.json +0 -1
- package/coverage/IdentifyCommand.js.html +0 -1462
- package/coverage/PropagateCommand.js.html +0 -1507
- package/coverage/PushCommand.js.html +0 -1504
- package/coverage/ScanCommand.js.html +0 -1654
- package/coverage/UploadCommand.js.html +0 -1846
- package/coverage/WatchCommand.js.html +0 -4111
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -191
- package/coverage/lcov-report/IdentifyCommand.js.html +0 -1462
- package/coverage/lcov-report/PropagateCommand.js.html +0 -1507
- package/coverage/lcov-report/PushCommand.js.html +0 -1504
- package/coverage/lcov-report/ScanCommand.js.html +0 -1654
- package/coverage/lcov-report/UploadCommand.js.html +0 -1846
- package/coverage/lcov-report/WatchCommand.js.html +0 -4111
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -191
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -210
- package/coverage/lcov.info +0 -1937
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/docs/API_ENDPOINTS_FOR_DETECTION.md +0 -647
- package/docs/API_RETRY_MECHANISM.md +0 -338
- package/docs/ARELA_IDENTIFY_IMPLEMENTATION.md +0 -489
- package/docs/ARELA_IDENTIFY_QUICKREF.md +0 -186
- package/docs/ARELA_PROPAGATE_IMPLEMENTATION.md +0 -581
- package/docs/ARELA_PROPAGATE_QUICKREF.md +0 -272
- package/docs/ARELA_PUSH_IMPLEMENTATION.md +0 -577
- package/docs/ARELA_PUSH_QUICKREF.md +0 -322
- package/docs/ARELA_SCAN_IMPLEMENTATION.md +0 -373
- package/docs/ARELA_SCAN_QUICKREF.md +0 -139
- package/docs/CROSS_PLATFORM_PATH_HANDLING.md +0 -597
- package/docs/DETECTION_ATTEMPT_TRACKING.md +0 -414
- package/docs/MIGRATION_UPLOADER_TO_FILE_STATS.md +0 -1020
- package/docs/MULTI_LEVEL_DIRECTORY_SCANNING.md +0 -494
- package/docs/QUICK_REFERENCE_API_DETECTION.md +0 -264
- package/docs/REFACTORING_SUMMARY_DETECT_PEDIMENTOS.md +0 -200
- package/docs/STATS_COMMAND_SEQUENCE_DIAGRAM.md +0 -287
- 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)
|