Em uma avaliação em lote, uma resposta mudou case_id de gold-pair-078 para gold-pair-079. O identificador de tarefa continuava apontando ao caso original. Estes campos foram reconstruídos do registro de falha:
task_id: gold-pair-078::gold-pair-078-candidate-127
candidate_id: gold-pair-078-candidate-127
case_id: gold-pair-079
A resposta pertencia a um lote de 20 candidatos. O JSON era analisável e passou pela validação estrutural. A conferência individual detectou o erro depois, mas o recibo já dizia status: ok. Registro original e localização do código
O resultado não formou uma avaliação formal completa, mas deixou um risco de recuperação: o “sucesso” antigo contradizia o registro posterior de falha. Um recuperador que importasse apenas pelos recibos de sucesso aceitaria o lote novamente.
A correção era clara. O sucesso deve ser gravado depois da verificação de identidade de todos os itens. O chamador já sabe a que tarefa pertence a solicitação. O programa deve comparar esse fato, sem deixar a garantia por conta do modelo.
Validar o lote inteiro antes de registrar sucesso
Um Schema limitado a tipos e estrutura aceita duas strings diferentes como válidas. Um Schema dinâmico pode restringir também os valores de identidade; neste sistema, a resposta é ainda comparada diretamente com a solicitação efetiva para aceitar o lote.
A implementação atual verifica, em ordem, o case_id superior, cobertura de tarefas, estrutura e identidade de cada item. A cobertura compara quantidade e conjunto para encontrar ausências, duplicações e tarefas extras. A identidade confere task_id, case_id, candidate_id e tipo de candidato.
O trecho abaixo simplifica a ordem central para ensino. A implementação de produção inclui Schemas de fase, recibos e tratamento de retentativas.
expected = {task["task_id"]: task for task in requests}
if len(expected) != len(requests):
raise InvalidBatch("请求自身包含重复任务")
ids = [item["task_id"] for item in response["items"]]
if len(ids) != len(expected) or set(ids) != set(expected):
raise InvalidBatch("任务缺失、重复或新增")
for item in response["items"]:
task = expected[item["task_id"]]
for key in ("task_id", "case_id", "candidate_id"):
if item[key] != task[key]:
raise InvalidBatch(f"身份字段不一致:{key}")
commit_success(response)
Associar por identificador permite mudar a ordem das respostas. Conferir campos redundantes impede que consumidores diferentes atribuam o mesmo objeto a tarefas distintas: um encontra 078 por task_id, outro agrupa em 079 por case_id.
O programa não simplesmente corrigiu 079 para 078. O desalinhamento não revela se o modelo copiou o número errado ou entendeu outra pergunta. Rejeitar o lote e preservar a resposta mantém a chance de investigar ambos.
A aceitação integral tem custo: os outros 19 itens aparentemente normais também não são reutilizados. Em troca, a fronteira de confirmação é simples. Aceitação parcial exigiria validar cada item independentemente, completar ausências e tratar confirmações duplicadas: outro desenho de recuperação.
Revalidar os antigos arquivos de sucesso
Após corrigir chamadas novas, os recibos históricos continuavam lá. Por isso, a importação confere cada item novamente. Ao encontrar a identidade errada associada ao log antigo, guarda o lote como diagnóstico e não inclui nenhum item no checkpoint reutilizável.
Os custos de chamadas já feitas continuam contabilizados. Reiniciar pode trocar o diretório de execução, mas não apagar tentativas anteriores. Caso contrário, o “custo por resultado utilizável” incluiria só o último trecho bem-sucedido.
O tamanho do lote deve considerar esse custo total. Lotes grandes diluem entradas comuns; repetir o lote amplia o efeito de um erro individual. Mais tarde, o projeto permitiu divisão determinística apenas para lotes específicos que já esgotaram retentativas, mantendo a possibilidade de uma falha individual encerrar a execução. Divisão é recuperação limitada, não justificativa para repetir sem fim.
A regressão corrompe intencionalmente a identidade de um item na primeira resposta e verifica três coisas: a tentativa grava recibo de falha, o caminho de checkpoint de sucesso fica vazio e só a resposta correta seguinte grava sucesso. Testa exatamente a abertura atravessada pelo defeito.
A contagem de lotes concluídos deve crescer daqui em diante: resposta e solicitação conferem, a aceitação do lote terminou e somente então o sucesso é confirmado.