Blog

Un republish fallito non cancella mai un backend funzionante

Il 25 settembre un republish fallito ha cancellato il backend di un'app che era stato live e funzionante per circa due ore e mezza. Il codice che annulla una pubblicazione fallita rimuoveva ogni app server toccata dalla pubblicazione, comprese quelle che già erogavano traffico prima che iniziasse. Ora vengono eliminate solo le app create da una pubblicazione; un'app già esistente viene riportata esattamente alla versione che eseguiva prima. Due correzioni successive, sempre quel giorno, hanno garantito che l'annullamento scatti anche quando lo strumento di deploy della piattaforma di hosting fallisce, e che un'app sana non venga segnata come fallita solo perché era in standby.

Come viene pubblicato un backend

Quando la tua app Mythex ha un backend, cioè un'API o un server anziché solo file statici, la pubblicazione lo costruisce da un Dockerfile (una ricetta per impacchettare l'app in un'immagine) e distribuisce quell'immagine sulle macchine della nostra piattaforma di hosting. Poi un health check attende che la nuova versione si avvii davvero e resti in funzione, prima che la pubblicazione venga segnata come live.

Se qualcosa fallisce lungo il percorso, parte un rollback per annullare il tutto. Farlo bene conta più di quasi ogni altra cosa nella pubblicazione, perché scatta proprio quando qualcosa sta già andando storto.

Problema 1: il rollback cancellava ciò che avrebbe dovuto ripristinare

Il rollback conservava una lista delle app server su cui la pubblicazione aveva fatto deploy e, in caso di errore, le distruggeva tutte. Per una prima pubblicazione è corretto: l'app è stata creata un attimo prima, nulla dipende da lei, e cancellarla lascia le cose come erano.

Per un republish è esattamente sbagliato. L'app esisteva già e serviva visitatori reali. Il 25 settembre, l'API di un'app che era live da circa due ore e mezza è stata cancellata da un republish fallito.

Nello stesso codice c'era una seconda modalità di guasto. Quando la cancellazione non andava a buon fine, la nuova immagine difettosa restava sulle macchine, mentre al proprietario dicevamo che il suo sito attuale era ancora online. Quando l'health check può fallire, la nuova immagine è già stata distribuita su ogni macchina. Non fare nulla non è la stessa cosa che annullare.

La correzione: elimina solo ciò che hai creato, ripristina il resto

Ogni pubblicazione ora registra, per ogni app server che tocca:

  • se questa pubblicazione l'ha creata, e
  • se non l'ha creata, quale immagine eseguiva appena prima.

In caso di errore, ogni app riceve uno di tre trattamenti:

  1. Creata da questa pubblicazione: eliminata, come prima.
  2. Già esistente, immagine precedente nota: si ridistribuisce l'immagine precedente con la stessa configurazione. Nessuna build: si riporta indietro solo l'immagine.
  3. Già esistente, immagine precedente sconosciuta: non si tocca. Un'app esistente non viene mai eliminata, nemmeno quando non possiamo ripristinarla.

Queste regole sono una piccola funzione pura con i propri test, così la decisione non può tornare a "distruggi tutto" senza che un test fallisca.

Problema 2: lo strumento di deploy poteva fallire prima che avessimo scritto come annullare

Subito dopo quella correzione abbiamo trovato una lacuna. Lo strumento di deploy della piattaforma esegue i propri controlli di smoke: se le nuove macchine si bloccano, esce con un errore. Ma lo fa dopo che la nuova immagine è già sulle macchine.

Il nostro codice registrava un'app per il rollback solo quando lo strumento restituiva un successo. Quando lo strumento stesso faceva fallire il deploy, l'app non era ancora nella lista del rollback, quindi non veniva ripristinato nulla. Nel nostro ambiente di staging, un republish rotto ha lasciato in servizio l'immagine rotta.

La correzione: registra l'annullamento prima di partire

Ora l'app viene registrata per il rollback, con l'indicazione se è stata creata e quale immagine eseguiva, non appena è preparata e prima che vi venga distribuito qualcosa. Qualunque cosa fallisca dopo, il rollback sa cosa rimettere. L'abbiamo verificato in locale: un republish rotto è fallito nei controlli di smoke dello strumento di deploy, e la versione precedente ha continuato a rispondere.

Problema 3: un'app in standby risultava "mai avviata"

Le app pubblicate su Mythex vanno in standby quando sono inattive, per risparmiare crediti. Un republish lascia una macchina ferma in standby, quindi l'health check deve svegliarla. Chiedeva alla piattaforma di avviare la macchina una sola volta, e ignorava la risposta.

Il 25 settembre, quella singola richiesta di avvio non ha prodotto nulla. Un'API sana è rimasta ferma per tutti i cinque minuti dell'health check ed è stata segnata come fallita con "1 macchina mai avviata (ultimo stato: stopped)".

La piattaforma a volte rifiuta un avvio. Mentre riproducevamo il problema, ha restituito un conflitto "lease currently held" senza che lo provocassimo, e rifiuta gli avvii mentre una macchina è in aggiornamento.

La correzione: continua a chiedere e bussa alla porta

L'health check ora:

  • chiede di nuovo di avviare una macchina ferma ogni 20 secondi mentre attende,
  • registra cosa ha risposto la piattaforma quando rifiuta, e
  • invia una normale richiesta all'app, come farebbe un visitatore: il proxy della piattaforma sveglia una macchina in standby quando arriva una richiesta.

Abbiamo riprodotto il problema sulla piattaforma reale con un'app di prova il cui primo avvio veniva rifiutato. Prima della correzione la pubblicazione falliva dopo 91 secondi; dopo, si è pubblicata in 20 secondi. Un'app che va davvero in crash all'avvio fallisce comunque, come deve.

Cosa ne abbiamo ricavato

  • Il rollback deve distinguere tra nuovo ed esistente. "Annulla" per qualcosa che hai creato significa eliminare. "Annulla" per qualcosa che c'era già significa ripristinare. Trattarli allo stesso modo è il modo in cui un meccanismo di sicurezza finisce per cancellare un'app funzionante.
  • Scrivi come annullare prima di agire. Se l'annullamento viene registrato solo dopo che un passo riesce, un passo che fallisce a metà non lascia nulla con cui tornare indietro.
  • Non ignorare mai la risposta a una richiesta da cui dipendi. Un "no" ignorato ha trasformato un'app sana in una pubblicazione fallita.

Una correzione collegata, della stessa giornata: catturare le app che vanno in crash subito dopo la pubblicazione. Per cosa succede quando una pubblicazione fallisce dal tuo lato, vedi risoluzione dei problemi di pubblicazione nella documentazione.

Mythex · Pricing · Crea qualsiasi cosa con l'AI · Template per siti web e app · Mythex a confronto · Glossario per creare app con l'AI · Strumenti gratuiti per creare app con l'AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)