Migrar para workspaces maiores sem fazer ninguém esperar
Todo projeto da Mythex ganha seu próprio workspace: um pequeno computador na nuvem onde o agente escreve código e a prévia do seu app roda. Tínhamos aumentado a memória dos novos workspaces de 1 GB para 2 GB, mas os mais antigos continuaram em 1 GB — no dia em que verificamos, cerca de um quarto deles. Nossa primeira correção movia um projeto para um workspace maior na próxima vez que ele fosse aberto. No primeiro dia em produção, isso fez uma pessoa esperar sete minutos. Colocamos um limite de tempo rígido e depois tiramos a migração de dentro da abertura do projeto.
Por que os workspaces antigos continuaram pequenos
Nosso provedor de sandbox define o tamanho de um workspace na criação e o mantém em todas as pausas e retomadas. Mudar o template, a receita a partir da qual os novos workspaces são construídos, afeta apenas os workspaces criados depois da mudança. Nada redimensiona os que já existem.
Isso importava. Um dos workspaces pequenos ficou sem memória durante um git push enquanto a prévia dele iniciava, e parou de responder por 11 minutos. Uma publicação falhou por causa disso.
Primeira tentativa: mover o projeto ao acordar
Workspaces pausam quando ninguém os usa e acordam quando o projeto é aberto. Acordar pareceu o momento certo para mover um projeto, porque ninguém está trabalhando nele ainda.
A migração funcionava assim:
- Verifique o tamanho. Se o workspace for menor que 2 GB, mova-o. Se o tamanho for desconhecido, não faça nada.
- Não atrapalhe uma publicação. Uma publicação lê os arquivos do workspace, então, se uma estiver em andamento, pule a migração.
- Empacote o projeto. Compacte tudo do projeto, inclusive o histórico do git, que são todos os checkpoints que o projeto tem, e o arquivo
.envdo app, que pertence ao dono, mas deixe de fora as dependências instaladas (node_modules), que podem ser reinstaladas. - Copie direto. Transmita o arquivo compactado do workspace antigo para um workspace novo de 2 GB, para que ele nunca precise caber na memória do nosso próprio servidor.
- Compare antes de trocar. Conte os arquivos, leia o checkpoint mais recente e conte os checkpoints, nos dois workspaces. Troque apenas se os três coincidirem.
- Mantenha o antigo em qualquer falha. Qualquer erro ou divergência descarta o workspace novo e abre o projeto no antigo, como antes.
Um detalhe na comparação importou mais do que parece. A verificação roda com a conta de administrador, e o git se recusa a ler um repositório que pertence a outro usuário. Ela não imprimiu nada nos dois lados — e “nada” igualou “nada”, então a verificação passou sem comparar histórico nenhum. Dissemos ao git para confiar no diretório e adicionamos um teste para que isso não volte a acontecer.
O que deu errado no primeiro dia
No primeiro dia em produção, empacotar um projeto atingiu um tempo limite de comando de cinco minutos — dentro do acordar. O dono esperou sete minutos para o workspace abrir. E como a migração tinha falhado, o projeto continuava pequeno, então a próxima abertura tentaria de novo e faria a pessoa esperar outra vez.
Uma migração que faz alguém esperar para abrir o próprio projeto é uma troca ruim. O sentido de fazê-la ao acordar era que ninguém perceberia.
Segunda tentativa: um orçamento rígido
No mesmo dia, mudamos quatro coisas:
- Um minuto para a migração inteira. Cada etapa — verificar o tamanho, empacotar, criar o novo workspace, copiar, desempacotar, comparar — divide um único orçamento de 60 segundos. Quando ele acaba, o projeto abre no workspace antigo.
- Pare o trabalho, não só a espera. Desistir do nosso lado não basta se a compactação ainda estiver rodando dentro do workspace que o dono está prestes a usar. Cada comando de compactação agora é encerrado dentro do próprio workspace pouco antes de o orçamento acabar. Se o workspace novo chegar depois de termos desistido, ele é descartado.
- Não faça o dono esperar a limpeza. Apagar o arquivo temporário agora acontece em segundo plano.
- Não tente de novo a cada abertura. Um projeto que não pôde ser migrado fica de fora por 24 horas, então uma falha custa no máximo um atraso por dia, e não um por abertura.
Terceira tentativa: tirar a migração do acordar
Isso deixou o pior caso em um minuto. Mas um minuto ainda é um minuto, e percebemos que a migração não precisava estar no caminho de ninguém.
Nenhum workspace é mais criado com 1 GB. Então isso não é um processo contínuo; é um trabalho único com uma lista fixa de workspaces. Fazê-lo dentro do acordar significava que uma pessoa real pagava por cada migração lenta, e a única forma de descobrirmos que um workspace não seria migrado era alguém ter acabado de esperar por ele.
Assim, removemos a migração do acordar por completo. Abrir um projeto faz o que fazia antes. Os workspaces pequenos restantes são tratados como um lote supervisionado: ninguém espera por ele, e um workspace que não puder ser migrado aparece no relatório do lote, onde podemos analisá-lo, em vez de aparecer na frente do dono.
O que tiramos disso
- Redimensionar nem sempre é possível. Quando uma plataforma fixa o tamanho na criação, aumentar o padrão só ajuda as coisas novas. Planeje para as antigas.
- “Ninguém está usando ainda” ainda significa que alguém está esperando. Trabalho feito no caminho para dentro de um produto é trabalho que uma pessoa observa.
- Coloque um orçamento em qualquer coisa que esteja no caminho do usuário, e pare o trabalho quando ele acabar. Dar timeout do nosso lado enquanto um comando continua rodando em outro lugar só desloca o problema.
- Uma migração única pertence a um trabalho único. Escondê-la em ações do dia a dia a torna mais barata de escrever e mais cara de rodar.
- Teste suas verificações de segurança. Uma comparação que não compara nada parece exatamente igual a uma que passou.
Se você constrói na Mythex, não há nada a fazer: o objetivo é simplesmente menos workspaces ficando sem memória, com a abertura de projetos tão rápida quanto antes. Como os workspaces pausam e acordam está descrito na documentação, em workspace privado. Para outra história de falta de memória, veja o estouro de memória escondido em um rótulo de progresso.