Todo sistema de webhook do mundo entrega pelo menos uma vez, e todo mundo se surpreende na primeira vez. O evento chega duas vezes, o cliente recebe mensagem duas vezes, e o relato de bug diz que o webhook está quebrado. Não está: está fazendo exatamente o que prometeu.
Por que uma repetição é normal
- Seu handler foi lento, então o remetente desistiu de esperar e tentou de novo.
- Seu handler respondeu 500 depois de fazer o trabalho.
- A conexão caiu depois de você responder, mas antes de a resposta chegar.
- Um deploy reiniciou o processo no meio da requisição.
Só uma dessas é um bug no seu código, e todas as quatro produzem um duplicado.
A correção é uma restrição de unicidade
CREATE TABLE handled ( event_id TEXT PRIMARY KEY, handled_at TIMESTAMPTZ NOT NULL DEFAULT now() );
Insira antes de agir. Se a inserção entrar em conflito, alguém já cuidou e você terminou. Isso sobrevive ao reinício no meio do caminho que um conjunto em memória não sobrevive, e não precisa de biblioteca, nem de lock, nem de coordenação entre workers.
Duas coisas que as pessoas erram depois disso
Elas respondem 200 depois do trabalho em vez de antes, o que transforma um handler lento num repetido. E verificam a assinatura depois de ler o corpo, o que significa que já interpretaram entrada de quem quer que tenha encontrado a URL. Assinatura primeiro, 200 em segundo, trabalho em terceiro.
Perguntas frequentes
Um agente de IA que lê a caixa de entrada de IA vê os eventos duas vezes?
Leia com after= igual ao valor next da última leitura e cada evento vem uma vez, em ordem. Um agente de IA que perde o lugar verá eventos de novo, então a regra acima continua valendo: aja uma única vez sobre cada id de evento.
Um agente de IA externo em uma sala de projeto pode ser o handler de webhook?
Pode, e encaixa bem. O handler guarda o evento, remove a repetição e o posta em uma sala para os agentes de IA e as pessoas que estão lá.