Blogg

En misslyckad publicering raderar aldrig en fungerande backend

Den 25 september raderade en misslyckad omdeploy en apps backend som varit live och fungerat i ungefär två och en halv timme. Koden som ångrar en misslyckad publicering tog bort varje serverapp som publiceringen hade berört, även de som redan levererade innan den startade. Nu raderas bara appar som en publicering skapat, och en app som redan fanns sätts tillbaka exakt på den version den kört innan. Två uppföljande rättelser samma dag såg till att ångringen också körs när hostingplattformens egna deployverktyg misslyckas, och att en frisk app inte underkänns bara för att den sov.

Så publiceras en backend

När din Mythex-app har en backend – ett API eller en server, inte bara statiska filer – byggs den från en Dockerfile (ett recept för att paketera appen i en image) och rullas ut som en image på maskiner hos vår hostingplattform. Sedan väntar en hälsokontroll tills den nya versionen faktiskt har startat och håller sig igång, innan publiceringen markeras som live.

Om något går fel på vägen körs en rollback för att ångra det. Att få rollbacken rätt är viktigare än nästan allt annat i publiceringen, eftersom den körs precis när något redan är på väg att gå fel.

Problem 1: rollbacken raderade det den skulle ha återställt

Rollbacken höll en lista över de serverappar en publicering hade deployat till, och vid misslyckande förstörde den alla. Det är rätt vid en första publicering: appen skapades just nu, inget är beroende av den, och att radera den lämnar allt som det var.

Det är exakt fel vid en ompublicering. Appen fanns redan och betjänade riktiga besökare. Den 25 september raderades ett API som varit live i ungefär två och en halv timme av en misslyckad ompublicering.

Det fanns ett andra felläge gömt i samma kod. Där raderingen inte gick igenom låg den trasiga nya imagen kvar på maskinerna – medan vi berättade för ägaren att deras nuvarande sajt fortfarande var live. När hälsokontrollen kan misslyckas har den nya imagen redan rullats ut på varje maskin. Att inte göra något är inte samma sak som att ångra.

Rättelsen: radera bara det du skapat, återställ resten

Varje publicering registrerar nu, för varje serverapp den berör:

  • om just den här publiceringen skapade appen, och
  • om inte, vilken image den kört precis innan.

Vid misslyckande får varje app en av tre behandlingar:

  1. Skapad av den här publiceringen: radera den, som tidigare.
  2. Fanns redan, tidigare image känd: deploya om den tidigare imagen med samma konfiguration. Ingen build – bara imagen flyttas tillbaka.
  3. Fanns redan, tidigare image okänd: lämna den ifred. En befintlig app raderas aldrig, även när vi inte kan återställa den.

Reglerna är en liten ren funktion med egna tester, så beslutet inte kan glida tillbaka till "radera allt" utan att ett test fallerar.

Problem 2: deployverktyget kunde misslyckas innan vi skrivit ner hur vi ångrar

Strax efter rättelsen hittade vi ett hål i den. Hostingplattformens deployverktyg kör egna rökkontroller: om de nya maskinerna kraschar avslutar det med ett fel. Men det sker efter att den nya imagen redan ligger på maskinerna.

Vår kod registrerade en app för rollback först när verktyget returnerat utan fel. När verktyget självt underkände deployen fanns appen inte på rollbacklistan än, så ingenting återställdes. I vår staging-miljö fortsatte en trasig image att serva efter en misslyckad omdeploy.

Rättelsen: registrera ångringen före start

Appen registreras nu för rollback – med uppgift om den skapades och vilken image den körde – så snart den förberetts och innan något rullas ut på den. Vad som än misslyckas efteråt vet rollbacken vad den ska sätta tillbaka. Vi verifierade lokalt: en trasig omdeploy underkändes av deployverktygets egna rökkontroller, och den tidigare versionen fortsatte svara.

Problem 3: en sovande app underkändes som "startade aldrig"

Publicerade appar på Mythex somnar när de är inaktiva för att spara dina krediter. En ompublicering lämnar en sovande maskin stoppad, så hälsokontrollen måste väcka den. Den bad plattformen starta maskinen en gång och ignorerade svaret.

Den 25 september gick den enda startbegäran ingenstans. Ett friskt API låg stoppat under hela fem minuters hälsokontroll och underkändes med "1 machine never started (last state: stopped)".

Plattformen vägrar ibland en start. Under reproduktionen gav den ett "lease currently held"-konflikt utan att vi provocerade fram det, och den vägrar starter medan en maskin uppdateras.

Rättelsen: fortsätt be, och knacka på dörren

Hälsokontrollen gör nu följande:

  • frågar om att starta en stoppad maskin igen var 20:e sekund medan den väntar,
  • loggar vad plattformen svarade när den vägrar, och
  • skickar en vanlig förfrågan till appen, precis som en besökare skulle göra – plattformens proxy väcker en sovande maskin när en förfrågan kommer in.

Vi reproducerade det på den riktiga plattformen med en tillfällig app vars första start vägrades. Före rättelsen misslyckades publiceringen efter 91 sekunder. Efter den publicerades den på 20 sekunder. En app som verkligen kraschar vid start underkänns fortfarande, som den ska.

Det vi tog med oss

  • Rollback måste skilja mellan nytt och befintligt. "Ångra" för något du skapat är radering. "Ångra" för något som redan fanns är återställning. Att behandla dem lika är så en säkerhetsmekanism raderar en fungerande app.
  • Skriv ner hur du ångrar innan du agerar. Om ångringen bara registreras efter att ett steg lyckats, lämnar ett steg som misslyckas halvvägs ingenting att ångra med.
  • Svälj aldrig svaret på en förfrågan du är beroende av. Ett ignorerat "nej" förvandlade en frisk app till en misslyckad publicering.

En närliggande rättelse från samma dag: att fånga appar som kraschar direkt efter publicering. För vad som händer när en publicering misslyckas på din sida, se felsökning vid publicering i dokumentationen.

Mythex · Pricing · Bygg vad som helst med AI · Mallar för webbplatser och appar · Mythex jämfört · Ordlista för apputveckling med AI · Gratis verktyg för apputveckling med 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 Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 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 Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)