Dominando o Tratamento de Erros e Retentativas da API Didit em Go (PT-BR)
Construir integrações robustas com a API Didit em Go exige estratégias sofisticadas de tratamento de erros e retentativas. Este guia explora as melhores práticas, desde a compreensão dos limites de taxa e códigos de erro.

Entenda os Limites de Taxa da DiditImplemente limitação do lado do cliente e backoff exponencial para respostas 429, utilizando os cabeçalhos
X-RateLimit-Limit,X-RateLimit-RemainingeX-RateLimit-Resetpara evitar interrupções do serviço.Diferencie os Tipos de ErroDistinga entre erros transitórios (por exemplo, problemas de rede, indisponibilidade do serviço) e erros permanentes (por exemplo, chaves de API inválidas, requisições malformadas) para aplicar lógica de retentativa apropriada ou falhar rapidamente.
Implemente Mecanismos de Retentativa RobustosEmpregue loops de retentativa estruturados com backoff exponencial, jitter e um número máximo de tentativas para lidar com falhas transitórias de forma elegante, melhorando a confiabilidade de operações críticas como a criação de sessão.
A Abordagem Developer-First da Didit Simplifica a IntegraçãoA Didit oferece documentação clara da API, cabeçalhos específicos de limite de taxa e uma arquitetura modular, permitindo que desenvolvedores Go construam fluxos de verificação de identidade resilientes com facilidade e confiança.
Integrar APIs de terceiros é um pilar fundamental no desenvolvimento de aplicações modernas, e a verificação de identidade não é exceção. Ao trabalhar com serviços críticos como a plataforma de identidade da Didit, garantir que sua integração seja resiliente a flutuações de rede, problemas de serviço e limites de taxa é primordial. Este guia aborda estratégias avançadas de tratamento de erros e retentativas especificamente adaptadas para integrações da API Didit usando Go, ajudando você a construir sistemas robustos e confiáveis.
Compreendendo o Cenário de Erros da API Didit
Antes de implementar qualquer lógica de retentativa, é crucial entender os tipos de erros que você pode encontrar. A API da Didit, como muitos serviços bem projetados, comunica vários estados por meio de códigos de status HTTP. Embora os códigos 2xx padrão indiquem sucesso, você se concentrará principalmente nos 4xx (erros do cliente) e 5xx (erros do servidor), e especialmente no 429 (Too Many Requests).
Limitação de Taxa da Didit e o que Isso Significa para Você
A Didit impõe limitação de taxa para manter a estabilidade da API. Este é um aspecto crítico a ser gerenciado em sua integração. Por exemplo, os endpoints GET geralmente têm um limite global de 300 requisições por minuto por aplicação, com endpoints específicos como session-decision (100 rpm) ou session-v2-create (600 rpm) tendo seus próprios limites, potencialmente mais rigorosos. Quando você atinge um limite de taxa, a Didit responde com um código de status 429 Too Many Requests e inclui cabeçalhos úteis:
X-RateLimit-Limit: O número máximo de requisições permitidas na janela atual.X-RateLimit-Remaining: O número de requisições restantes na janela atual.X-RateLimit-Reset: O tempo (em segundos epoch) quando a janela atual de limite de taxa é redefinida.Retry-After: (Geralmente incluído) O número de segundos a aguardar antes de fazer outra requisição.
Seu cliente Go deve monitorar ativamente esses cabeçalhos. Quando X-RateLimit-Remaining cair abaixo de um certo limite (por exemplo, 15% de X-RateLimit-Limit), você deve limitar proativamente suas requisições. Ignorar isso pode levar a erros 429 sustentados, afetando a capacidade de sua aplicação de criar sessões de verificação ou recuperar resultados de produtos como ID Verification ou AML Screening da Didit.
Implementando Estratégias de Retentativa Robustas com Backoff Exponencial em Go
Para erros transitórios (por exemplo, timeouts de rede, indisponibilidade temporária do serviço ou 429s), as retentativas são essenciais. No entanto, retentativas ingênuas podem exacerbar os problemas. O padrão ouro é o backoff exponencial com jitter.
Backoff Exponencial com Jitter
Backoff exponencial significa aumentar o tempo de espera entre as retentativas exponencialmente. Jitter (adicionar um pequeno atraso aleatório) evita um problema de 'thundering herd', onde muitos clientes tentam novamente simultaneamente após uma interrupção, sobrecarregando o serviço novamente. Aqui está um exemplo conceitual em Go:
package main
import (
"fmt"
"io/ioutil"
"net/http"
"time"
"math/rand"
)
func callDiditAPIWithRetry(url string, maxRetries int) ([]byte, error) {
client := &http.Client{Timeout: 10 * time.Second}
rand.Seed(time.Now().UnixNano())
for i := 0; i <= maxRetries; i++ {
resp, err := client.Get(url)
if err != nil {
// Lida com erros de rede (por exemplo, conexão recusada, timeout)
fmt.Printf("Tentativa %d: Erro de rede: %v\n", i+1, err)
if i == maxRetries {
return nil, fmt.Errorf("falhou após %d retentativas: %w", maxRetries, err)
}
sleepTime := time.Duration(1<<i)*time.Second + time.Duration(rand.Intn(1000))*time.Millisecond // Backoff exponencial + jitter
fmt.Printf("Tentando novamente em %v...\n", sleepTime)
time.Sleep(sleepTime)
continue
}
defer resp.Body.Close()
switch resp.StatusCode {
case http.StatusOK:
fmt.Printf("Tentativa %d: Sucesso!\n", i+1)
return ioutil.ReadAll(resp.Body)
case http.StatusTooManyRequests:
// Respeita o cabeçalho Retry-After se presente
retryAfter := resp.Header.Get("Retry-After")
if retryAfter != "" {
if sleepSeconds, err := time.ParseDuration(retryAfter + "s"); err == nil {
fmt.Printf("Tentativa %d: Limite de taxa atingido. Tentando novamente após %v.\n", i+1, sleepSeconds)
time.Sleep(sleepSeconds)
continue
}
}
// Fallback para backoff exponencial se Retry-After estiver ausente ou inválido
fmt.Printf("Tentativa %d: Limite de taxa atingido (429).\n", i+1)
if i == maxRetries {
return nil, fmt.Errorf("limite de taxa atingido após %d retentativas", maxRetries)
}
sleepTime := time.Duration(1<<i)*time.Second + time.Duration(rand.Intn(1000))*time.Millisecond
fmt.Printf("Tentando novamente em %v...\n", sleepTime)
time.Sleep(sleepTime)
continue
case http.StatusInternalServerError, http.StatusBadGateway, http.StatusServiceUnavailable, http.StatusGatewayTimeout:
// Erros do lado do servidor que podem ser transitórios
fmt.Printf("Tentativa %d: Erro do servidor %d. Tentando novamente.\n", i+1, resp.StatusCode)
if i == maxRetries {
return nil, fmt.Errorf("erro do servidor %d após %d retentativas", resp.StatusCode, maxRetries)
}
sleepTime := time.Duration(1<<i)*time.Second + time.Duration(rand.Intn(1000))*time.Millisecond
fmt.Printf("Tentando novamente em %v...\n", sleepTime)
time.Sleep(sleepTime)
continue
default:
// Erros não retentáveis (erros de cliente 4xx, etc.)
body, _ := ioutil.ReadAll(resp.Body)
return nil, fmt.Errorf("erro de API não retentável: %d %s, response: %s", resp.StatusCode, resp.Status, string(body))
}
}
return nil, fmt.Errorf("fluxo de controle inesperado") // Não deve ser alcançado
}
func main() {
// Exemplo de uso: Substitua pelo endpoint real da API Didit
// Para uma integração real, você estaria POSTando para /v3/session/ ou similar
// e manipulando a verification_url.
apiURL := "https://verification.didit.me/health"
data, err := callDiditAPIWithRetry(apiURL, 5)
if err != nil {
fmt.Println("Falha ao chamar a API:", err)
} else {
fmt.Println("Resposta da API:", string(data))
}
}
Este trecho demonstra como lidar com erros de rede, 429s (respeitando Retry-After) e erros 5xx comuns com backoff exponencial e jitter. Ele também mostra como falhar rapidamente para erros 4xx não retentáveis, que geralmente são devido a entrada incorreta e não serão resolvidos com a retentativa. Isso é crucial para operações como a criação de uma sessão de verificação usando a arquitetura modular da Didit.
Implementando um Padrão de Circuit Breaker
Embora as retentativas ajudem com problemas transitórios, tentar novamente continuamente um serviço com falha pode sobrecarregá-lo ainda mais ou desperdiçar recursos se o serviço estiver realmente inativo. É aqui que entra o padrão circuit breaker. Um circuit breaker monitora falhas e, se elas atingirem um certo limite, 'abre' o circuito, impedindo mais requisições por um período definido. Após o período, ele permite algumas requisições de teste para ver se o serviço se recuperou.
Em Go, você pode usar bibliotecas como sony/gobreaker para implementar este padrão:
package main
import (
"errors"
"fmt"
"io/ioutil"
"net/http"
"time"
"github.com/sony/gobreaker"
)
var cb *gobreaker.CircuitBreaker
func init() {
st := gobreaker.Settings{
Name: "DiditAPICircuitBreaker",
MaxRequests: 3, // Permite 3 requisições em estado semiaberto
Interval: 5 * time.Second, // Período para coletar dados para decisões de viagem
Timeout: 10 * time.Second, // Abre o circuito por 10 segundos
ReadyToTrip: func(counts gobreaker.Counts) bool {
return counts.ConsecutiveFailures > 5 // Dispara após 5 falhas consecutivas
},
OnStateChange: func(name string, from gobreaker.State, to gobreaker.State) {
fmt.Printf("Circuit Breaker '%s' mudou de %s para %s\n", name, from, to)
},
}
cb = gobreaker.NewCircuitBreaker(st)
}
func callDiditAPIWithCircuitBreaker(url string) ([]byte, error) {
body, err := cb.Execute(func() (interface{}, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err // Erro de rede
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
// Apenas conta 5xx e 429 como falhas para o circuit breaker
if resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= http.StatusInternalServerError {
return nil, fmt.Errorf("API retornou status %d", resp.StatusCode)
}
// Para outros erros 4xx, podemos não querer disparar o breaker, mas ainda retornar um erro
bodyBytes, _ := ioutil.ReadAll(resp.Body)
return nil, fmt.Errorf("erro de API não retentável: %d %s, response: %s", resp.StatusCode, resp.Status, string(bodyBytes))
}
return ioutil.ReadAll(resp.Body)
})
if err != nil {
if errors.Is(err, gobreaker.ErrOpenState) {
return nil, fmt.Errorf("circuit breaker está aberto: %w", err)
}
return nil, err
}
return body.([]byte), nil
}
func main() {
// Exemplo de uso
apiURL := "https://verification.didit.me/health"
for i := 0; i < 10; i++ {
data, err := callDiditAPIWithCircuitBreaker(apiURL)
if err != nil {
fmt.Printf("Chamada %d falhou: %v\n", i+1, err)
} else {
fmt.Printf("Chamada %d bem-sucedida: %s\n", i+1, string(data))
}
time.Sleep(1 * time.Second)
}
}
A combinação de circuit breakers com backoff exponencial garante que sua aplicação permaneça responsiva e não sobrecarregue um serviço externo com dificuldades. Isso é particularmente importante ao lidar com requisições de verificação de identidade de alto volume, como as que envolvem a Verificação de ID da Didit ou as verificações de Liveness Passiva e Ativa.
Lidando com Falhas de Webhook e Resultados Assíncronos
A API da Didit frequentemente fornece resultados assincronamente via webhooks, por exemplo, depois que um usuário completa um fluxo de verificação de ID ou quando uma verificação de AML Screening é concluída. Seu endpoint de webhook deve ser robusto. Se seu endpoint falhar ao processar um webhook (por exemplo, retornar um código de status 5xx), a Didit tentará novamente entregar o webhook. É crucial:
- Confirmar o Recebimento Imediatamente: Retorne um código de status 2xx o mais rápido possível para sinalizar o recebimento bem-sucedido, mesmo que o processamento demore mais.
- Processar Assincronamente: Entregue o payload do webhook a um worker em segundo plano ou a uma fila de mensagens (por exemplo, Kafka, RabbitMQ) para processamento. Isso evita que seu endpoint de webhook expire as retentativas da Didit.
- Idempotência: Garanta que sua lógica de processamento de webhook seja idempotente. Se a Didit tentar novamente e entregar o mesmo webhook várias vezes, seu sistema deve processá-lo apenas uma vez para evitar ações duplicadas ou inconsistências de dados.
- Verificar Assinaturas: Sempre verifique a assinatura do webhook usando sua
Webhook Secret Keydo Console Didit para garantir que a requisição realmente se originou da Didit e não foi adulterada.
Como a Didit Ajuda
A Didit foi projetada com a experiência do desenvolvedor e a confiabilidade em mente, oferecendo recursos que simplificam inerentemente o tratamento avançado de erros e as estratégias de retentativa para suas integrações Go. Nossa abordagem developer-first significa documentação de API clara e abrangente, um sandbox instantâneo e APIs limpas que tornam a integração direta.
- Limitação de Taxa Previsível: A Didit define claramente limites de taxa globais e específicos de endpoint, juntamente com cabeçalhos HTTP padrão (
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset,Retry-After) para guiar sua lógica de limitação e backoff do lado do cliente. Essa transparência permite que você construa mecanismos de retentativa otimizados para serviços como Verificação de ID e AML Screening. - Arquitetura Modular: Nossas primitivas de identidade modulares significam que você pode construir fluxos de trabalho resilientes por design. Se uma verificação específica (por exemplo, Comprovante de Endereço) encontrar um problema transitório, seu fluxo de trabalho geral pode ser configurado para se adaptar ou tentar novamente componentes específicos sem impactar etapas de verificação não relacionadas.
- Confiabilidade Nativas de IA: O backend nativo de IA da Didit é construído para escala e resiliência, minimizando os erros do lado do servidor que você encontrará. Isso permite que você concentre seu tratamento de erros em problemas de rede e do lado do cliente, em vez de interrupções constantes do serviço.
- KYC Core Gratuito e Preços Flexíveis: Comece com o nível gratuito da Didit para KYC Core, permitindo que você teste completamente seu tratamento de erros e estratégias de retentativa em um ambiente de produção sem custos iniciais. Nosso modelo de pagamento por verificação bem-sucedida alinha ainda mais nosso sucesso com o seu.
Pronto para Começar?
Pronto para ver a Didit em ação? Obtenha uma demonstração gratuita hoje.
Comece a verificar identidades gratuitamente com o nível gratuito da Didit.