Multiagente e Orquestração|INEMA.CLUB-PRO

Aula 6 · 20 min

Filas, retomada e colisão entre sessões

Uma fila em pastas sobrevive a queda: o que estava rodando volta para a entrada. Mas a mesma retomada que salva uma cópia atropela a outra quando duas rodam na mesma pasta. Nesta aula você interrompe e retoma uma fila, provoca a colisão com números, trava com flock e vê a guarda de colisão perguntar antes de editar.

Começar a aula
Bandejas de metal numa prateleira escura: entrada com pastas, uma do meio com uma pasta sob trava e uma de saída.

Nesta aula você vai

  1. 1Os estados entrada, rodando, feito e falhou
  2. 2Retomada: pelo menos uma vez, nunca exatamente uma
  3. 3Duas cópias na mesma pasta: cada tarefa roda duas vezes
  4. 4flock e a guarda de colisão do runtime

Objetivo: interromper e retomar uma fila, provocar a colisão de duas filas na mesma pasta e travar com flock e com a guarda de colisão.

01O caminho de uma tarefa na fila

A fila caseira do jornada-agentes, em pastas. Clique em cada estado.

Clique em cada bloco do diagrama para ver o que ele faz.

A fila durável de verdade, com banco, tentativas e portões, é o inemaccbot do curso de Filas. Aqui a ideia mínima, para ver a falha.

02Interrompa e retome

Rode, mate o processo no meio e rode de novo. Uma tarefa falha na primeira execução.

entrada/

rodando/

feito/

falhou/

Simulação ilustrativa no navegador. O ensaio de verdade, com o script e um claude falso, está logo abaixo.

03Ensaio: retomada, colisão e flock

Um claude FALSO no PATH anota cada execução num log. Contar linhas do log mostra quantas vezes cada tarefa rodou.

Terminal · ensaio sem cota
cd ~/jornada-agentes                      # git clone https://github.com/inematds/jornada-agentes.git ~/jornada-agentes
E=${TMPDIR:-/tmp}/ensaio-multi/fila; rm -rf $E && mkdir -p $E/bin
cat > $E/bin/claude <<'SH'
#!/usr/bin/env bash
# claude FALSO: anota quem rodou o quê, demora 1 s e responde (nenhum modelo é chamado)
echo "$PPID $2" >> "${E_LOG:?}"; sleep 1; echo "resposta para: $2"
SH
chmod +x $E/bin/claude; export PATH=$E/bin:$PATH E_LOG=$E/execucoes.log
nova_fila() { rm -rf $E/fila $E_LOG; mkdir -p $E/fila/entrada; for i in 1 2 3 4; do echo "tarefa $i" > $E/fila/entrada/0$i.md; done; }
F=./ferramentas/fila-caseira.sh

echo "## 1) roda e é interrompida no meio"
nova_fila; timeout -s INT 2.5 $F $E/fila
echo "rodando: $(ls $E/fila/rodando) · feito: $(ls $E/fila/feito | tr '\n' ' ')"
echo "## 2) roda de novo: retoma"
$F $E/fila | tail -1
echo "execuções: $(wc -l < $E_LOG) para 4 tarefas"

echo "## 3) duas filas na mesma pasta, ao mesmo tempo"
nova_fila; $F $E/fila > $E/a.log 2>&1 & $F $E/fila > $E/b.log 2>&1 & wait
echo "execuções: $(wc -l < $E_LOG) para 4 tarefas · repetidas: $(cut -d' ' -f2- $E_LOG | sort | uniq -d | tr '\n' ' ')"

echo "## 4) a mesma coisa com flock"
nova_fila; flock -n $E/fila.lock $F $E/fila > $E/a.log 2>&1 &
sleep 0.3; flock -n $E/fila.lock $F $E/fila || echo "outra fila já roda nesta pasta (saída $?)"; wait
echo "execuções: $(wc -l < $E_LOG) para 4 tarefas"
Exemplo do repositório
## 1) roda e é interrompida no meio
→ 01.md
  feito
→ 02.md
  feito
→ 03.md
rodando: 03.md · feito: 01.md 02.md 
## 2) roda de novo: retoma
entrada: 0 · feito: 4 · falhou: 0
execuções: 5 para 4 tarefas
## 3) duas filas na mesma pasta, ao mesmo tempo
execuções: 8 para 4 tarefas · repetidas: tarefa 1 tarefa 2 tarefa 3 tarefa 4 
## 4) a mesma coisa com flock
outra fila já roda nesta pasta (saída 1)
execuções: 4 para 4 tarefas

Rodado três vezes, mesmo resultado. Em 2, a tarefa 3 rodou duas vezes (interrompida e retomada): a tarefa tem de aguentar rodar de novo. Em 3, as quatro rodaram duas vezes. Em 4, a segunda cópia nem começou.

04Sessões que editam o mesmo arquivo: a guarda de colisão

O projeto de treino traz colisao.mjs, um hook que anota quem editou cada arquivo e pergunta antes de outra sessão editar. Aqui, só a detecção; hook como guarda é o curso 4.

Terminal · ensaio sem cota (duas sessões fingidas pelo session_id)
cd ~/treino-multi
export INEMA_RUNTIME_ESTADO=${TMPDIR:-/tmp}/ensaio-multi/colisao; rm -rf $INEMA_RUNTIME_ESTADO
G=runtime/mods/runtime-guarda/hooks/colisao.mjs
j() { printf '{"session_id":"%s","cwd":"%s","tool_input":{"file_path":"notas.md"}}' "$1" "$PWD"; }
echo "rascunho" > notas.md
j sessao-AAAAAAAA | node $G pos                      # a sessão A acabou de editar notas.md
echo "## A quer editar de novo"; j sessao-AAAAAAAA | node $G pre; echo "(saída $?)"
echo "## B quer editar o mesmo arquivo"; j sessao-BBBBBBBB | node $G pre; echo; echo "(saída $?)"
Exemplo do repositório
## A quer editar de novo
(saída 0)
## B quer editar o mesmo arquivo
{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"ask","permissionDecisionReason":"Guarda de colisão: Outra sessão (sessao-A) editou notas.md agora há pouco. Seguir mesmo assim, usar outra cópia (worktree) ou cancelar?"}}
(saída 0)

A mesma sessão passa calada. A outra recebe "permissionDecision":"ask": o Claude Code para e pergunta. A janela padrão é de 30 min (INEMA_COLISAO_MIN). INEMA_RUNTIME_ESTADO manda o registro para a pasta de ensaio, para não misturar com o seu real.

05Colisões que já aconteceram nesta máquina

Do LESSONS.md do projeto de monitoramento do INEMA, com data. Cada uma virou uma regra de uma linha.

1. Scratchpad

Cursos feitos em paralelo por subagentes dividiam a mesma pasta temporária. Pasta de imagens com nome genérico colidiu: o script de um agente pulou a imagem porque a arte do outro já existia.

Regra: pasta temporária com o id da tarefa no nome.

06Prática

Fila, colisão e guarda, sem gastar cota.

E12 · Interromper e retomar

10 min

Clone o jornada-agentes e rode as partes 1 e 2 do ensaio.

Pronto quando: aparecem rodando: 03.md · feito: 01.md 02.md e depois execuções: 5 para 4 tarefas.

E13 · Colisão e flock

10 min

Rode as partes 3 e 4. Depois escreva, numa linha do seu AGENTS.md ou CLAUDE.md, a regra de trava para os scripts de fila que você usa.

Pronto quando: a parte 3 imprime execuções: 8 para 4 tarefas; a parte 4 imprime outra fila já roda nesta pasta (saída 1) e execuções: 4 para 4 tarefas; grep -c flock AGENTS.md CLAUDE.md acha a sua regra.

E14 · Guarda de colisão

10 min

Rode o ensaio da guarda no projeto de treino.

Pronto quando: a sessão A sai sem texto e (saída 0); a sessão B imprime "permissionDecision":"ask" com Outra sessão (sessao-A) editou notas.md.

07Teste da aula

Pergunta 1 de 4

A fila caiu no meio da tarefa 3. Na retomada, quantas vezes a tarefa 3 terá rodado?competência

08Em três frases

Retomada repeteO que estava rodando volta para a entrada; cada tarefa tem de aguentar rodar de novo.
Uma fila por pastaSem trava, duas cópias executam tudo duas vezes; flock -n resolve com uma linha.
Sessões se cruzamA guarda pergunta antes de editar o que outra sessão mexeu; worktree evita a pergunta.

Para ir além

Aula anteriorPróxima aula