Blogue

Uma Republicação Falhada Nunca Apaga um Backend que Funciona

No dia 25 de setembro, uma republicação falhada apagou o backend de uma app que esteve ativo e a funcionar durante cerca de duas horas e meia. O código que desfaz uma publicação falhada removeu todas as apps de servidor que a publicação tinha tocado, incluindo as que já estavam a responder antes de ela começar. Agora, só são apagadas as apps que uma publicação criou, e uma app que já existia volta exatamente à versão que estava a correr antes. Duas correções seguintes, no mesmo dia, garantiram que o desfazer também corre quando a própria ferramenta de deploy da plataforma de alojamento falha, e que uma app saudável não é dada como falhada só porque estava a dormir.

Como é publicado um backend

Quando a sua app Mythex tem um backend (uma API ou servidor, e não apenas ficheiros estáticos), a publicação constrói-o a partir de um Dockerfile (uma receita para empacotar a app numa imagem) e instala essa imagem em máquinas da nossa plataforma de alojamento. Depois, um health check aguarda que a nova versão arranque de facto e se mantenha em funcionamento antes de a publicação ser marcada como ativa.

Se alguma coisa falhar pelo caminho, é executado um rollback para a desfazer. Acertar nesse rollback é mais importante do que quase tudo o resto na publicação, porque corre precisamente quando algo já está a correr mal.

Problema 1: o rollback apagava o que devia restaurar

O rollback mantinha uma lista das apps de servidor onde uma publicação tinha feito deploy e, em caso de falha, destruía todas. Isso está certo numa primeira publicação: a app foi criada há um momento, nada depende dela, e apagá-la deixa tudo como estava.

Esteve exatamente errado numa republicação. A app já existia e estava a servir visitantes reais. A 25 de setembro, a API de uma app que estava ativa há cerca de duas horas e meia foi apagada por uma republicação falhada.

Havia um segundo modo de falha escondido no mesmo código. Quando o apagamento não chegava a acontecer, a nova imagem avariada ficava nas máquinas, enquanto dizíamos ao dono que o seu site atual continuava ativo. No momento em que o health check pode falhar, a nova imagem já foi instalada em todas as máquinas. Não fazer nada não é o mesmo que desfazer.

A correção: destruir apenas o que foi criado e restaurar o resto

Cada publicação regista agora, para cada app de servidor que toca:

  • se esta publicação a criou, e
  • se não a criou, que imagem estava a correr imediatamente antes.

Em caso de falha, cada app recebe um de três tratamentos:

  1. Criada por esta publicação: é destruída, como antes.
  2. Já existia, e a imagem anterior é conhecida: é feito novo deploy da imagem anterior com a mesma configuração. Não há build; só a imagem volta atrás.
  3. Já existia, e a imagem anterior é desconhecida: fica como está. Uma app existente nunca é apagada, mesmo quando não a conseguimos restaurar.

Estas regras são uma pequena função pura com testes próprios, para que a decisão não volte a ser "destruir tudo" sem que um teste falhe.

Problema 2: a ferramenta de deploy podia falhar antes de termos registado como desfazer

Logo depois dessa correção, encontrámos uma lacuna. A ferramenta de deploy da plataforma de alojamento executa os seus próprios testes de funcionamento: se as novas máquinas se avariarem, termina com erro. Mas fá-lo depois de a nova imagem já estar nas máquinas.

O nosso código só registava uma app para rollback quando a ferramenta devolvia sucesso. Quando a própria ferramenta falhava o deploy, a app ainda não estava na lista de rollback, por isso nada era restaurado. No nosso ambiente de staging, uma republicação avariada deixou a imagem avariada a servir.

A correção: registar o desfazer antes de começar

A app fica agora registada para rollback, com a indicação de se foi criada e da imagem que corria, assim que é preparada e antes de qualquer coisa ser instalada nela. Aconteça o que acontecer a seguir, o rollback sabe o que repor. Verificámos localmente: uma republicação avariada falhou nos próprios testes de funcionamento da ferramenta de deploy, e a versão anterior continuou a responder.

Problema 3: uma app a dormir foi dada como "nunca arrancou"

As apps publicadas na Mythex entram em modo de espera quando estão inativas, para poupar créditos. Uma republicação deixa uma máquina parada que estava a dormir, por isso o health check tem de a acordar. Pedia à plataforma para arrancar a máquina uma única vez, e ignorava a resposta.

A 25 de setembro, esse único pedido de arranque não surtiu efeito. Uma API saudável ficou parada durante todo o health check de cinco minutos e foi dada como falhada com "1 máquina nunca arrancou (último estado: parada)".

A plataforma por vezes recusa um arranque. Durante a reprodução do problema, devolveu um conflito "lease currently held" sem que o tivéssemos provocado, e recusa arranques enquanto uma máquina está a ser atualizada.

A correção: continuar a insistir e bater à porta

O health check passa agora a:

  • voltar a pedir o arranque de uma máquina parada a cada 20 segundos enquanto espera,
  • registar o que a plataforma respondeu quando recusou, e
  • enviar um pedido normal à app, tal como faria um visitante. O proxy da plataforma acorda uma máquina a dormir quando chega um pedido.

Reproduzimos o problema na plataforma real com uma app descartável cujo primeiro arranque era recusado. Antes da correção, a publicação falhava ao fim de 91 segundos. Depois, publicou-se em 20 segundos. Uma app que realmente se avaria ao arrancar continua a falhar, como deve ser.

O que retirámos disto

  • O rollback tem de distinguir o que é novo do que já existia. "Desfazer" algo que criaste é apagar. "Desfazer" algo que já lá estava é repor. Tratar as duas coisas da mesma forma é como um mecanismo de segurança acaba por apagar uma app que funciona.
  • Escreve como desfazer antes de agir. Se o desfazer só é registado depois de um passo ter sucesso, um passo que falha a meio deixa nada para desfazer.
  • Nunca ignores a resposta a um pedido de que dependes. Um "não" ignorado transformou uma app saudável numa publicação falhada.

Uma correção relacionada, do mesmo dia: apanhar apps que se avariam logo após a publicação. Para o que acontece quando uma publicação falha do teu lado, consulta a resolução de problemas de publicação na documentação.

Mythex · Pricing · Crie qualquer coisa com IA · Modelos de sites e apps · Mythex comparado · Glossário de criação de apps com IA · Ferramentas grátis para criar apps com IA · 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) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)