Compare commits

...

1 Commits

Author SHA1 Message Date
renato97
207b7856b5 Actualización: cambios varios y archivos nuevos
- Modificaciones en main.py
- Agregado kubectl
- Agregado plus.md y todo.md
2026-01-10 19:25:37 +00:00
4 changed files with 2044 additions and 1 deletions

BIN
kubectl Normal file

Binary file not shown.

46
main.py
View File

@@ -9,10 +9,15 @@ import time
import fcntl import fcntl
import os import os
import json import json
import threading
from pathlib import Path from pathlib import Path
from datetime import datetime from datetime import datetime
from typing import Optional from typing import Optional
# Load environment variables from .env file
from dotenv import load_dotenv
load_dotenv()
# Configure logging with JSON formatter for production # Configure logging with JSON formatter for production
class JSONFormatter(logging.Formatter): class JSONFormatter(logging.Formatter):
"""JSON formatter for structured logging in production""" """JSON formatter for structured logging in production"""
@@ -234,6 +239,41 @@ def send_error_notification(error_type: str, error_message: str) -> None:
logger.warning(f"Failed to send error notification: {e}") logger.warning(f"Failed to send error notification: {e}")
def run_dashboard_thread() -> None:
"""Run Flask dashboard in a separate thread"""
try:
from api.routes import create_app
app = create_app()
# Run Flask in production mode with threaded=True
app.run(
host='0.0.0.0',
port=5000,
debug=False,
threaded=True,
use_reloader=False # Important: disable reloader in thread
)
except Exception as e:
logger.error(f"Dashboard thread error: {e}")
logger.exception("Dashboard thread exception details")
def start_dashboard() -> threading.Thread:
"""Start dashboard in a background daemon thread"""
dashboard_port = int(os.getenv('DASHBOARD_PORT', '5000'))
logger.info(f"Starting dashboard on port {dashboard_port}...")
# Create daemon thread so it doesn't block shutdown
dashboard_thread = threading.Thread(
target=run_dashboard_thread,
name="DashboardThread",
daemon=True
)
dashboard_thread.start()
logger.info(f"Dashboard thread started (Thread-ID: {dashboard_thread.ident})")
return dashboard_thread
def run_main_loop() -> None: def run_main_loop() -> None:
"""Main processing loop with improved error handling""" """Main processing loop with improved error handling"""
from config import settings from config import settings
@@ -418,6 +458,7 @@ def run_main_loop() -> None:
def main(): def main():
"""Main entry point""" """Main entry point"""
lock_fd = None lock_fd = None
dashboard_thread = None
try: try:
logger.info("=== CBCFacil Service Started ===") logger.info("=== CBCFacil Service Started ===")
logger.info(f"Version: {os.getenv('APP_VERSION', '8.0')}") logger.info(f"Version: {os.getenv('APP_VERSION', '8.0')}")
@@ -425,6 +466,11 @@ def main():
lock_fd = acquire_lock() lock_fd = acquire_lock()
initialize_services() initialize_services()
# Start dashboard in background thread
dashboard_thread = start_dashboard()
# Run main processing loop
run_main_loop() run_main_loop()
except KeyboardInterrupt: except KeyboardInterrupt:

799
plus.md Normal file
View File

@@ -0,0 +1,799 @@
# 🚀 CBCFacil - Mejoras y Extensiones Recomendadas
Documento con recomendaciones para hacer el proyecto más complejo, robusto y profesional.
---
## 📋 Resumen Ejecutivo
Después de analizar todo el proyecto, identifiqué las siguientes áreas principales de mejora:
| Área | Prioridad | Complejidad | Estado Actual |
|------|-----------|-------------|---------------|
| Testing | 🔴 Alta | Media | Solo `conftest.py` existe |
| Frontend Dashboard | 🔴 Alta | Alta | Template básico sin JS |
| Sistema de Colas | 🟡 Media | Alta | Loop síncrono simple |
| Autenticación API | 🔴 Alta | Media | Sin autenticación |
| Base de Datos | 🟡 Media | Media | Solo archivo TXT |
| Métricas/Observabilidad | 🟡 Media | Media | Básico |
| Video Processor | 🟢 Baja | Alta | No existe |
| WebSockets | 🟢 Baja | Media | No existe |
| Internacionalización | 🟢 Baja | Baja | Solo español |
---
## 🧪 1. Testing Completo (CRÍTICO)
### Estado Actual
- Solo existe `tests/conftest.py` y `tests/__init__.py`
- No hay tests unitarios ni de integración implementados
- Arquitectura mencionada en `ARCHITECTURE.md` indica ~60% cobertura (falso)
### Recomendaciones
#### 1.1 Tests Unitarios
```
tests/
├── unit/
│ ├── test_settings.py # Validar configuración
│ ├── test_validators.py # Validar validators.py
│ ├── test_result.py # Patrón Result
│ ├── test_exceptions.py # Excepciones personalizadas
│ ├── test_bloom_filter.py # BloomFilter en registry
│ ├── test_token_bucket.py # Rate limiter
│ └── test_circuit_breaker.py # Circuit breaker
```
#### 1.2 Tests de Integración
```
tests/
├── integration/
│ ├── test_webdav_service.py # Mock de Nextcloud
│ ├── test_telegram_service.py # Mock de Telegram API
│ ├── test_ai_providers.py # Mock de APIs AI
│ ├── test_audio_processor.py # Con audio de prueba
│ ├── test_pdf_processor.py # Con PDF de prueba
│ └── test_document_generator.py
```
#### 1.3 Tests E2E
```
tests/
├── e2e/
│ ├── test_full_audio_workflow.py
│ ├── test_full_pdf_workflow.py
│ └── test_api_endpoints.py
```
#### 1.4 Fixtures de Prueba
```python
# tests/fixtures/
# - sample_audio.mp3 (5 segundos de audio en español)
# - sample_pdf.pdf (2 páginas con texto)
# - expected_transcription.txt
# - expected_summary.md
```
---
## 🖥️ 2. Dashboard Frontend Completo
### Estado Actual
- Solo existe `templates/` con un archivo básico
- API REST sin interfaz visual
- Sin JavaScript interactivo
### Recomendaciones
#### 2.1 Estructura Frontend
```
frontend/
├── src/
│ ├── components/
│ │ ├── FileList.js # Lista de archivos
│ │ ├── FileCard.js # Tarjeta individual
│ │ ├── ProcessingStatus.js # Estado en tiempo real
│ │ ├── GPUMonitor.js # Monitor VRAM
│ │ ├── QueueViewer.js # Cola de procesamiento
│ │ └── NotificationBell.js # Notificaciones
│ ├── pages/
│ │ ├── Dashboard.js # Vista principal
│ │ ├── Files.js # Gestión de archivos
│ │ ├── Settings.js # Configuración
│ │ └── Logs.js # Visor de logs
│ └── services/
│ ├── api.js # Cliente API
│ └── websocket.js # Conexión WS
├── public/
│ └── index.html
└── package.json
```
#### 2.2 Funcionalidades
- [ ] Drag & drop para subir archivos
- [ ] Preview de PDFs y audio
- [ ] Visor de transcripciones lado a lado
- [ ] Editor de resúmenes con Markdown preview
- [ ] Gráficas de uso de GPU/CPU
- [ ] Historial de procesamiento
- [ ] Búsqueda en contenido
- [ ] Dark mode / Light mode
---
## 📬 3. Sistema de Colas (Celery/RQ)
### Estado Actual
- Loop infinito síncrono en `main.py`
- Sin priorización de tareas
- Sin reintentos configurables
- Sin distribución de carga
### Recomendaciones
#### 3.1 Implementar Celery
```python
# services/queue/
__init__.py
celery_app.py # Configuración Celery
tasks/
__init__.py
audio_tasks.py # Tareas de audio
pdf_tasks.py # Tareas de PDF
notification_tasks.py
workers/
worker_config.py
```
#### 3.2 Estructura de Tareas
```python
# tasks/audio_tasks.py
from celery import shared_task
@shared_task(bind=True, max_retries=3, default_retry_delay=60)
def process_audio(self, file_path: str, options: dict) -> dict:
"""Procesar audio con reintentos automáticos"""
...
@shared_task
def transcribe_audio(file_path: str) -> str:
"""Transcribir audio con Whisper"""
...
@shared_task
def generate_summary(transcription: str, base_name: str) -> dict:
"""Generar resumen con IA"""
...
```
#### 3.3 Prioridades de Cola
- `high`: Archivos pequeños (<10MB)
- `default`: Archivos normales
- `low`: Archivos grandes (>100MB)
---
## 🔐 4. Autenticación y Autorización
### Estado Actual
- API completamente abierta
- Sin manejo de sesiones
- Sin roles de usuario
### Recomendaciones
#### 4.1 Implementar JWT
```python
# api/auth/
__init__.py
jwt_handler.py # Generación/validación JWT
middleware.py # Middleware de autenticación
decorators.py # @require_auth, @require_admin
models.py # User, Role, Permission
```
#### 4.2 Endpoints de Auth
```python
# api/routes_auth.py
POST /api/auth/login # Login con usuario/password
POST /api/auth/refresh # Refrescar token
POST /api/auth/logout # Invalidar token
GET /api/auth/me # Perfil del usuario
```
#### 4.3 Roles Sugeridos
- `admin`: Acceso completo
- `processor`: Puede procesar archivos
- `viewer`: Solo lectura
- `api`: Acceso solo API (para integraciones)
---
## 🗄️ 5. Base de Datos (SQLite/PostgreSQL)
### Estado Actual
- Solo `processed_files.txt` como registro
- Sin historial de procesamiento
- Sin metadatos de archivos
### Recomendaciones
#### 5.1 Modelos de Base de Datos
```python
# storage/models/
__init__.py
base.py # SQLAlchemy base
file.py # Modelo File
processing_job.py # Modelo ProcessingJob
user.py # Modelo User
audit_log.py # Modelo AuditLog
```
#### 5.2 Esquema Propuesto
```sql
-- files
CREATE TABLE files (
id SERIAL PRIMARY KEY,
filename VARCHAR(255) NOT NULL,
original_path TEXT,
file_type VARCHAR(20),
file_size BIGINT,
checksum VARCHAR(64),
status VARCHAR(20) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- processing_jobs
CREATE TABLE processing_jobs (
id SERIAL PRIMARY KEY,
file_id INTEGER REFERENCES files(id),
job_type VARCHAR(50),
status VARCHAR(20),
started_at TIMESTAMP,
completed_at TIMESTAMP,
error_message TEXT,
result_path TEXT,
metadata JSONB
);
-- audit_logs
CREATE TABLE audit_logs (
id SERIAL PRIMARY KEY,
user_id INTEGER,
action VARCHAR(50),
resource_type VARCHAR(50),
resource_id INTEGER,
details JSONB,
timestamp TIMESTAMP DEFAULT NOW()
);
```
---
## 📊 6. Métricas y Observabilidad
### Estado Actual
- `services/metrics_collector.py` básico
- Sin exportación a sistemas externos
- Sin dashboards de monitoreo
### Recomendaciones
#### 6.1 Prometheus Metrics
```python
# services/observability/
__init__.py
prometheus_exporter.py # Endpoint /metrics
metrics.py # Definición de métricas
tracing.py # Tracing distribuido
```
#### 6.2 Métricas a Implementar
```python
from prometheus_client import Counter, Histogram, Gauge
# Contadores
files_processed_total = Counter('files_processed_total', 'Total files processed', ['type', 'status'])
ai_requests_total = Counter('ai_requests_total', 'AI API requests', ['provider', 'operation'])
# Histogramas
processing_duration = Histogram('processing_duration_seconds', 'Processing time', ['type'])
ai_response_time = Histogram('ai_response_time_seconds', 'AI response time', ['provider'])
# Gauges
active_jobs = Gauge('active_jobs', 'Currently processing jobs')
vram_usage = Gauge('vram_usage_bytes', 'GPU memory usage')
queue_size = Gauge('queue_size', 'Jobs in queue', ['priority'])
```
#### 6.3 Integración
- [ ] Grafana dashboard preconfigurado
- [ ] Alertas con AlertManager
- [ ] Logs estructurados con Loki
- [ ] Tracing con Jaeger/Zipkin
---
## 🎬 7. Video Processor (NUEVO)
### Recomendaciones
#### 7.1 Estructura
```python
# processors/video_processor.py
class VideoProcessor(FileProcessor):
"""Processor for video files"""
def extract_audio(self, video_path: str) -> str:
"""Extraer audio de video con ffmpeg"""
...
def extract_frames(self, video_path: str, interval: int = 60) -> List[str]:
"""Extraer frames cada N segundos para análisis"""
...
def analyze_frames(self, frames: List[str]) -> Dict[str, Any]:
"""Analizar frames con visión AI (Gemini Vision)"""
...
def process(self, file_path: str) -> Dict[str, Any]:
"""Pipeline completo: audio + frames + análisis"""
...
```
#### 7.2 Extensiones de Video
```python
VIDEO_EXTENSIONS = {".mp4", ".avi", ".mkv", ".mov", ".webm"}
```
#### 7.3 Funcionalidades
- [ ] Transcripción de audio del video
- [ ] Extracción de frames clave
- [ ] Análisis visual con IA (slides, pizarra)
- [ ] Generación de índice por escenas
- [ ] Subtítulos automáticos (SRT/VTT)
---
## 🔌 8. WebSockets para Tiempo Real
### Estado Actual
- Solo API REST
- Sin actualizaciones en tiempo real
- Polling pesado para estado
### Recomendaciones
#### 8.1 Implementación
```python
# api/websocket/
__init__.py
manager.py # ConnectionManager
events.py # Tipos de eventos
handlers.py # Event handlers
```
#### 8.2 Eventos a Implementar
```python
# Eventos del servidor -> cliente
{
"type": "file.processing_started",
"data": {"file_id": 1, "filename": "audio.mp3"}
}
{
"type": "file.processing_progress",
"data": {"file_id": 1, "progress": 45, "stage": "transcribing"}
}
{
"type": "file.processing_completed",
"data": {"file_id": 1, "result_path": "/path/to/result.docx"}
}
{
"type": "system.gpu_usage",
"data": {"vram_used": 4.5, "vram_total": 8.0}
}
```
#### 8.3 Integración con Flask
```python
from flask_socketio import SocketIO, emit
socketio = SocketIO(app, cors_allowed_origins="*")
@socketio.on('connect')
def handle_connect():
emit('connected', {'status': 'ok'})
@socketio.on('subscribe')
def handle_subscribe(data):
join_room(data['file_id'])
```
---
## 🌐 9. API versioning y OpenAPI
### Estado Actual
- API sin versionado
- Sin documentación OpenAPI/Swagger
- Endpoints inconsistentes
### Recomendaciones
#### 9.1 Versionado de API
```
/api/v1/files
/api/v1/process
/api/v1/health
/api/v2/files (futura versión)
```
#### 9.2 OpenAPI Spec
```python
# api/openapi/
spec.yaml # Especificación OpenAPI 3.0
swagger_ui.py # Swagger UI integration
# Usar flask-restx o flasgger
from flask_restx import Api, Resource, fields
api = Api(app,
version='1.0',
title='CBCFacil API',
description='API para procesamiento de documentos'
)
```
---
## 🐳 10. Containerización Mejorada
### Estado Actual
- `.dockerignore` existe pero no Dockerfile completo
- Sin docker-compose
- Sin multi-stage builds
### Recomendaciones
#### 10.1 Docker Multi-stage
```dockerfile
# Dockerfile
FROM python:3.11-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip wheel --no-cache-dir -w /wheels -r requirements.txt
FROM nvidia/cuda:12.1-runtime-ubuntu22.04 as runtime
# ... instalación optimizada
```
#### 10.2 Docker Compose
```yaml
# docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "5000:5000"
environment:
- NVIDIA_VISIBLE_DEVICES=all
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
redis:
image: redis:7-alpine
celery-worker:
build: .
command: celery -A celery_app worker -l info
depends_on:
- redis
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana
ports:
- "3000:3000"
```
---
## 🔧 11. Unificación y Refactoring
### 11.1 AIProvider Unificado
Actualmente existe lógica duplicada entre:
- `services/ai_service.py`
- `services/ai/gemini_provider.py`
- `services/ai/claude_provider.py`
**Recomendación**: Crear interfaz unificada con Chain of Responsibility:
```python
class AIProviderChain:
"""Cadena de proveedores con fallback automático"""
def __init__(self, providers: List[AIProvider]):
self.providers = providers
def generate(self, prompt: str) -> str:
for provider in self.providers:
try:
if provider.is_available():
return provider.generate_text(prompt)
except Exception as e:
logging.warning(f"{provider.name} failed: {e}")
raise AllProvidersFailedError()
```
### 11.2 Procesadores Unificados
Crear pipeline unificado:
```python
class ProcessingPipeline:
def __init__(self):
self.steps = []
def add_step(self, processor: FileProcessor):
self.steps.append(processor)
return self
def process(self, file_path: str) -> Dict[str, Any]:
result = {}
for step in self.steps:
if step.can_process(file_path):
result.update(step.process(file_path))
return result
```
---
## 📱 12. Notificaciones Mejoradas
### Estado Actual
- Solo Telegram
- Sin templates de mensajes
- Sin notificaciones push
### Recomendaciones
#### 12.1 Multi-canal
```python
# services/notifications/
__init__.py
base_notifier.py # Interface base
telegram_notifier.py # Actual optimizado
email_notifier.py # Nuevo
slack_notifier.py # Nuevo
webhook_notifier.py # Para integraciones
notification_manager.py # Orquestador
```
#### 12.2 Templates de Mensaje
```python
TEMPLATES = {
"processing_started": "🎵 Procesando: {filename}\n⏱️ Estimado: {eta}",
"processing_completed": "✅ Completado: {filename}\n📄 Resumen: {summary_url}",
"processing_failed": "❌ Error en {filename}\n🔍 Detalles: {error}",
"daily_summary": "📊 Resumen del día:\n- Procesados: {count}\n- Tiempo total: {time}"
}
```
---
## 🗂️ 13. Sistema de Plugins
### Recomendaciones
```python
# plugins/
__init__.py
base_plugin.py # Interface de plugin
plugin_manager.py # Gestor de plugins
examples/
custom_ocr/ # Plugin OCR personalizado
s3_storage/ # Plugin para AWS S3
discord_notifier/ # Plugin Discord
```
#### Interfaz de Plugin
```python
class BasePlugin(ABC):
"""Base class for plugins"""
@property
@abstractmethod
def name(self) -> str: ...
@property
@abstractmethod
def version(self) -> str: ...
@abstractmethod
def initialize(self, config: dict) -> None: ...
@abstractmethod
def execute(self, context: dict) -> dict: ...
@abstractmethod
def cleanup(self) -> None: ...
```
---
## 📈 14. Mejoras de Rendimiento
### 14.1 Caching Avanzado
```python
# services/cache/
__init__.py
cache_manager.py # Gestor de cache
redis_cache.py # Cache en Redis
file_cache.py # Cache en disco
```
### 14.2 Batch Processing
```python
class BatchProcessor:
"""Procesar múltiples archivos en paralelo"""
def process_batch(self, files: List[str], max_workers: int = 4) -> List[dict]:
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = {executor.submit(self.process_single, f): f for f in files}
results = []
for future in as_completed(futures):
results.append(future.result())
return results
```
### 14.3 Streaming de Archivos Grandes
```python
def stream_process(file_path: str, chunk_size: int = 1024*1024):
"""Procesar archivos grandes en streaming"""
with open(file_path, 'rb') as f:
while chunk := f.read(chunk_size):
yield process_chunk(chunk)
```
---
## 🔒 15. Seguridad Adicional
### 15.1 Validación de Archivos
```python
# services/security/
__init__.py
file_validator.py # Validación de archivos
malware_scanner.py # Escaneo de malware
rate_limiter.py # Rate limiting por IP
```
### 15.2 Checks de Seguridad
- [ ] Validar tipos MIME reales (no solo extensiones)
- [ ] Limitar tamaño máximo de archivo
- [ ] Sanitizar nombres de archivo
- [ ] Escanear con ClamAV
- [ ] Rate limiting por usuario/IP
- [ ] Logs de auditoría
---
## 📝 16. CLI Mejorado
### Estado Actual
- Solo comandos básicos en `main.py`
### Recomendaciones
```python
# cli/
__init__.py
main.py # Click/Typer app
commands/
process.py # cbcfacil process audio.mp3
queue.py # cbcfacil queue list/stats
config.py # cbcfacil config show/set
db.py # cbcfacil db migrate/seed
```
#### Ejemplo con Typer
```python
import typer
app = typer.Typer()
@app.command()
def process(
file: str,
output_dir: str = ".",
format: str = "docx",
ai_provider: str = "auto"
):
"""Procesar archivo de audio o PDF"""
...
@app.command()
def status():
"""Mostrar estado del servicio"""
...
@app.command()
def queue(action: str):
"""Gestionar cola de procesamiento"""
...
```
---
## 📁 Resumen de Nuevos Archivos/Directorios
```
cbc/
├── tests/
│ ├── unit/
│ ├── integration/
│ ├── e2e/
│ └── fixtures/
├── frontend/
│ ├── src/
│ └── public/
├── services/
│ ├── queue/
│ ├── cache/
│ ├── notifications/
│ ├── observability/
│ └── security/
├── api/
│ ├── auth/
│ ├── websocket/
│ └── openapi/
├── storage/
│ └── models/
├── processors/
│ └── video_processor.py
├── plugins/
├── cli/
├── docker-compose.yml
├── prometheus.yml
└── grafana/
```
---
## ✅ Checklist de Implementación
### Fase 1 - Fundamentos (2-3 semanas)
- [ ] Implementar tests unitarios básicos
- [ ] Agregar autenticación JWT
- [ ] Migrar a base de datos SQLite
### Fase 2 - Mejoras Core (3-4 semanas)
- [ ] Implementar sistema de colas con Celery
- [ ] Agregar WebSockets
- [ ] Crear dashboard frontend básico
### Fase 3 - Observabilidad (1-2 semanas)
- [ ] Prometheus metrics
- [ ] Grafana dashboards
- [ ] Logging estructurado
### Fase 4 - Extensiones (2-3 semanas)
- [ ] Video processor
- [ ] Multi-canal de notificaciones
- [ ] Sistema de plugins
### Fase 5 - Producción (2 semanas)
- [ ] Docker compose completo
- [ ] CI/CD pipeline
- [ ] Documentación completa
---
*Documento generado por análisis exhaustivo del proyecto CBCFacil v9*

1198
todo.md Normal file

File diff suppressed because it is too large Load Diff