Detectar apps que se caen justo después de publicar
El 25 de septiembre, tres publicaciones se marcaron como correctas aunque la API de la app se caía segundos después de cada arranque. Como “tuvieron éxito”, no se ejecutó ninguna vuelta atrás; una comprobación en segundo plano las dio por fallidas unos minutos después, y todo el sitio devolvió un 404. El health check contaba las caídas en la lista de eventos de la plataforma de hosting, que solo guarda los últimos cinco eventos por máquina, así que un bucle de caídas la mantiene llena y el recuento nunca crece. Ahora compara la hora de la caída más reciente, y una publicación con bucle de caídas falla y restaura la versión anterior.
Lo que espera una publicación
Cuando publicas una app con backend en Mythex, la nueva versión se despliega en máquinas de nuestra plataforma de hosting, y un health check decide si la publicación quedó activa o falló. Si falló, una vuelta atrás restaura la versión anterior.
Lo difícil es que “arrancado” no es lo mismo que “sirviendo”. La plataforma informa de que una máquina está arrancada en cuanto está levantada. Una app que se cae un segundo después de arrancar se reinicia de inmediato, y un momento después vuelve a figurar como arrancada. Así que el health check había ido acumulando varias capas con el tiempo:
- Mirar dos veces. Después de que una máquina figure como arrancada, espera un momento y vuelve a mirar. Una caída al arrancar suele fallar en la segunda mirada.
- Vigilar los bucles de caídas. Si la plataforma informa de que una máquina se cayó repetidamente y dejó de reiniciarla, falla.
- Contar las caídas desde que empezó la publicación. Dos miradas de “arrancado” pueden cruzar un reinicio. Así que si hubo alguna caída desde que empezó esta publicación, se mira una tercera vez; si hay más caídas que en la mirada anterior, la app no se mantiene en pie.
La tercera comprobación es la que falló aquí.
Por qué el recuento se quedaba plano
La información de caídas viene de la lista de eventos de cada máquina: inicios, salidas, reinicios. La plataforma guarda solo los últimos cinco eventos por máquina.
Imagina una app que se cae a los 2,5 segundos de cada arranque, como una de ellas. Cada ciclo añade una caída y un inicio. Tras un par de ciclos, la lista está llena. A partir de ahí, cada evento nuevo empuja a uno antiguo fuera. La lista avanza, pero siempre tiene la misma mezcla: un par de caídas, un par de inicios.
Así que “cuántas caídas desde que empezó la publicación” devolvía el mismo número en cada mirada. La segunda mirada veía, digamos, dos caídas. La tercera también veía dos —caídas distintas, pero el mismo número—. La comprobación concluía que las caídas habían cesado, y daba la publicación por buena.
Eso pasó tres veces el 25 de septiembre, en dos apps. Cada vez:
- la publicación se marcó como activa,
- no se ejecutó ninguna vuelta atrás, porque nada había fallado,
- nuestro reconciliador, un trabajo en segundo plano que revisa los despliegues a posteriori, falló el despliegue unos minutos después,
- y todo el sitio devolvió 404.
Una publicación que falla a tiempo se puede recuperar: la vuelta atrás restaura la versión anterior. Una publicación que falla unos minutos tarde, después de haberse declarado un éxito, ya se ha saltado su vuelta atrás.
Cómo lo encontramos
Lo reproducimos en local: tomamos una API que funcionaba, la dejamos dormirse y la republicamos con un cambio que se caía al arrancar. El health check la marcó como activa.
Eso coincidió con producción: en cada una de las tres publicaciones, la app moría segundos después de cada arranque, pero el recuento de caídas que comparaba la comprobación nunca subía entre miradas.
La solución: comparar la caída más reciente, no el recuento
En lugar de contar caídas, la comprobación ahora mira la hora de la caída más reciente desde que empezó la publicación.
Si la segunda mirada muestra alguna caída desde que empezó la publicación, la comprobación espera y mira una tercera vez. Si la caída más reciente en la tercera mirada es posterior a la más reciente de la segunda, la máquina se cayó de nuevo en el intervalo. No se mantiene en pie, y la publicación falla con un mensaje que indica que la máquina se cayó repetidamente desde la publicación y sigue reiniciándose.
Esto funciona sin importar lo corta que sea la lista de eventos. Una ventana deslizante de cinco eventos puede ocultar cuántas caídas hubo, pero no puede ocultar que acaba de producirse una nueva: el evento más reciente es siempre el que se conserva.
Con este cambio, la reproducción local se comporta correctamente: la publicación falla y se restaura la imagen anterior. También hay una prueba que simula el comportamiento de la plataforma —cada mirada añade una caída y un inicio, y recorta la lista a cinco— y comprueba que el veredicto es un fallo, no un éxito.
Lo que aprendimos
- Conoce la forma de los datos que cuentas. Un recuento sobre una lista limitada deja de significar algo cuando la lista se llena. El límite no estaba oculto; simplemente no habíamos diseñado la comprobación pensando en él.
- Prefiere “¿pasó algo nuevo?” a “¿cuántas cosas pasaron?”. La marca de tiempo más reciente sobrevive al truncado. Un total no.
- Un fallo tardío es peor que uno temprano. La misma compilación rota es inofensiva si la publicación falla y vuelve atrás, y tumba un sitio si primero se declara un éxito.
- Reproduce en las condiciones reales. El error necesitaba una máquina que ya se hubiera caído suficientes veces como para llenar su lista de eventos. Una sola caída rápida en una prueba no lo habría mostrado.
Esta corrección se complementa con otra del mismo día, que hizo que la vuelta atrás restaure la versión anterior en lugar de borrarla: una republicación fallida nunca borra un backend que funciona. Si tu propia app no se publica porque se cae al arrancar, la documentación de solución de problemas de publicación y nuestra guía sobre cómo depurar una app creada con IA son buenos puntos de partida.