🐜 Workers (Cloud Functions)
Los workers son Google Cloud Functions que ejecutan tareas asíncronas pesadas. Son disparados por Cloud Tasks (en respuesta a acciones del usuario) o por Cloud Scheduler (tareas programadas). Viven en el repo rial-workers/.
Resumen
| Worker | Cola / Trigger | Descripción |
|---|---|---|
images-download | images-download queue (Cloud Tasks) | Genera signed URLs de GCS para descarga de imágenes |
admin-metrics | admin-metrics-fetcher queue (Cloud Scheduler 2x/día) | Calcula métricas admin y las publica en el caché del backend |
faceswap-recognition | faceswap-recognition queue (Cloud Tasks) | Clasifica imágenes como FACESWAP o BYPASS |
Estos son los tres workers desplegados desde rial-workers. La combinación de prendas usa el
endpoint de jobs y el servicio externo configurado para esa capacidad; no es una Cloud Function
desplegada en este repositorio.
images-download
Qué hace
Genera signed URLs de Google Cloud Storage para las imágenes que el cliente quiere descargar. Procesa las imágenes en lotes para evitar timeouts y actualiza el Job en la BD a medida que avanza.
Cómo se dispara
- El cliente hace clic en “Descargar” en la plataforma
- El backend (
POST /downloads/project-images) crea unJoby encola una tarea en Cloud Tasks con eljobIdy los filtros de búsqueda - Cloud Tasks dispara la Cloud Function
Comportamiento
1. Recibe: { jobId, query: { projectFolderId, statuses, ... } }
2. Consulta la BD para obtener la lista de imágenes filtradas
3. Por cada lote de N imágenes:
a. Llama a GCS para generar signed URLs (expiración: 24 horas)
b. Persiste el resultado del `JobBatch` y su progreso
4. Al terminar todos los lotes:
a. Persiste el `Job` como `COMPLETED` con result: { signedUrls[] }
5. El frontend, que estaba en polling, recibe COMPLETED y descarga los archivosManejo de fallos
- Si falla una operación técnica, responde con
5xxpara permitir el retry de Cloud Tasks. - Errores permanentes, payload inválido o recursos inexistentes responden con
4xx. - Los batches son idempotentes: un batch
DONEno vuelve a generar URLs ni crea tareas duplicadas. - La cancelación remota del Job todavía no está expuesta por el controller de descargas; la UI puede cancelar el polling y la transferencia local, pero una task ya entregada puede continuar.
admin-metrics
Qué hace
Calcula las métricas de rendimiento de todas las compañías y marcas: SKUs por generar, aprobaciones, rechazos, tiempos promedio. Guarda los resultados en Redis vía el endpoint interno POST /cache/admin-metrics.
Cómo se dispara
- Automáticamente: Cloud Scheduler dispara la tarea 2 veces al día (aprox. 06:00 y 18:00 UTC)
- Manualmente: Se puede disparar manualmente desde la consola de GCP si las métricas están desactualizadas
Comportamiento
1. Consulta la BD con queries agregadas para calcular métricas de:
- Companies: casos activos, SKUs totales, tasa de aprobación
- Brands: rendimiento por marca
- Projects: desglose por proyecto
- ProjectFolders: estado y KPIs por caso
2. Formatea el payload como un Job completado con result = metricsData
3. Llama a POST /cache/admin-metrics (con header secret) para cada tipo de métrica
4. El API guarda en Redis con TTL (~12 horas)Autenticación interna
El worker incluye un header secreto que el API verifica:
ADMIN_METRICS_BRANDS_REFRESH_SECRET: [valor-del-secret]Cada tipo de métrica tiene su propio secret. Si el header no coincide, el API rechaza la petición con 401.
Manejo de fallos
- Si Redis está caído: el worker puede fallar y Cloud Tasks reintentará
- Si la BD está lenta: el worker tiene timeout extendido; Cloud Scheduler lo reintentará al siguiente ciclo
- Las métricas antiguas se mantienen en Redis hasta que expira el TTL — el cliente verá datos del último ciclo exitoso
faceswap-recognition
Qué hace
Procesa el reconocimiento facial para proyectos de tipo FACESWAP. Analiza las imágenes de la sesión original y las imágenes de referencia de los modelos de la marca para generar los datos necesarios para el reemplazo de rostros.
Cómo se dispara
- Cuando se crea un proyecto FACESWAP, el backend encola una tarea en Cloud Tasks
- Cloud Tasks dispara la Cloud Function con los parámetros del proyecto
Comportamiento
1. Recibe: jobId, projectId, referenceImages[], sourceImages[]
2. Procesa el reconocimiento facial (modelo de ML)
3. Actualiza el Job con los resultados intermedios
4. Al terminar: Job status=COMPLETED con los datos de reconocimiento
5. El equipo Rial usa estos datos para el paso de generaciónManejo de fallos
- Si falla la clasificación de una imagen, el Job falla y Cloud Tasks puede reintentarlo.
- Los resultados ya persistidos se conservan y los retries procesan únicamente imágenes que aún no han sido clasificadas.
- El clasificador solo devuelve
FACESWAPoBYPASS; ante duda se usaFACESWAP. - Un folder sin imágenes puede completar exitosamente y un Job cancelado se omite sin reintento.
Estructura del repositorio
rial-workers/
├── images-download/
│ ├── src/
│ │ └── index.ts — Entry point de la Cloud Function
│ ├── package.json
│ └── Dockerfile
├── admin-metrics/
│ ├── src/
│ │ └── index.ts
│ ├── package.json
│ └── Dockerfile
└── faceswap-recognition/
├── src/
│ └── index.ts
├── package.json
└── DockerfileCómo agregar un nuevo worker
- Crear una nueva carpeta en
rial-workers/ - Implementar la Cloud Function que procese el Job y llame al API para actualizarlo
- Crear la cola correspondiente en Cloud Tasks (GCP Console o Terraform)
- Agregar el endpoint de encole en el backend (
cloud-tasks.service.ts) - Agregar el tipo de Job en el enum
JobTypedel schema Prisma y correr migración
Los handlers deben responder 4xx para errores permanentes y 5xx para errores técnicos
reintentables. Cloud Tasks entrega al menos una vez, por lo que cada fase debe ser idempotente y
proteger los estados terminales antes de llamar servicios externos o crear nuevos batches.
Logs y monitoreo
Los workers emiten logs a Cloud Logging (GCP). Para ver los logs de un worker en ejecución:
gcloud functions logs read images-download \
--region=southamerica-east1 \
--limit=50Los errores también aparecen en New Relic si el worker llama al backend, ya que las traces se propagan a través del API.