Lançamos suporte a beads v1.0.0. Foram necessários um rollback, um bug de flock e 6 hotfixes.
Em 2 de abril, beads lançou v1.0.0. A funcionalidade principal era embedded Dolt: um backend zero-config que roda o banco de dados in-process, sem servidor separado para gerenciar. Para desenvolvedores solo, era a promessa de bd init e pronto. Sem portas, sem daemons, sem configuração.
Começamos a adicionar suporte no Beadbox imediatamente. Seis hotfixes, um rollback público e um mergulho profundo no código-fonte do bd depois, saímos do outro lado com uma camada de resiliência que provavelmente deveríamos ter construído meses antes.
A manhã antes de tudo quebrar
O dia começou limpo. Tínhamos feito uma caçada a código morto pela codebase e lançado v0.20.0 com 5.350 linhas removidas e uma melhoria de 2 segundos no cold launch. Quarenta e dois beads fechados. Uma boa manhã.
Então atualizamos bd para 0.63.3, o primeiro release construído sobre o backend embedded Dolt do beads v1.0.0.
Beadbox não conseguia encontrar o banco de dados. O modo embedded armazena dados em .beads/embeddeddolt/ em vez de .beads/dolt/. O nome do banco também mudou, de beads hardcoded para um prefixo de projeto lido de metadata.json. E bd sql, que nosso servidor WebSocket usava para detecção de mudanças O(1) via DOLT_HASHOF_TABLE, não é suportado em modo embedded.
Três suposições quebradas nos primeiros dez minutos.
Seis releases em um dia
Descobrir, corrigir, lançar, descobrir de novo.
v0.20.1 adicionou persistência de credenciais usando o keychain do OS (seis beads de trabalho já em andamento), corrigiu um bug do filtro de status personalizado e corrigiu problemas específicos do Windows.
v0.20.2 ensinou o Beadbox a ler dolt_database de metadata.json para encontrar o banco de dados renomeado.
v0.20.3 adicionou guards para o modo embedded. Cada chamada bd sql foi envolvida com uma verificação: se estamos em modo embedded, fazer fallback para polling baseado em CLI ao invés de queries SQL diretas. A função getDoltDir aprendeu a verificar primeiro em embeddeddolt/.
v0.20.4 corrigiu a normalização de caminhos --db para o layout embedded. Caminhos que funcionavam com a estrutura de diretórios antiga quebravam com a nova.
Cada correção revelava o próximo problema.
O flock
Depois do v0.20.4, achamos que estávamos estáveis. Então rodamos um teste simples de concorrência: cinco chamadas bd list ao mesmo tempo.
Quatro falharam.
Embedded Dolt adquire um file lock exclusivo (flock) no banco de dados por toda a vida útil de cada comando. De PersistentPreRun a PersistentPostRun, nada mais pode acessar. Isso é por design. Sem ele, a inicialização concorrente do engine causa um nil-pointer panic (beads#2571). O flock previne o crash. Mas também significa que em modo embedded, bd é efetivamente single-process.
Beadbox não é single-process. Nosso servidor WebSocket faz polling de mudanças a cada segundo. A UI dispara múltiplas server actions no carregamento da página. Um usuário navegando pelo app enquanto o poller de fundo roda vai gerar chamadas bd concorrentes. O flock bloqueia todas exceto a primeira.
O post do blog DoltHub sobre a implementação embedded descrevia o comportamento pretendido: chamadores concorrentes deveriam "se enfileirar naturalmente com backoff exponencial." Mas arch revisou o código-fonte publicado e descobriu que bd usa TryLock com LOCK_NB (não-bloqueante). Não espera. Falha imediatamente. Existem duas camadas de lock: o flock do bd no topo, e o backoff do Dolt no nível do driver embaixo. A primeira camada curto-circuita a segunda. A lógica de retry existe na codebase, mas nunca executa porque o flock rejeita a conexão antes que o backoff do Dolt tenha chance de rodar.
A correção (locks compartilhados para operações de leitura via FlockSharedNonBlock) existe no código-fonte do bd. Só não está conectada ainda.
Este e o problema que o Beadbox resolve.
Visibilidade em tempo real do que toda a sua frota de agentes esta fazendo.
Podíamos continuar lançando hotfixes contra um alvo em movimento, ou recuar e construir uma camada de resiliência adequada. Recuamos.
Todos os releases v0.20.x foram removidos do repo público. v0.19.0 voltou como versão recomendada. Publicamos uma discussão explicando o que aconteceu e o que fazer, e adicionamos um banner no beadbox.app. Trinta minutos da decisão até o fim.
Cada hora que um release quebrado fica público é uma hora em que alguém faz download, encontra o problema do flock e culpa o produto. Preferimos explicar um rollback do que debugar a experiência ruim de primeiro uso de outra pessoa.
Não fomos os únicos
Enquanto debugávamos, um usuário de beads chamado Kevin postou beads#2938: "Beads feels painful to use." Ele havia passado 9,5 horas debugando problemas que incluíam exatamente a confusão embedded-para-servidor que estávamos enfrentando. A atualização para v1.0.0 havia silenciosamente trocado seu workspace do modo servidor para modo embedded (beads#2949), escondendo suas issues existentes atrás de um banco de dados novo e vazio.
9,5 horas. Um usuário experiente, não alguém novo na ferramenta. Se essa é a experiência para alguém que conhece beads bem, o problema não é o usuário. É o caminho de migração.
O que construímos para v0.21.0
Em vez de fazer patch em falhas individuais, construímos uma camada que trata contenção de lock como uma condição operacional normal.
Flock retry com backoff exponencial. Cada chamada ao CLI do bd tenta novamente até 5 vezes, 100ms a 1,6 segundos entre tentativas. Fica em um único lugar em lib/bd.ts, então todo comando ganha de graça. Isso cobre o caso comum: duas chamadas colidem, uma espera brevemente, ambas têm sucesso.
UI de degradação elegante. Contenção de lock não significa mais uma tela de erro. O app mostra dados obsoletos com um indicador de atualização. Se a contenção persiste por mais de 30 segundos, um banner âmbar explica a situação. Quando o lock é liberado, o banner desaparece e os dados são atualizados automaticamente.
Sugestão de auto-promote. Contenção repetida aciona uma sugestão para migrar para modo servidor: backup, reinicialização com --server, restauração. Um clique. Essa é a resposta certa para qualquer um rodando Beadbox junto com outros consumidores bd, e agora o app diz isso ao invés de te deixar descobrir sozinho.
Detecção de modo embedded.getDoltDir verifica embeddeddolt/ e roteia de acordo. Chamadas bd sql são protegidas. O pipeline WebSocket faz fallback para polling baseado em CLI em modo embedded (mais lento, mas respeita a restrição single-process).
O que aprendemos
Embedded Dolt é single-process por design. Não é bug. O flock previne panics reais. Qualquer ferramenta consumindo um workspace beads concorrentemente precisa serializar o acesso ou rodar em modo servidor. Para Beadbox, modo servidor é o padrão correto. Embedded funciona para uso leve com a camada de retry absorvendo colisões ocasionais.
A documentação descrevia a intenção, não a implementação. O blog do DoltHub disse backoff. O código disse TryLock com LOCK_NB. Gastamos tempo assumindo que leituras concorrentes deveriam funcionar porque a documentação dizia isso. Ler o código-fonte resolveu a confusão em minutos. Quando o comportamento não bate com a documentação, leia o código.
Teste concorrência antes de lançar. Não rodamos chamadas bd concorrentes até que v0.20.4 estava público. for i in {1..5}; do bd list & done; wait teria pego o problema do flock antes de qualquer release. Cinco segundos de teste teriam nos poupado um rollback.
Faça rollback cedo. O instinto de continuar avançando é forte. Você está perto, consegue ver a correção, só mais um release. Mas cada release quebrado que fica público é uma retirada de confiança que não se desfaz facilmente. Voltar para v0.19.0 nos deu espaço para construir a camada de resiliência adequadamente ao invés de lançá-la em incrementos de pânico.
Verifique suas variáveis de ambiente. Perdemos horas porque BEADS_DIR apontava bd para o workspace errado. bd estava descobrindo um banco de dados diferente daquele que Beadbox estava monitorando, e os sintomas pareciam corrupção de dados. Se seus comandos bd retornam resultados inesperados, env | grep BEADS antes de qualquer coisa.
Situação atual
v0.21.0 está disponível com suporte a beads v1.0.0, a camada de resiliência e persistência de credenciais via keychain do OS. A discussão do release tem os detalhes completos.
Se você está no beads v1.0.0 com modo embedded e enfrentando falhas intermitentes, a camada de retry do v0.21.0 deve resolver. Se você roda Beadbox junto com outras ferramentas que acessam o mesmo workspace, mude para modo servidor. O fluxo de auto-promote faz isso em um clique.
E se você é o Steve ou alguém do time beads lendo isso: shared flocks para leituras corrigiriam a causa raiz upstream. beads#2939 (Unix domain sockets) tornaria conexões locais mais limpas também. Vamos continuar construindo em torno do que for lançado.
Experimente você mesmo
Comece com beads como camada de coordenação. Adicione o Beadbox quando precisar de supervisão visual.
Gratuito durante o beta. Sem necessidade de conta. Compatível nativamente com Dolt.