Skip to content

Estándar de Cómputo Pesado (HC-001 a HC-004)

🎯 Problema

Cloudflare Workers tienen límite de CPU de 30 segundos. Algoritmos como:

  • Machine Learning (predicciones, clasificaciones)
  • Optimización de rutas (TSP, VRP)
  • Procesamiento de video/imágenes pesado
  • Reportes masivos (millones de registros) ...exceden este límite.

🏗️ Solución: Workers para lógica ligera + Containers para cómputo pesado


⚡ REGLAS INQUEBRANTABLES

HC-001: TODO CÓMPUTO > 15s DEBE IR A CONTAINER

[REQUIRED] Por qué: el límite de CPU del Worker es una pared dura: al alcanzarla la petición se corta a medias, sin resultado y sin forma de recuperarla. El umbral de 15s deja margen deliberado frente al límite real para que la variabilidad de carga no convierta un trabajo que casi cabía en un fallo intermitente.

Regla de decisión:

Duración estimadaDónde ejecutarTecnología
< 15sCloudflare WorkerTypeScript
15s - 10minCloud Run / FargateNode.js, Python
10min - 1horaBatch Job (GCP/AWS)Python, Go
> 1 horaKubernetes JobCualquiera

HC-002: PATRÓN COLA + WORKER → CONTAINER

[REQUIRED] Por qué: la cola desacopla aceptar el trabajo de ejecutarlo, y eso es lo que permite responder rápido, reintentar sin duplicar y absorber picos sin perder peticiones. Llamar al container de forma síncrona traslada su latencia y sus fallos al usuario.

typescript
// 1. Worker recibe request y encola trabajo pesado
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const { videoUrl } = await request.json()
    
    // Encolar trabajo
    const jobId = crypto.randomUUID()
    await env.QUEUE.send({
      id: jobId,
      type: 'process_video',
      payload: { videoUrl },
      status: 'queued'
    })
    
    // Responder inmediatamente
    return Response.json({ jobId, status: 'processing' })
  }
}
python
# 2. Container en Cloud Run procesa el trabajo
import os
from google.cloud import tasks_v2

def process_video(job_id: str, video_url: str):
    # Descargar video
    video = download(video_url)
    
    # Procesar (puede tardar 10 minutos)
    processed = heavy_ml_processing(video)
    
    # Guardar resultado
    upload_to_r2(processed, f"processed/{job_id}.mp4")
    
    # Notificar completado
    requests.post(f"https://api.omnisuite.com/webhooks/jobs/{job_id}", json={
        "status": "completed",
        "result_url": f"https://cdn.omnisuite.com/processed/{job_id}.mp4"
    })

HC-003: PROGRESS TRACKING PARA TRABAJOS LARGOS

[REQUIRED] Por qué: sin señal de progreso el usuario asume que se rompió, recarga y vuelve a lanzar el trabajo — duplicando la carga justo cuando el sistema ya va cargado. El progreso no es una mejora estética: es control de carga.

typescript
// Worker expone endpoint de status
export async function getJobStatus(jobId: string, env: Env): Promise<Response> {
  const job = await env.KV.get(`job:${jobId}`, 'json')
  
  return Response.json({
    id: job.id,
    status: job.status, // queued | processing | completed | failed
    progress: job.progress, // 0-100
    estimated_completion: job.eta,
    result_url: job.result_url
  })
}

// Frontend puede hacer polling o WebSocket
const { data: job } = useQuery({
  queryKey: ['job', jobId],
  queryFn: () => fetch(`/api/jobs/${jobId}`).then(r => r.json()),
  refetchInterval: job => job?.status === 'processing' ? 5000 : false
})

HC-004: WORKER SPIN-UP PARA CÓMPUTO MEDIO

[RECOMMENDED] Por qué: para trabajos en la franja intermedia, arrancar un container cuesta más en latencia y complejidad que el propio cálculo. Es recomendado porque la frontera depende del perfil real de la tarea, y medirla vale más que elegir por regla fija.

typescript
// Para tareas de 15-30s: usar Worker con más memoria
// wrangler.toml
[env.production]
cpu_ms = 30000  # Máximo permitido
memory = "256MB" # Subir de 128MB default

// Si necesita más: evaluar migrar a Container

📊 DECISIÓN RÁPIDA

TareaTiempoSolución
Generar PDF propuesta2sWorker (pdf-lib)
Procesar CSV 10K filas8sWorker (streaming)
Optimizar rutas 50 puntos45sCloud Run
Entrenar modelo ML30minBatch Job
Procesar video 4K10minCloud Run + GPU

171 documentos indexados · generado desde INDEX.json