Duas estatísticas, duas definições de "capturado"
O dashboard do Greenhouse mostra duas estatísticas relacionadas: um badge de “Capturado hoje” e uma sequência de dias consecutivos. Elas deveriam concordar, e na maior parte do tempo concordavam, até você capturar uma ideia e promovê-la a um projeto ativo no mesmo dia. Aí “Capturado hoje” silenciosamente voltava pra desligado, mesmo você tendo capturado algo naquela mesma manhã.
O bug era duas funções calculando o mesmo conceito de duas formas diferentes. A função da sequência puxava o created_at de todo item independente de qual status ele tinha agora, de propósito, com um comentário no código explicando que um dia de captura não deveria sumir só porque a ideia foi promovida depois. Mas a contagem de “capturado hoje” filtrava só por status = 'fresh_idea'. No momento em que você promovia uma ideia, ela parava de ser uma ideia nova, e parava de contar, mesmo com a sequência ainda creditando o dia corretamente. Mesmo dado subjacente, duas lentes diferentes, duas respostas diferentes.
Enquanto rastreava isso encontrei uma segunda pergunta relacionada, sem resposta, sentada no mesmo canto do código: importar uma pasta já existente do disco grava o created_at no momento da importação e silenciosamente também alimentava a sequência. Importe uma pasta cheia de ideias de música de seis meses atrás e o Greenhouse te creditaria por ter capturado algo hoje. O PRD quer dizer algo mais restrito com “capturado”, porém, e é explícito: “Capturou uma ideia hoje?” é sobre o fluxo de Captura, o ato criativo de verdade de se sentar com uma ideia nova. Adotar uma pasta que alguém já criou não é isso.
Corrigi as duas coisas de uma vez: adicionei uma coluna marcando linhas como importadas ou genuinamente capturadas, e apontei as duas estatísticas pra mesma query subjacente, filtrada pra excluir importações. Linhas já existentes recebem backfill como “não importada” por padrão, o que significa que importações antigas de antes desse fix ainda contam retroativamente. Decidi que isso estava bom. É um empurrãozinho motivacional, não um livro-razão, e o PRD é explícito que sequências são estatísticas, nunca travas.
O fix inteiro morava na camada de banco de dados, sem UI pra clicar, então a verificação foram quatro testes novos exercitando as funções de produção de verdade diretamente em vez de uma renderização mockada. Às vezes a quantidade certa de cerimônia pra um bug é uma migration e alguns testes unitários, não um navegador.
Leitura relacionada
O banco de dados vazio que parecia perfeitamente saudável
O SQLite trata um arquivo de zero bytes como um banco de dados novo e válido, então toda checagem de corrupção passava - e a poda de backups teria apagado as cópias boas em uma semana.
A guarda que nunca esteve lá
Adicionar uma checagem de status a uma função Rust a impediu de chamar outra função do mesmo jeito - e isso abriu em silêncio uma brecha que nenhuma das duas tinha sozinha.
Um teste que não provou nada, e o bug que ele deveria pegar
Um lote de limpeza com cinco descobertas, onde o menor item foi o que mais importou: um teste de regressão que falhou porque o bug que ele mirava é estruturalmente inalcançável.
Você também pode achar útil
Proton Drive
Armazenamento em nuvem criptografado, da equipe por trás do Proton Mail.
Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).
Saiba maisProton VPN
VPN comercial com filtragem NetShield e interruptor de desligamento automático.
Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).
Saiba maisRackNerd VPS
Hospedagem VPS econômica para serviços leves que funcionam continuamente.
Como afiliado da RackNerd, ganho com compras qualificadas.
Saiba mais