From f0b4eb9e2b5f405d367e91511f733001bb6dd0b1 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 27 May 2026 00:51:53 +0000 Subject: [PATCH] docs: automated weekly documentation synchronization [AI Agent] Co-authored-by: Jaime Basso --- CHANGELOG.md | 8 ++++++++ docs/INDEX.md | 2 +- docs/guides/event-driven.md | 22 +++++++++++++++++++++- docs/product/roadmap.md | 5 ++++- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e1fdd5..f8bb77b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 +## Week of 2026-05-27 + +### Fixed + +- `EventRouter` com `RetryPolicy::Exponential`: o atraso `base_delay * 2^n` usa `Duration::saturating_mul` e limita o expoente a 31, evitando panic por overflow de `Duration` em retentativas longas ou `base_delay` grande ([#13](https://github.com/JaimeJunr/serverust/pull/13)). +- `SqsBroker::handle_sqs_event` (Lambda ESM + `ReportBatchItemFailures`): mensagens sem handler para a fila do ARN ou sem `event_source_arn` válido entram em `batchItemFailures` quando há `messageId`, em vez de ack silencioso pela Lambda ([#12](https://github.com/JaimeJunr/serverust/pull/12)). + ## [Unreleased] ### Fixed +- `EventRouter` com `RetryPolicy::Exponential`: backoff exponencial entre tentativas usa `Duration::saturating_mul` com expoente limitado a 31 — evita panic quando `base_delay * 2^n` excede o máximo representável em `Duration`. - `SqsBroker::handle_sqs_event` (Lambda ESM + `ReportBatchItemFailures`): mensagens sem handler para a fila do ARN ou sem `event_source_arn` válido passam a entrar em `batchItemFailures` quando há `messageId`, em vez de serem tratadas como sucesso implícito (a Lambda removia da fila sem processamento). ## [0.3.0] - 2026-05-17 diff --git a/docs/INDEX.md b/docs/INDEX.md index 7adaa03..6933678 100644 --- a/docs/INDEX.md +++ b/docs/INDEX.md @@ -8,7 +8,7 @@ Ponto de entrada da documentação técnica. Comece pelo [README.md](../README.m - [**guides/lambda-tutorial.md**](guides/lambda-tutorial.md) — Tutorial completo: construir uma API de tarefas (CRUD com validação, OpenAPI, DI), rodar local e fazer **deploy em AWS Lambda**. Tempo: 30-45 min. - [**guides/iac-compatibility.md**](guides/iac-compatibility.md) — Contrato oficial de compatibilidade com Serverless Framework, SST, Terraform, SAM/CDK e como validamos isso em testes/CI. - [**guides/dynamodb.md**](guides/dynamodb.md) — Guia prático de DynamoDB: setup de deps, CRUD com `DynamoRepo` e `#[dynamo_table]`, credenciais (env vars, IAM role em Lambda), testes locais com DynamoDB Local e troubleshooting. -- [**guides/event-driven.md**](guides/event-driven.md) — Guia de event-driven com Kafka: `Broker` trait, `EventRouter`, macros `#[subscriber]`/`#[publisher]`, retry policies e detecção de runtime Lambda vs long-running. +- [**guides/event-driven.md**](guides/event-driven.md) — Guia event-driven (Kafka + SQS): `Broker` trait, `EventRouter`, `SqsBroker` (Lambda ESM), macros `#[subscriber]`/`#[publisher]`, retry policies e detecção de runtime Lambda vs long-running. ## Produto diff --git a/docs/guides/event-driven.md b/docs/guides/event-driven.md index 892c6b5..b24d813 100644 --- a/docs/guides/event-driven.md +++ b/docs/guides/event-driven.md @@ -1,6 +1,6 @@ # Guia de Uso: Event-Driven com serverust-events -Este guia cobre as APIs event-driven do `serverust-events` introduzidas no v0.2.0, com exemplos de US-1 a US-7. +Este guia cobre as APIs event-driven do `serverust-events` (v0.2.0 Kafka; v0.3.0 SQS), com exemplos de US-1 a US-7 e notas operacionais de SQS Lambda ESM. ## Conceitos centrais @@ -12,6 +12,7 @@ Este guia cobre as APIs event-driven do `serverust-events` introduzidas no v0.2. | `#[publisher]` | macro | Empilhado em `#[subscriber]`, publica o valor de retorno | | `LambdaBroker` | struct | Broker sink-only para modo AWS Lambda | | `KafkaBroker` | struct (feat `kafka`) | Broker bidirecional via rust-rdkafka | +| `SqsBroker` | struct (feat `sqs`) | Broker sink-only para SQS em Lambda ESM (`handle_sqs_event`) | | `InMemoryBroker` | struct (feat `in-memory`) | Broker em memória para testes | --- @@ -141,6 +142,8 @@ RetryPolicy::immediate(3) RetryPolicy::exponential(3, Duration::from_secs(1)) ``` +Com `RetryPolicy::Exponential`, o `EventRouter` calcula o atraso como `base_delay.saturating_mul(2^n)` com `n` limitado a 31. Valores que excederiam o máximo de `Duration` saturam em `Duration::MAX` em vez de panicar (regressão coberta em `router.rs`). + Encadeie na subscrição: ```rust @@ -227,6 +230,23 @@ match Runtime::detect() { --- +## SQS Lambda ESM — `SqsBroker` e partial batch failure + +Com a feature `sqs`, `SqsBroker` despacha registros de `SqsEvent` por nome de fila (último segmento do `event_source_arn`). A resposta deve incluir `batchItemFailures` para mensagens que falharam ou não puderam ser despachadas — caso contrário a Lambda as remove como sucesso. + +Comportamento atual (`handle_sqs_event`): + +| Situação | Resultado | +|---|---| +| Handler inscrito e `Ok(())` | Mensagem não entra em `batchItemFailures` (ack implícito) | +| Handler retorna erro | `messageId` em `batchItemFailures` | +| Sem handler para a fila do ARN | `messageId` em `batchItemFailures` (quando presente) | +| `event_source_arn` ausente ou não parseável | `messageId` em `batchItemFailures` (quando presente) | + +Routing: use o mesmo nome de fila em `EventRouter::subscribe` / `#[subscriber(driver = "sqs", queue = "...")]` que o segmento final do ARN da fila no event source mapping. + +--- + ## Exemplo completo: kafka-wallet Veja [`examples/kafka-wallet/`](../../examples/kafka-wallet/) para o exemplo end-to-end diff --git a/docs/product/roadmap.md b/docs/product/roadmap.md index e1910b9..7eb9b49 100644 --- a/docs/product/roadmap.md +++ b/docs/product/roadmap.md @@ -76,7 +76,10 @@ Sugestões da review automática (Claude Code Action) agendadas para release de - **Structured logging completo**: padronizar `tracing::warn!` para `tracing::error!` quando o evento é falha de invariante. Campos consistentes: `queue`, `message_id`, `attempt`, `error`. - **Schema validation pós-deserialização**: validar campos obrigatórios em `Json` extractor e em `SqsMetadata::from_message`. - **Graceful degradation**: contador `idempotency_bypass_total` quando `message_id` vazio; validação básica de formato em `receipt_handle` antes do heartbeat. -- **Overflow protection no backoff**: trocar `config.base_backoff * 2u32.pow(attempt - 1)` por `saturating_pow` + `max_backoff: Duration` configurável (default 30s). +- **Overflow protection no backoff**: + - ✅ `EventRouter` (`RetryPolicy::Exponential`): `saturating_mul` + expoente cap 31 ([#13](https://github.com/JaimeJunr/serverust/pull/13), 2026-05-25). + - Pendente: `max_backoff: Duration` configurável (default 30s) em `SqsProducer`, `DeleteManager` e fila vazia do `StandaloneSqsBroker` (ainda usam `base_backoff * 2u32.pow(...)`). +- **Partial batch sem ack silencioso**: ✅ registros sem handler ou ARN inválido entram em `batchItemFailures` quando há `messageId` ([#12](https://github.com/JaimeJunr/serverust/pull/12), 2026-05-20). - **Métricas EMF operacionais**: `idempotency_bypass_total`, `metadata_serialize_failures_total`, `heartbeat_invalid_receipt_total`. - **Circuit breaker no `StandaloneSqsBroker`**: trip após N falhas consecutivas de `ReceiveMessage` para evitar storm em incidente AWS.