Passar para Espaços de Trabalho Maiores Sem Fazer Ninguém Esperar
Cada projeto da Mythex tem o seu próprio espaço de trabalho: um pequeno computador na nuvem onde o agente escreve código e onde corre a pré-visualização da tua app. Tínhamos subido a memória dos novos espaços de trabalho de 1 GB para 2 GB, mas os mais antigos continuaram em 1 GB; no dia em que verificámos, cerca de um quarto deles. A nossa primeira correção movia um projeto para um espaço de trabalho maior quando era aberto a seguir. No primeiro dia em produção, isso fez uma pessoa esperar sete minutos. Pusemos um limite de tempo rígido e depois tirámos a mudança do ato de abrir um projeto.
Porque é que os espaços antigos continuavam pequenos
O nosso fornecedor de sandboxes define o tamanho de um espaço de trabalho quando é criado, e mantém-no em todas as pausas e retomas. Alterar o modelo (a receita a partir da qual os novos espaços são construídos) só afeta os espaços criados depois da alteração. Nada redimensiona os que já existem.
Isso tinha importância. Um dos espaços pequenos ficou sem memória durante um git push enquanto a pré-visualização arrancava, e deixou de responder durante 11 minutos. Uma publicação falhou por causa disso.
Primeira tentativa: mover o projeto quando acorda
Os espaços de trabalho entram em pausa quando ninguém os usa e acordam quando o projeto é aberto. Acordar pareceu o momento certo para mover um projeto, porque ninguém está a trabalhar nele ainda.
A mudança funcionava assim:
- Verificar o tamanho. Se o espaço de trabalho for menor que 2 GB, move-o. Se o tamanho for desconhecido, não faz nada.
- Não perturbar uma publicação. Uma publicação lê os ficheiros do espaço de trabalho, por isso, se uma estiver a correr, a mudança é saltada.
- Empacotar o projeto. Arquiva tudo o que está no projeto, incluindo o seu histórico git (ou seja, cada checkpoint que o projeto tem) e o ficheiro
.envda app, que pertence ao dono, mas deixa de fora as dependências instaladas (node_modules), que podem ser reinstaladas. - Copiar diretamente. Transmite o arquivo do espaço antigo para um espaço novo de 2 GB, para que nunca tenha de caber na memória do nosso próprio servidor.
- Comparar antes de mudar. Conta os ficheiros, lê o checkpoint mais recente e conta os checkpoints, nos dois espaços. Só muda se os três coincidirem.
- Manter o antigo em qualquer falha. Qualquer erro ou qualquer diferença descarta o novo espaço e abre o projeto no antigo, como antes.
Um detalhe da comparação fez mais diferença do que parece. A verificação corre como a conta de administrador, e o git recusa-se a ler um repositório que pertence a outro utilizador. Não imprimia nada nos dois lados, e "nada" igualava "nada", por isso a verificação passava sem comparar história nenhuma. Dissemos ao git para confiar no diretório e acrescentámos um teste para que isso não volte a acontecer.
O que correu mal no primeiro dia
No seu primeiro dia em produção, o empacotamento de um projeto atingiu um tempo limite de cinco minutos dentro do acordar. O dono esperou sete minutos até o seu espaço de trabalho abrir. E como a mudança tinha falhado, o projeto continuava pequeno, por isso a abertura seguinte tentaria de novo e voltaria a fazê-lo esperar.
Uma migração que obriga alguém a esperar ao abrir o seu próprio projeto é um mau negócio. A ideia de a fazer no momento de acordar era que ninguém desse por ela.
Segunda tentativa: um orçamento rígido
No mesmo dia, mudámos quatro coisas:
- Um minuto para a mudança inteira. Cada passo (verificar o tamanho, empacotar, criar o novo espaço, copiar, desempacotar, comparar) partilha um único orçamento de 60 segundos. Quando acaba, o projeto abre no espaço antigo.
- Parar o trabalho, não apenas a espera. Desistir do nosso lado não basta se o arquivo ainda estiver a correr dentro do espaço que o dono está prestes a usar. Cada comando de arquivo é agora terminado dentro do próprio espaço, pouco antes de o orçamento acabar. Se o novo espaço chegar depois de termos desistido, é descartado.
- Não fazer o dono esperar pela limpeza. Apagar o arquivo temporário passa a acontecer em segundo plano.
- Não tentar de novo a cada abertura. Um projeto que não conseguiu mudar fica em paz durante 24 horas, por isso uma falha custa no máximo um atraso por dia, e não um por abertura.
Terceira tentativa: tirá-la do acordar
Isso reduziu o pior caso a um minuto. Mas um minuto continua a ser um minuto, e percebemos que a mudança não precisava de estar no caminho de ninguém.
Nenhum espaço é criado com 1 GB hoje em dia. Por isso, isto não é um processo contínuo; é uma tarefa pontual com uma lista fixa de espaços de trabalho. Fazê-la dentro do acordar significava que uma pessoa real pagava por cada mudança lenta, e a única forma de sabermos que um espaço não ia mudar era alguém ter acabado de esperar por ele.
Por isso retirámos a mudança do acordar por completo. Abrir um projeto faz o que fazia antes. Os espaços pequenos que restam são tratados como um lote supervisionado: ninguém está à espera, e um espaço que não consiga mudar aparece no relatório do lote, onde podemos olhar para ele, em vez de aparecer à frente da pessoa que é dona dele.
O que retirámos disto
- Redimensionar nem sempre é possível. Quando uma plataforma fixa o tamanho na criação, aumentar a predefinição só ajuda o que é novo. Planeia para os antigos.
- "Ninguém está a usar ainda" não quer dizer que ninguém esteja à espera. Trabalho feito à entrada de um produto é trabalho que uma pessoa observa.
- Põe um orçamento em tudo o que está no caminho de um utilizador, e para o trabalho quando o orçamento acaba. Expirar do nosso lado enquanto um comando continua a correr noutro lado só move o problema.
- Uma migração pontual pertence a uma tarefa pontual. Escondê-la em ações do dia a dia torna-a mais barata de escrever e mais cara de executar.
- Testa as tuas verificações de segurança. Uma comparação que não compara nada parece exatamente igual a uma que passou.
Se construis na Mythex, não tens de fazer nada: o objetivo é simplesmente ter menos espaços de trabalho a ficar sem memória, mantendo a abertura de um projeto tão rápida como antes. Como os espaços de trabalho entram em pausa e acordam está explicado na documentação, em espaço de trabalho privado. Para outra história de falta de memória, vê o crash por falta de memória escondido numa etiqueta de progresso.