Skip to content

fix(host-cloudflare): una caída breve de D1 ya no hace fallar search ni invoke - #41

Merged
fforres merged 1 commit into
skywardfrom
fforres/d1-retry-outage-budget
Oct 30, 2026
Merged

fforres merged 1 commit into
skywardfrom
fforres/d1-retry-outage-budget

Conversation

@fforres

@fforres fforres commented Oct 30, 2026

Copy link
Copy Markdown

Qué cambia

Cuando D1 falla por unos 15 segundos, search e invoke de Executor ya no devuelven Internal tool error [id]: las lecturas se reintentan hasta 20 segundos (antes, cinco intentos en menos de 4 segundos).

Causa (confirmada con logs de producción)

El 2026-10-28 entre 14:50:10Z y 14:50:26Z, D1 respondió D1_ERROR: internal error; reference = ... a casi todas las consultas del worker executor-cloudflare: 86 spans d1_all/d1_run con error y ninguna consulta exitosa entre 14:50:09 y 14:50:27. Eso explica las tres fallas de una misma ejecución de Skywardin (search 14,5 s, invoke 19,4 s, search 3,4 s). search no llama a ningún upstream: lee el catálogo desde D1.

El reintento de D1 ya existía y se activó (avisos D1 transient failure, retrying desde 14:50:13). Pero la mayoría de los intentos fallidos vuelven en milisegundos, así que los cinco intentos con espera de 200 ms a 1,6 s se agotaban en menos de 4 segundos, mucho antes de que D1 se recuperara. Las tres fallas sí dejaron su línea [executor:mcp] execute defect correlation_id=... (ef70a6b1, ce1cc2d7, de660f2d); la lectura anterior de que solo una la dejaba era un error de la consulta de logs.

No es un timeout upstream: la hipótesis de 19 s igual a timeout queda descartada.

Cómo se probó

  • Prueba nueva: una lectura que falla durante 16 s virtuales y luego responde debe tener éxito. Falló antes del cambio (agotaba los 5 intentos) y pasa ahora.
  • La prueba de "se rinde" ahora comprueba que se rinde al agotar el presupuesto de 20 s, con más de 5 y menos de 25 intentos.
  • vitest run src/db en apps/host-cloudflare: 58 pruebas pasan.

Cómo comprobarlo después del despliegue

Servicio executor-cloudflare, ventana de 7 días, sin cambios en la métrica base:

  • needle: "execute defect": línea base 3 (todas el 2026-10-28 14:50Z). Debe seguir en 0 ante un cuarto de hora de errores de D1.
  • spanName ~ ^d1_ con level = error: línea base 25 a 138 por día (se reintentan y se recuperan solos). Esperable que no baje; lo importante es que no aparezcan defectos.
  • needle: "D1 transient failure": si aparece d1.attempt mayor que 5 y luego la consulta tiene éxito, el presupuesto nuevo está actuando.

@fforres

fforres commented Oct 30, 2026

Copy link
Copy Markdown
Author

El CI de Blacksmith no corre en este repositorio (todas sus ejecuciones quedan en cola o canceladas), así que se verificó en local sobre el head 9c14439 (al día con skyward):

  • bunx oxfmt --check sobre los archivos tocados: OK
  • bunx oxlint -c .oxlintrc.jsonc --deny-warnings apps/host-cloudflare/src/db: 0 advertencias, 0 errores
  • bunx vitest run src/db en apps/host-cloudflare: 3 archivos, 58 pruebas, todas OK
  • bun run typecheck en apps/host-cloudflare (tsgo): OK

@fforres
fforres merged commit 7badab8 into skyward Oct 30, 2026
4 of 40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant