Incidente 503/1102 — Workers Free asfixiado por el crecimiento de la Biblioteca (05→07 julio 2026)
Incidente 503/1102 — Workers Free asfixiado por el crecimiento de la Biblioteca
✅ INCIDENTE CERRADO (07-07-2026, mañana): Edu contrató Workers Paid (5 $/mes) — verificado activo por API. Límite CPU: 10 ms → 30 s por petición. La clase entera de problema queda eliminada; la dieta de s202 se mantiene por higiene. Task #184 done.
Resumen ejecutivo
Del 05-07 ~00:00Z al 06-07 ~20:00Z, la API del workspace (CF Pages Functions, workspace.crearack.com/api/mcp) devolvió 503 con error code 1102 de forma intermitente: 298 invocaciones muertas con status exceededResources frente a ~23.000 correctas (~1,3%). La madrugada del 06-07 tumbó los 4 crons de mantenimiento wiki (lint, curator, drift-check, utility) y salpicó ciclos sueltos del bib-reindex de Pro. El heartbeat avisó por email el 06-07 a las 10:30Z.
Causa raíz
Cuota de CPU del plan Workers Free (10 ms/petición), no un bug. Evidencia:
- Las invocaciones muertas tienen
cpuTimeP50clavado en 10.000 µs = exactamente 10 ms (el límite del Free; el enforcement es tolerante a ráfagas, por eso hay éxitos con p99 123 ms y el fallo es probabilístico). - La cuenta no tenía suscripción Workers Paid (solo R2/Cache Reserve/Teams, todas a 0 €).
- No hay leak: el único estado residente a nivel de módulo es la cache JWKS (bytes). El binding Vectorize está presente — el fallback D1 que causó el incidente-gemelo de s73 (HTTP 524) está dormido.
Por qué ahora: crecimiento sin dieta cruzando el umbral — 9.436 chunks (~49 MB de embeddings), bib_index_runs con 47.129 filas (el AST de Pro reescribía ~2.470 nodos cada 10 min aunque el repo no cambiara = ~1.000 filas/día + CPU de upserts), D1 en 94,6 MB, y más tráfico de crons desde la migración a OPS (s193-s201). Los picos de error coinciden con las ventanas de ráfaga nocturna (00:45-01:30 Madrid) y la mañana laboral.
Qué se hizo (s202, noche del 06→07-07)
| Acción | Dónde | Efecto |
|---|---|---|
Retry 3× con backoff 20s/40s en mcp_call | scripts/ops/biblioteca-crons/_common.sh (ws cf422ddf, desplegado en OPS) | un kill puntual ya no tumba un cron |
wiki-lint.sh por pasos independientes | ídem | un 503 en contradicciones ya no se salta el reclaim (lo que pasó el 06-07) |
| Guard por SHA en el reindex AST de Pro | scripts/cron-bib-reindex.sh (Pro a047f260) | no-op si HEAD no cambió y <12h → −99% del churn; refresh 12h para el watchdog cloud; --force |
| Purga one-time D1 | vía API CF | bib_index_runs 47.129→23.552 · bib_wiki_log 4.233→2.905 |
| Retención recurrente | .github/workflows/d1-cleanup.yml | runs 30d→14d + paso nuevo bib_wiki_log 60d |
| Scripts de OPS a git | scripts/ops/biblioteca-crons/ | deuda cerrada: tenían copia única en el servidor |
| Menores | OPS | asunto del heartbeat “STAGE”→“OPS” (y el 07-07, IP vieja de STAGE→crearack-ops.netbird.cloud) · borrados .bak huérfanos |
Verificación de la dieta (madrugada del 07-07, aún en Free): todos los crons de la noche en VERDE — lint completo con reclaim (back=6), enrich applied 5/5, escriba de drift armado OK, drift-check OK. Solo 1 kill en todo el día (03:00Z), absorbido por el retry.
Resolución (07-07-2026)
Workers Paid contratado por Edu la mañana del 07-07 (5 $/mes, verificado state: Paid vía API). CPU por petición: 10 ms → 30 s. A partir de aquí, un 1102/exceededResources ya no puede ser cuota del plan — si reaparece, es un problema real de código (leak, bucle, payload desmedido) y hay que investigarlo como tal.
Cómo reconocerlo si vuelve
- Síntoma:
[ERROR] ... FAILED (http=503)+error code: 1102en logs de OPS; en CF GraphQL,pagesFunctionsInvocationsAdaptiveGroupscon statusexceededResources. - Post-Paid: con 30 s de CPU, un exceededResources señala un bug real, no cuota. Mirar CPU p50/p99 de la petición muerta.
- NO confundir con: el techo de subrequests del lint pairwise (error distinto, solo contradicciones), ni con el split-brain de refs s192 (ahí desaparecen refs de GitHub).
Daño colateral del incidente (anexo, 07-07 mañana)
El build del sitio (cf-pages-deploy) estuvo roto de 21:53Z a 05:51Z por causa INDEPENDIENTE: las 2 páginas wiki creadas en s202 llevaban sources como strings (footgun wiki_create_page_schema, 3ª reincidencia). Fix 520afcd4 + resuelto de raíz server-side el mismo día (ba181a54: el handler normaliza sources/related antes de commitear, +13 tests).
Véase también
- [[entity—biblioteca—endpoint—crons]]
- [[concept—infra—ops-server]]