Lock deve viver em sidecar, nunca no arquivo de dados
Sessões de agente de IA rodando em paralelo (uma IA "pai" mais um ou mais subagentes, ou várias sessões independentes) frequentemente precisam escrever no mesmo arquivo de estado — um índice, um registro, um arquivo de configuração compartilhado. A tentação natural é colocar um campo de "lock" dentro do próprio arquivo: uma chave locked_by, um timestamp de locked_at. Isso quebra de um jeito específico e sutil.
Por que o lock inline quebra
A causa raiz é como escrita atômica de arquivo normalmente funciona: para evitar corromper o arquivo se o processo morrer no meio da escrita, o padrão seguro é escrever num arquivo temporário e depois trocar atomicamente (os.replace ou equivalente) para o nome final. Essa troca substitui o inode inteiro — não faz um "merge" de campos. Se o lock mora dentro do arquivo de dados, qualquer escrita normal do conteúdo apaga o lock junto (porque o novo inode não tem ideia de que havia um lock no antigo), mesmo que nenhum código tenha pedido para liberar o lock.
O resultado prático: duas sessões podem, cada uma achando que detém o lock, escrever por cima uma da outra — exatamente o cenário que o lock deveria impedir. O bug não está na lógica de "verificar antes de escrever"; está em onde o estado do lock mora fisicamente em relação ao mecanismo de escrita atômica.
O padrão correto: sidecar
O lock precisa viver num arquivo separado — um sidecar, geralmente com sufixo .lock ao lado do arquivo de dados (estado.json + estado.json.lock). A sessão que quer escrever:
- Tenta criar o arquivo
.lockde forma exclusiva (o equivalente aO_EXCL— falha se já existir, em vez de sobrescrever). - Se conseguiu criar, tem o lock: pode fazer sua escrita atômica normal no arquivo de dados.
- Remove o
.lockao terminar (ou trata timeout/stale-lock se a sessão travou sem liberar).
Como o sidecar nunca é tocado pela escrita atômica do arquivo de dados (são inodes diferentes), o lock sobrevive exatamente pelo tempo que deveria — nem um segundo a mais, nem um a menos.
Generalização
A regra vale para qualquer par (estado compartilhado, escrita atômica): se o mecanismo de troca de conteúdo substitui o arquivo inteiro, nenhum metadado que precise sobreviver a essa troca pode morar dentro do mesmo arquivo. Isso inclui não só locks, mas qualquer contador de versão ou marca d'água de concorrência que precise ser lido antes de decidir se a escrita é segura — se ele mora no mesmo lugar que está sendo substituído, a leitura de "antes" e o dado de "depois" nunca coexistem de forma confiável.
← Voltar pra Notes