Saltar al contenido
crawlforgeEnglish
Se rompió12 de octubre de 20267 min de lecturaRead in English

88 páginas que no estaban rotas

La 0.16.0 añade una regla para los enlaces externos tras un muro y mide bien las rayas. La 0.17.0 deja de tomar un límite de peticiones por una página rota.

La bitácora de campo de la fase 1 lleva vacía desde el 3 de agosto. Es lo último que falta para cerrar la fase, y solo se rellena usando la herramienta con sitios de verdad. Así que hoy le dediqué una sesión: volver a rastrear colorvivo.com sobre una copia del fichero del 3 de agosto, que da un diff real de dos meses, hacer lo mismo con especialmundial.com y apuntar lo que fuera molestando.

Molestó en los primeros diez minutos. Entre medias salieron dos versiones, y aquí van las dos en el orden en que pasaron.

La 0.16.0: los enlaces de los que nadie hablaba

HTTP-404-EXTERNAL avisa de los enlaces salientes que ya no existen, y para eso solo se fía de dos códigos, 404 y 410, más un dominio que ya no resuelve. Los 401, 403 y 429 se quedan fuera a propósito. La comprobación es una petición HEAD con user-agent de bot, muchas veces desde una IP de centro de datos, y eso es justo lo que frenan Cloudflare y compañía. En agosto lo medimos: medium.com, wsj.com y ft.com responden a la comprobación con 401 o 403, y las tres abren bien en un navegador.

Dejarlos fuera de la regla de enlace roto era lo correcto. Que desaparecieran del todo, no. Un enlace tras un muro tampoco demuestra que funcione, y hasta ahora nada en el informe lo distinguía de un enlace comprobado y sano.

HTTP-EXTERNAL-UNVERIFIABLE tapa ese hueco. Es low, tiene su propio ID y dice lo que pasó: el otro sitio rechazó la comprobación, así que abre el enlace para confirmarlo. Meterlo en el ID de enlace roto habría cambiado lo que significa ese ID, y un diff histórico depende de que los IDs de regla no cambien nunca de significado. En el rastreo de colorvivo de hoy salen 8 enlaces que responden 403, entre ellos gartner.com y ostraining.com. Los 7 que respondieron 404 siguen yendo a su regla. El catálogo pasa a 64 reglas.

Hay cinco tests nuevos. Cuatro van contra una base en memoria y uno de extremo a extremo contra el servidor local de pruebas, donde una ruta externa responde 403 y otra 404, y cada código tiene que caer en su regla y en ninguna más. Rompí cuatro cosas a propósito para verlos fallar: una consulta que no encuentra nada, el filtro que solo cuenta enlaces <a>, el que solo cuenta URLs externas y una lista de códigos ampliada con 407 y 451. Cada una puso su test en rojo.

El segundo arreglo de la 0.16.0 vino de otro lado. Mientras un agente preparaba cambios de copy para esta web, se dio cuenta de que la tabla de anchos con la que las reglas de título y descripción estiman los píxeles se equivocaba con las rayas. En Arial la raya — ocupa un em entero y la tabla le daba 556 milésimas. La semirraya – mide 556 y la tabla le daba 333, lo mismo que un guion. Un título Título — Sitio salía unos 9 píxeles corto. Es el mismo separador que usa esta web para su sufijo « — CrawlForge», así que los títulos de nuestras propias páginas se medían con manga ancha. Un comentario del mismo fichero decía que el core tenía una copia de esa tabla. No la tiene, llama a esta, y ahora el comentario lo dice.

La 0.17.0: un límite de peticiones no es una página rota

Vamos con la sesión de campo. A los diez minutos de lanzar el rastreo de colorvivo, el fichero tenía 801 páginas hechas y 92 de ellas con estado 429. Le hice la misma pregunta que haría el informe, qué enlaces internos apuntan a un 4xx, y salieron 88 páginas. Severidad crítica, «enlace interno roto». Un curl normal desde el mismo Mac también recibía un 429. Y ninguna de esas páginas estaba rota: en el rastreo de agosto, las que aparecían respondían 200 o redirigían, todas.

Cloudflare estaba frenando al rastreador. En agosto el mismo sitio, rastreado con la misma concurrencia, respondió 200 en sus 2.857 páginas y no mandó ni un 429. Algo ha cambiado desde entonces en Cloudflare, y no pasa nada, le puede pasar a cualquier sitio. Lo que sí está mal es que nos creyéramos el 429 como estado de la página.

El motor ya tenía dos defensas. Reintenta un 429 tres veces, esperando 1, 2 y 4 segundos, y tras tres señales de sobrecarga seguidas baja a la mitad la concurrencia con ese host. A veces no basta. Cuando una página seguía recibiendo un 429 después del tercer reintento, ese estado se escribía en el fichero, y a partir de ahí todas las reglas que leen un 4xx interno como roto se lo creían. Conté más de diez consultas que lo hacen: enlaces rotos, recursos rotos, canonicals y hreflang que apuntan a errores, las vistas del XLSX. Parchearlas una a una habría sido dejarse alguna.

El arreglo va antes, en el motor. Una página que sigue respondiendo 429 tras sus reintentos no se procesa. Su fila se queda pending, como se escribió al descubrirla, así que ninguna regla puede confundirla con una página rota. El rastreo se marca incompleto con un motivo nuevo, rate_limited, y las reglas que necesitan el sitio entero callan, porque los enlaces de esas páginas no se leyeron nunca. El resumen dice cuántas quedaron pendientes y qué lanzar más tarde:

crawlforge resume crawl-colorvivo-com.sqlite

Hasta ahora un rastreo terminado no se podía reanudar, y eso sigue igual salvo en este caso. resume acepta un fichero terminado si lo frenó el sitio, pide solo las pendientes y, si no queda ninguna, el fichero deja de decirse incompleto. Un 429 que se arregla dentro de los reintentos se procesa como siempre.

Para probarlo, el servidor local necesitaba algo nuevo: una ruta que falle las primeras N veces y luego responda. El test hace que la página responda 429 cuatro veces (la petición original y los tres reintentos), comprueba que queda pendiente y sin hallazgo de enlace roto, reanuda, y comprueba que la quinta petición vuelve con un 200 y que el fichero ya no está marcado como incompleto. Sin el cambio del motor el test falla en el motivo, y sin la excepción de resume falla al reanudar. Los mensajes del resumen y del informe tienen sus propios tests, y cada uno falla sin su rama.

En qué me equivoqué hoy

Para ver los tests en rojo rompo el código y luego lo devuelvo a su sitio. En una de esas lo devolví con git checkout, y eso también deshizo un cambio mío de la misma sesión que aún no estaba en un commit, la lista de códigos de la regla nueva. La compilación siguiente falló y me di cuenta en el momento. Desde entonces devuelvo los ficheros desde una copia, nunca desde git.

La otra salió al público. La entrada anterior, la del panel de cartera, decía que ninguna regla cuelga un hallazgo de una URL externa, y HTTP-404-EXTERNAL lo hace. Lo había comprobado con ficheros de agosto, de antes de que se sondearan los enlaces externos. Corregí la entrada y dejé una nota al final con lo que cambió. El código estaba bien; la frase no.

Lo que queda abierto

El motor todavía no hace caso de Retry-After en las páginas del propio sitio, solo en las sondas externas. Con eso podría esperar lo que pida el servidor en vez de tres esperas fijas, y algunas de estas páginas no necesitarían un resume. Es la siguiente pieza, y como toca el bucle de rastreo necesita su propia medición.

El cambio de la 0.17.0 sí toca engine.rs, así que lo medí contra la 0.16.0 alternando las dos durante doce rondas. El Mac estaba muy cargado, con la carga media llegando a 27, y los números bailan mucho. Las medianas son 50.845 y 52.846 elementos por segundo, un empate. El cambio es una comparación de un entero por página, así que habría sido raro ver otra cosa.

El rastreo de colorvivo sigue en marcha con el binario viejo. Mientras escribo esto tiene 288 páginas atascadas en 429, 273 de ellas enlazadas desde un <a>, que son todas las que la versión vieja habría dado por enlace interno roto. De las que también estaban en el rastreo de agosto, 213 respondían entonces 200 y 62 redirigían. Es el mejor registro del fallo que podía pedir, y la bitácora vuelve a tener entradas.

Se construye en público

Cada dos semanas: mediciones, fallos y ejemplos de uso. Nada más.

← Volver a la bitácora