> ## Documentation Index
> Fetch the complete documentation index at: https://lifters.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Runbook: Reprocessamento de DLQ

> Procedimento para detectar, inspecionar e reprocessar mensagens na Dead-Letter Queue do pipeline de eventos Atlas.

# Runbook: Reprocessamento de DLQ

**Serviço afetado:** `events/` — pipeline Kafka
**Alerta relacionado:** `atlas_dlq_messages_total > 0`
**Impacto:** Eventos não ingeridos → métricas analíticas desatualizadas

***

## 1. Detectar

O alerta `atlas_dlq_messages_total > 0` dispara quando qualquer mensagem é enviada ao topic `atlas.events.dlq`.

Para verificar manualmente:

```bash theme={null}
# Verificar lag no topic DLQ
kafka-consumer-groups.sh \
  --bootstrap-server $KAFKA_BOOTSTRAP \
  --describe \
  --group atlas-events-dlq-inspector

# Contar mensagens pendentes
kafka-run-class.sh kafka.tools.GetOffsetShell \
  --broker-list $KAFKA_BOOTSTRAP \
  --topic atlas.events.dlq \
  --time -1
```

Se o offset máximo for maior que 0, há mensagens na DLQ.

***

## 2. Inspecionar

Ler as últimas mensagens da DLQ sem confirmar offset (modo dry-run):

```bash theme={null}
kafka-console-consumer.sh \
  --bootstrap-server $KAFKA_BOOTSTRAP \
  --topic atlas.events.dlq \
  --from-beginning \
  --max-messages 20 \
  --property print.key=true \
  --property key.separator=" | "
```

Cada mensagem tem o seguinte formato:

```json theme={null}
{
  "original_topic": "atlas.events.raw.sportsbook",
  "original_key": "org-123/brand-abc",
  "payload": { "...evento original..." },
  "error": "timeout publishing to Kafka after 3 retries",
  "failed_at": "2026-03-26T14:30:00Z",
  "retry_count": 3
}
```

**Categorias de erro comuns:**

| Erro                   | Causa                               | Ação                                               |
| ---------------------- | ----------------------------------- | -------------------------------------------------- |
| `timeout publishing`   | Kafka broker lento ou indisponível  | Verificar saúde do cluster Kafka                   |
| `message too large`    | Payload acima do limite do produtor | Investigar evento malformado no campo `payload`    |
| `unknown topic`        | Topic destino não existe            | Verificar criação de topics via `data/` migrations |
| `authorization failed` | ACL do produtor revogada            | Verificar credenciais do serviço `events/`         |

***

## 3. Reprocessar

### 3a. Reprocessamento automático via script

O serviço `events/` expõe um endpoint interno para reprocessar a DLQ:

```bash theme={null}
# Reprocessar todas as mensagens pendentes (máx. 1000 por chamada)
curl -X POST http://events-internal:8081/internal/dlq/reprocess \
  -H "Authorization: Bearer $INTERNAL_TOKEN" \
  -d '{"max_messages": 1000, "dry_run": false}'
```

Parâmetros:

| Campo          | Tipo | Descrição                                        |
| -------------- | ---- | ------------------------------------------------ |
| `max_messages` | int  | Limite de mensagens por chamada (padrão: 100)    |
| `dry_run`      | bool | Se `true`, simula sem publicar (padrão: `false`) |

Resposta esperada:

```json theme={null}
{
  "processed": 42,
  "failed": 0,
  "skipped": 0
}
```

### 3b. Reprocessamento manual via kafka-console-producer

Para casos onde o endpoint automático não está disponível:

```bash theme={null}
# 1. Exportar mensagens DLQ para arquivo
kafka-console-consumer.sh \
  --bootstrap-server $KAFKA_BOOTSTRAP \
  --topic atlas.events.dlq \
  --from-beginning \
  --timeout-ms 5000 \
  > /tmp/dlq-messages.jsonl

# 2. Extrair apenas os payloads originais e publicar no topic correto
cat /tmp/dlq-messages.jsonl | jq -r '"\(.original_key)\t\(.payload | tojson)"' | \
  kafka-console-producer.sh \
  --bootstrap-server $KAFKA_BOOTSTRAP \
  --topic atlas.events.raw.sportsbook \
  --property parse.key=true \
  --property key.separator=$'\t'
```

> **Atenção:** Substitua `atlas.events.raw.sportsbook` pelo topic correto conforme o campo `original_topic` de cada mensagem.

***

## 4. Verificar Integridade

Após o reprocessamento, confirmar que:

### 4a. DLQ zerada

```bash theme={null}
kafka-run-class.sh kafka.tools.GetOffsetShell \
  --broker-list $KAFKA_BOOTSTRAP \
  --topic atlas.events.dlq \
  --time -1
# Deve retornar offset igual ao offset antes do reprocessamento
```

### 4b. Eventos chegaram ao ClickHouse

```sql theme={null}
-- Verificar que eventos das últimas 2 horas existem nas tabelas Gold
SELECT
    toStartOfMinute(event_time) AS minute,
    count() AS events
FROM gold_sport_ggr_by_day
WHERE event_date >= today() - 1
GROUP BY minute
ORDER BY minute DESC
LIMIT 10;
```

### 4c. Métricas analíticas atualizadas

Acessar o dashboard de um operador afetado e verificar que os KPIs refletem os eventos reprocessados.

### 4d. Confirmar offset da DLQ

Após verificar integridade, confirmar o offset do grupo consumidor da DLQ para evitar reprocessamento duplo:

```bash theme={null}
kafka-consumer-groups.sh \
  --bootstrap-server $KAFKA_BOOTSTRAP \
  --group atlas-events-dlq-inspector \
  --reset-offsets \
  --to-latest \
  --topic atlas.events.dlq \
  --execute
```

***

## 5. Escalar se necessário

Se o reprocessamento falhar repetidamente para as mesmas mensagens:

1. **Isolar as mensagens problemáticas:** mover para um topic `atlas.events.dlq.poison` para análise sem bloquear o reprocessamento.
2. **Abrir ticket no Linear** com as mensagens exportadas e o erro observado.
3. **Notificar o time de dados** se o volume de DLQ ultrapassar 10.000 mensagens — pode indicar problema sistêmico no pipeline.

***

## Referências

* Configuração do Kafka producer: `events/internal/kafka/producer.go`
* Topics e ACLs: `data/migrations/kafka/`
* Alertas de observabilidade: `infra/terraform/staging/monitoring.tf`
* Regras de alerta relacionadas: `atlas_dlq_messages_total`, `atlas_pipeline_gold_stale_minutes`
