Individuare le app che vanno in crash subito dopo la pubblicazione
Il 25 settembre tre pubblicazioni sono state segnate come riuscite anche se l'API dell'app andava in crash pochi secondi dopo ogni avvio. Poiché risultavano "riuscite", il rollback non è partito; un controllo in background le ha fatte fallire qualche minuto dopo, e l'intero sito è andato in 404. L'health check contava i crash nell'elenco di eventi della piattaforma di hosting, che contiene solo gli ultimi cinque eventi per macchina, quindi un ciclo di crash riempie la lista e il conteggio non cresce mai. Ora confronta invece l'ora del crash più recente, e una pubblicazione in crash ripetuto fallisce e ripristina la versione precedente.
Cosa aspetta una pubblicazione
Quando pubblichi un'app con un backend su Mythex, la nuova versione viene distribuita sulle macchine della nostra piattaforma di hosting, e un health check decide se la pubblicazione è andata live o è fallita. Se è fallita, un rollback rimette la versione precedente.
La parte difficile è che "avviato" non è lo stesso che "in servizio". La piattaforma segnala una macchina come avviata appena è accesa. Un'app che va in crash un secondo dopo l'avvio viene riavviata subito, e un attimo dopo risulta di nuovo avviata. Quindi l'health check nel tempo si era stratificato su più livelli:
- Guarda due volte. Dopo che una macchina risulta avviata, aspetta un momento e guarda di nuovo. Un crash all'avvio spesso fa fallire il secondo controllo.
- Controlla i cicli di crash. Se la piattaforma segnala che una macchina è andata in crash più volte e ha smesso di riavviarla, fallisci.
- Conta i crash dall'inizio della pubblicazione. Due controlli "avviato" possono cadere a cavallo di un riavvio. Quindi, se c'è stato un crash da quando la pubblicazione è iniziata, guarda una terza volta; se ci sono più crash rispetto al controllo precedente, l'app non resta in piedi.
Il terzo controllo è quello che qui ha fallito.
Perché il conteggio restava fermo
Le informazioni sui crash vengono dall'elenco di eventi di ogni macchina: avvii, uscite, riavvii. La piattaforma conserva solo gli ultimi cinque eventi per macchina.
Immagina un'app che va in crash dopo 2,5 secondi a ogni avvio, come una di queste. Ogni ciclo aggiunge un crash e un avvio. Dopo un paio di cicli la lista è piena. Da quel momento, ogni nuovo evento spinge fuori uno vecchio. La lista scorre in avanti, ma contiene sempre più o meno lo stesso mix: un paio di crash, un paio di avvii.
Quindi "quanti crash dall'inizio della pubblicazione" restituiva lo stesso numero a ogni controllo. Il secondo controllo vedeva, diciamo, due crash. Il terzo ne vedeva ancora due, crash diversi ma lo stesso numero. Il controllo concludeva che i crash si erano fermati, e approvava la pubblicazione.
È successo tre volte il 25 settembre, su due app. Ogni volta:
- la pubblicazione è stata segnata come live,
- nessun rollback è partito, perché nulla era fallito,
- il nostro reconciler, un job in background che controlla i deployment a posteriori, ha fatto fallire il deployment qualche minuto dopo,
- e l'intero sito ha restituito 404.
Una pubblicazione che fallisce in tempo è recuperabile: il rollback ripristina la versione precedente. Una pubblicazione che fallisce qualche minuto in ritardo, dopo essere stata dichiarata un successo, ha già saltato il suo rollback.
Come l'abbiamo scoperto
Lo abbiamo riprodotto in locale: abbiamo preso un'API funzionante, l'abbiamo lasciata andare in standby, poi l'abbiamo ripubblicata con una modifica che andava in crash all'avvio. L'health check l'ha segnata come live.
Questo corrispondeva alla produzione: in ciascuna delle tre pubblicazioni, l'app moriva pochi secondi dopo ogni avvio, eppure il conteggio dei crash confrontato dal controllo non aumentava mai tra un controllo e l'altro.
La correzione: confronta il crash più recente, non il conteggio
Invece di contare i crash, il controllo ora guarda l'ora del crash più recente dall'inizio della pubblicazione.
Se il secondo controllo mostra un qualsiasi crash dall'inizio della pubblicazione, il controllo attende e guarda una terza volta. Se il crash più recente nel terzo controllo è più tardi di quello più recente nel secondo, la macchina è andata in crash di nuovo nel frattempo. Non sta restando in piedi, e la pubblicazione fallisce con un messaggio che indica che la macchina è andata in crash più volte dalla pubblicazione e sta ancora riavviandosi.
Funziona indipendentemente dalla lunghezza dell'elenco di eventi. Una finestra scorrevole di cinque eventi può nascondere quanti crash ci sono stati, ma non può nascondere che ne è appena accaduto uno nuovo: l'evento più recente è sempre quello che resta.
Con questa modifica, la riproduzione locale si comporta correttamente: la pubblicazione fallisce e viene ripristinata l'immagine precedente. C'è anche un test che simula il comportamento della piattaforma, dove ogni controllo aggiunge un crash e un avvio e riduce la lista a cinque voci, e verifica che il verdetto sia un fallimento, non un successo.
Cosa ne abbiamo ricavato
- Conosci la forma dei dati che stai contando. Un conteggio su un elenco limitato smette di avere senso una volta che l'elenco è pieno. Il limite non era nascosto; semplicemente non avevamo progettato il controllo tenendone conto.
- Preferisci "è successo qualcosa di nuovo?" a "quante cose sono successe?". Il timestamp più recente sopravvive al troncamento. Un totale no.
- Un fallimento in ritardo è peggio di uno in anticipo. La stessa build difettosa è innocua se la pubblicazione fallisce e torna indietro; se invece viene prima dichiarata un successo, abbatte un sito.
- Riproduci nelle condizioni reali. Il bug richiedeva una macchina che avesse già in crash abbastanza volte da riempire la lista di eventi. Un singolo crash rapido in un test non l'avrebbe mostrato.
Questa correzione si accompagna a un'altra della stessa giornata, che ha garantito che il rollback rimettesse la vecchia versione invece di cancellarla: un republish fallito non cancella mai un backend funzionante. Se la tua app non viene pubblicata perché va in crash all'avvio, la documentazione risoluzione dei problemi di pubblicazione e la nostra guida a come fare debug di un'app costruita con l'AI sono un buon punto di partenza.