un

guest
1 / ?
back to lessons

Forma 1: Reparo de Estado. Forma 2: Relatório Desperdiçado.

Um Coração Medido bate no relógio. Não no necessidade. Não na mudança. No cronômetro.

Dois formatos, uma causa raiz: um trabalho agendado substituindo o design correto.

Forma 1: Reparo de Estado

Uma transição de estado falha para ser concluída atomicamente. Em vez de corrigir a transição, um trabalho de fundo é executado com atraso & reconcilia. Os usuários veem estado quebrado durante a janela de reconciliação.

Exemplo do GitHub (2026-04-08): Uma solicitação de pull do repositório upstream tornou-se privada. O GitHub tentou uma transição de estado: fechar o PR, atualizar o status do branch, limpar o status de fusão. A transição não concluiu atomicamente. O status do PR mostrou 'branch-forced-closed' & 'Não é possível carregar o status de fusão' simultaneamente. Um trabalho de fundo Sidekiq correu minutos depois & concluiu a reconciliação. Observadores viram estado quebrado durante a duração da janela.

O Coração Medido: o trabalho Sidekiq foi executado conforme o agendado. Ele não foi executado porque o GitHub detectou estado quebrado; ele foi executado porque o relógio disparou. Um usuário assistindo o PR em tempo real viu um PR que contradizia-se até a próxima execução do trabalho.

Forma 2: Relatório Desperdiçado

Um relatório ou agregação recalcula do zero em um intervalo fixo. Nenhuma verificação de cache. Nenhuma guarda de idempotência. Nenhuma atualização incremental. Cada execução: um escaneamento completo.

Exemplos: um trabalho de cron noturno que recalcula o total de compras de cada usuário escaneando todas as ordens desde o início do tempo. Um trabalho de análise diário que regenera um painel do dashboard a partir de logs de eventos brutos. Um e-mail semanal de resumo que consulta todas as linhas na tabela de atividades.

Cada um dispara independentemente de haver dados alterados desde a última execução. Cada um escaneia a história completa mesmo quando apenas os últimos 24 horas contêm novos dados. Cada um substitui a repetição agendada por um design incremental.

A Raiz Compartilhada

Um Coração Medido não pode dizer a verdade sobre seu próprio estado. Ele só sabe do relógio. Forma 1: o trabalho de reparo de estado é executado às 5 minutos após T independentemente de o estado estar quebrado em T+0. Forma 2: o trabalho de relatório é executado às 2 da madrugada independentemente de haver dados alterados desde ontem.

O relógio não carrega informações sobre o que precisa ser feito. Um evento carrega essa informação: 'uma transição de estado acabou de falhar', 'novas ordens acabaram de chegar'. Um Coração Medido joga essa informação no lixo & a substitui por um agendamento.

Drenagem de Capital

O Coração Medido drena capital vivo: engenheiros em chamada para incidentes de estado quebrado. Erode a confiança social: usuários veem dados inconsistentes e relatam defeitos que se resolvem sozinhos. Amplifica outros MOADs: um trabalho de reparo de estado que escaneia todos os registros para encontrar estado quebrado frequentemente contém MOAD-0001 (escaneamento O(N²)). Um trabalho de relatório que recalcula dados frios pode disparar MOAD-0005 (estampide de cache). O MOAD-0009 agrava outros defeitos.

A Raiz Compartilhada

Forma 1 e Forma 2 parecem diferentes na superfície: uma reparo estado, a outra recalcula dados. A causa raiz os conecta.

Forma 1 e Forma 2 compartilham uma causa raiz. Descreva em uma frase. Em seguida, forneça um exemplo de cada forma de software que você já usou.

Queime Mudança, Não Relógio

Design baseado em eventos dispara quando algo muda. A transição de estado é o evento. O evento é o gatilho.

Forma 1: a transição atômica substitui o trabalho de reparo.

Se uma transição de estado pode deixar o sistema em um estado quebrado intermediário, o defeito vive na transição, não na ausência de um trabalho de reparo. Corrija a transição para ser completada atomaticamente (ou transacionalmente). Quando a transição for completada atomaticamente, o estado quebrado nunca existirá. O trabalho de reparo não terá nada para reparar.

# DEFECT: transição não-atômica deixa estado quebrado
def close_pr_on_repo_private(pr_id):
    pr = PR.get(pr_id)
    pr.status = 'branch-forced-closed'   # etapa 1: estado parcial
    pr.save()                             # visível aos usuários AGORA
    # ... outras etapas podem falhar ...
    pr.merge_status = 'not_applicable'
    pr.save()                             # etapa 2: agora consistente
    # Job Sidekiq de reconciliação se a etapa 2 falhar
# CORREÇÃO: transição atômica; nenhum estado intermediário visível
def close_pr_on_repo_private(pr_id):
    with db.transaction():
        pr = PR.get(pr_id)
        pr.status = 'branch-forced-closed'
        pr.merge_status = 'not_applicable'
        pr.save()   # ambos os campos se comprometem atomicamente; nunca escrito pela metade

Forma 2: a atualização incremental substitui o cálculo completo.

Um relatório que recalcula do zero dispara porque dados antigos + novos dados = novo resultado. Mas os dados antigos + delta = mesmo novo resultado, calculado incrementalmente. O evento: dados novos chegaram. O gatilho: atualize o agregado apenas para os novos dados.

# DEFICIÊNCIA: cálculo completo agendado
def nightly_totals_job():
    for user in all_users():
        total = sum(o.amount for o in user.orders)  # analisar todos os tempos
        user.total_purchases = total
        user.save()

# CORREÇÃO: atualização incremental baseada em eventos
def on_order_placed(order):
    order.user.total_purchases += order.amount   # apenas delta
    order.user.save()

A atualização incremental dispara quando uma compra é feita, não às 2 da madrugada. Ele atualiza apenas o usuário afetado. Ele lê apenas a nova compra, não todas as compras de todos os tempos. O job noturno desaparece.

Por que a Forma 1 Revela uma Transição Quebrada

Um Medidor de Corrente da Forma 1 Revela que uma transição de estado foi deixada incompleta. O job de reparo existe porque um engenheiro notou um estado quebrado e adicionou um mecanismo de reconciliação em vez de corrigir a transição. O job de reparo: uma correção sobre uma decisão arquitetural quebrada.

MOAD-0009 como Amplificador

O MOAD-0009 amplifica outros MOADs. Um job de reparo do estado que varre todos os registros para encontrar o estado quebrado: MOAD-0001 (O(N) ou O(N²) scan por execução do job). Um job de relatório que recalcula tudo em frio: MOAD-0005 (estampide de cache quando o job começa e atinge uma fonte upstream quente). O MOAD-0009 não machuca apenas por si só; ele entrega outros MOADs em um cronograma.

Diagnose & Redesign

Um time executa um job cron noturno às 2 da madrugada. O job escaneia todos os pedidos de todos os usuários e recomputea o total de compras de cada usuário do zero. O job leva 4 horas. Às 6 da manhã, o painel mostra totais atualizados. Entre às 2 da madrugada e às 6 da manhã, o painel mostra totais do dia anterior.

Qual forma do MOAD-0009 é esta? Que evento deveria disparar o recálculo em vez disso? Qual estrutura de dados intermediária torna a atualização incremental?