Blog

Uma republicação com falha nunca apaga um backend que funciona

No dia 25 de setembro, uma republicação com falha apagou o backend de um app que estava no ar e funcionando havia cerca de duas horas e meia. O código que desfaz uma publicação com falha removeu todos os apps de servidor que a publicação tinha tocado, inclusive os que já estavam servindo antes de ela começar. Agora só são apagados os apps que a própria publicação criou; um app que já existia é colocado de volta exatamente na versão que rodava antes. Duas correções de acompanhamento, no mesmo dia, garantiram que essa desfazer também rode quando a ferramenta de deploy da plataforma de hospedagem falha, e que um app saudável não seja marcado como falho só porque estava em modo de espera.

Como um backend é publicado

Quando seu app na Mythex tem um backend (uma API ou servidor, e não apenas arquivos estáticos), a publicação o compila a partir de um Dockerfile (uma receita para empacotar o app em uma imagem) e coloca essa imagem nas máquinas da nossa plataforma de hospedagem. Depois, um health check aguarda a nova versão realmente subir e se manter de pé antes de marcar a publicação como ativa.

Se qualquer coisa falhar pelo caminho, um rollback é executado para desfazer o que foi feito. Acertar esse rollback importa mais do que quase qualquer outra coisa na publicação, porque ele roda justamente quando algo já está dando errado.

Problema 1: o rollback apagava o que deveria restaurar

O rollback mantinha uma lista dos apps de servidor para os quais a publicação tinha feito deploy e, em caso de falha, destruía todos eles. Isso está certo para uma primeira publicação: o app foi criado há pouco, nada depende dele, e apagá-lo deixa tudo como estava.

É exatamente errado para uma republicação. O app já existia e atendia visitantes de verdade. Em 25 de setembro, a API de um app que estava no ar havia cerca de duas horas e meia foi apagada por uma republicação com falha.

Havia um segundo modo de falha escondido no mesmo código. Quando a exclusão não se concluía, a imagem nova e quebrada continuava nas máquinas, enquanto avisávamos o dono de que o site atual ainda estava no ar. Quando o health check pode falhar, a nova imagem já foi colocada em todas as máquinas. Não fazer nada não é o mesmo que desfazer.

A correção: destruir só o que você criou, restaurar o resto

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

  • se esta publicação o criou, e
  • se não, qual imagem ele estava rodando logo antes.

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

  1. Criado por esta publicação: destruir, como antes.
  2. Já existia, e a imagem anterior é conhecida: fazer redeploy da imagem anterior com a mesma configuração. Sem build; apenas a imagem volta.
  3. Já existia, e a imagem anterior é desconhecida: não mexer. Um app existente nunca é apagado, mesmo quando não conseguimos restaurá-lo.

Essas regras são uma pequena função pura com testes próprios, então a decisão não pode voltar a ser “destruir tudo” sem que um teste falhe.

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

Logo depois dessa correção, encontramos uma lacuna nela. A ferramenta de deploy da plataforma roda os próprios checks de fumaça: se as novas máquinas travam, ela sai com erro. Mas faz isso depois que a nova imagem já está nas máquinas.

Nosso código só registrava um app para rollback quando a ferramenta retornava com sucesso. Quando a própria ferramenta reprovava o deploy, o app ainda não estava na lista de rollback, então nada era restaurado. No nosso ambiente de staging, uma republicação quebrada deixou a imagem quebrada no ar.

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

O app agora é registrado para rollback, com a informação de se foi criado e de qual imagem rodava, assim que é preparado e antes de qualquer coisa ser colocada nele. O que falhar depois, o rollback sabe o que recolocar. Verificamos localmente: uma republicação quebrada falhou nos próprios checks de fumaça da ferramenta de deploy, e a versão anterior continuou respondendo.

Problema 3: um app em espera foi reprovado como “nunca iniciou”

Apps publicados na Mythex entram em espera quando ficam ociosos, para economizar seus créditos. Uma republicação deixa a máquina parada em espera, então o health check precisa acordá-la. Ele pedia à plataforma que iniciasse a máquina uma única vez e ignorava a resposta.

Em 25 de setembro, esse único pedido de início não surtiu efeito. Uma API saudável ficou parada durante todo o health check de cinco minutos e foi reprovada com “1 máquina nunca iniciou (último estado: stopped)”.

A plataforma às vezes recusa um início. Enquanto reproduzíamos o problema, ela retornou um conflito “lease currently held” sem que tivéssemos provocado isso, e recusa inícios enquanto uma máquina está sendo atualizada.

A correção: continuar pedindo e bater na porta

O health check agora:

  • pede de novo para iniciar uma máquina parada a cada 20 segundos enquanto espera,
  • registra o que a plataforma respondeu quando recusou, e
  • envia uma requisição comum ao app, do jeito que um visitante faria: o proxy da plataforma acorda a máquina em espera quando chega uma requisição.

Reproduzimos o caso na plataforma real com um app descartável cujo primeiro início foi recusado. Antes da correção, a publicação falhava após 91 segundos. Depois, publicou em 20 segundos. Um app que trava de fato ao iniciar continua falhando, como deve.

O que tiramos disso

  • O rollback precisa saber a diferença entre novo e existente. “Desfazer” algo que você criou é apagar. “Desfazer” algo que já estava ali é restaurar. Tratar as duas coisas igual é como um mecanismo de segurança acaba apagando um app que funcionava.
  • Registre como desfazer antes de agir. Se o desfazer só é registrado depois que um passo tem sucesso, um passo que falha no meio deixa nada para desfazer.
  • Nunca ignore a resposta de um pedido do qual você depende. Um “não” ignorado transformou um app saudável em uma publicação falha.

Uma correção relacionada, do mesmo dia: apps que travam logo depois de publicar. Para o que acontece quando uma publicação falha do seu lado, veja solução de problemas de publicação na documentação.

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