← System Design: decidir, dimensionar e recuperar sistemas
12 / 12 · 70 MIN

Leases, gerações e publicação

Coordena consumidores de uma fila e rejeita conclusões antigas através de condições verificadas na atualização do estado.

Adquirir trabalho sem esperar pela mesma linha

Duas sessões iniciam transações. A primeira bloqueia job 1 ready com FOR UPDATE SKIP LOCKED; a segunda obtém job 2. O guião confirma que as linhas selecionadas são diferentes antes de terminar as transações. A seleção e a alteração do job 1 para running ocorrem na mesma transação da primeira sessão. Isto evita um intervalo entre escolher e registar a posse nesse percurso local. Não há broker ou workers autónomos em processos separados: as sessões seguem uma ordem controlada pelo coordenador. O exemplo serve para discutir aquisição numa tabela de fila, não para afirmar garantias universais de justiça, ordenação ou distribuição entre consumidores.

Interpretar uma aquisição vazia

Enquanto a segunda sessão bloqueia job 2, a primeira tenta selecionar especificamente esse job com SKIP LOCKED e recebe zero linhas. O job existe e está ready na visão relevante, mas não pode ser bloqueado por essa tentativa. Concluir que a população de trabalho acabou seria incorreto. Uma rotina de polling precisa de distinguir ausência de trabalho elegível de trabalho indisponível naquele instante e definir uma política limitada de nova tentativa. A contagem global da fila e a idade dos jobs ajudam a diagnosticar estagnação. Este ensaio não mede espera prolongada, starvation ou comportamento de muitos consumidores concorrentes; essas propriedades permanecem por testar.

Expirar autorização sem matar execução

A primeira aquisição regista owner A, epoch 1 e lease_until 10. Uma tentativa de adoção com tempo lógico 9 altera zero linhas. Com tempo lógico 10, a condição aceita a adoção, muda owner para B e incrementa epoch para 2. A sessão A continua a executar SELECT depois disso. Assim, perder autoridade não significa desaparecer, terminar ou cancelar uma operação em curso. Os valores 9 e 10 são inteiros escolhidos pelo guião, não relógios medidos. Não existe scheduler, heartbeat periódico, clock skew ou pausa de processo ensaiada. Numa solução real, define a fonte de tempo e testa atrasos e renovações sem converter a simples expiração numa garantia de exclusividade física.

Verificar a geração no destino

O heartbeat antigo inclui id, estado running, owner A e epoch 1 no predicado. Depois da adoção, devolve zero linhas e não prolonga o lease de B. A publicação usa igualmente estado, owner, epoch e validade lógica do lease. O candidato antigo permanece no disco, mas a atualização de publicação é rejeitada. A geração atual altera uma linha e grava nome e digest do candidato escolhido. A proteção existe porque a base verifica as condições no momento de alterar o registo. Uma verificação anterior seguida de escrita incondicional deixaria outra janela. Serviços externos que não verificam a geração continuam fora desta garantia; o guião não cancela os seus efeitos.

Reconciliar uma conclusão repetida

Depois de complete, repetir a mesma atualização condicionada a running devolve zero linhas. Isso não significa automaticamente falha do resultado nem sucesso da nova tentativa. O guião consulta o registo e confirma geração 2, o candidato esperado e um hash correspondente. Esta reconciliação distingue uma conclusão já aplicada de perda de ownership, cancelamento ou estado incompatível. Outro grupo marca job 2 cancelled e confirma que uma transição condicionada a running é recusada. Não há processo em execução a ser morto nesse caso. O contrato precisa de dizer o que cancelamento bloqueia, o que já pode ter acontecido e como a resposta ao consumidor explica o estado observado.

Entregar uma matriz de falhas

Para um projeto fictício APS, documenta materialização não confirmada, job ready, lease ainda válido, adoção, candidato órfão, publicação confirmada e artefacto indisponível. Liga cada estado a observações, ação permitida, responsável e critério de reversão. Os dezasseis grupos locais mostram mecanismos concretos, mas não estabelecem uma implementação distribuída completa. Planeia ensaios de interrupção de processo, storage, identidade, concorrência de limpeza e comunicação HTTP no destino apropriado. Inclui custos de retenção e critérios de conclusão para negócio. Um diagrama só se torna útil ao suporte quando explica onde obter a evidência e evita que uma tentativa antiga ou incompleta seja apresentada como resultado válido.

python3 content/labs/design-export/run.py --postgres-prefix /path/to/postgresql-18.6 --output /tmp/dr-export-new.json
# Use a fresh output path; owned cluster and files are temporary.
NA PRÁTICA

A geração 2 assume o job após o limite lógico 10; a sessão antiga continua utilizável, mas o seu heartbeat e a sua publicação alteram zero linhas.

Armadilhas comuns

Lease como processo terminado, SKIP LOCKED vazio como fila vazia, zero updates como sucesso e proteção SQL como cancelamento de efeitos externos.

Tópicos relacionados: Filas e concorrência · Recuperação de exportações

Leva esta ideia contigo

A geração identifica a autoridade atual. O destino da publicação deve verificá-la; expiração e nomes de worker não bastam para rejeitar trabalho antigo.

Criar conta

Referência: SELECT and SKIP LOCKED · System design patterns; PostgreSQL18 scoped examples; primary guidance consulted 2026-09-30