diff --git a/README.md b/README.md index 1f77926..c85bb7e 100644 --- a/README.md +++ b/README.md @@ -1,133 +1,167 @@ -# Payment API +# payment-api -API de pagamentos Pix em Java + Spring Boot com Clean Architecture, Kafka (KRaft), Postgres, Prometheus, Grafana e Jaeger. +Fundação de um core de pagamentos Pix em Java — infraestrutura, observabilidade e pipeline CI/CD prontos; domínio em construção. -**Documentação de arquitetura:** -- [docs/architecture.md](docs/architecture.md) — domínio, fluxos, API, pacotes, idempotência -- [docs/devops-flow.md](docs/devops-flow.md) — pipeline CI/CD + observabilidade (Mermaid) +[![CI](https://github.com/lmoraesdev/java-payment-hexagonal/actions/workflows/ci.yml/badge.svg)](https://github.com/lmoraesdev/java-payment-hexagonal/actions/workflows/ci.yml) +![Java](https://img.shields.io/badge/Java-21-blue?logo=openjdk&logoColor=white) +![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.5.3-6DB33F?logo=springboot&logoColor=white) + +## Status + +A plataforma está completa: serviços sobem, métricas chegam no Grafana, traces no Jaeger, testes de integração passam com Testcontainers. O que ainda não existe é o domínio de negócio — entidades, casos de uso, portas e adapters de persistência/mensageria. Esses são os próximos passos (ver [Roadmap](#roadmap)). ## Stack -| Camada | Tecnologia | -|---|---| -| Runtime | Java 21 LTS | -| Framework | Spring Boot 3.5.3 | -| Messaging | Kafka 3.9 (KRaft — sem Zookeeper) | -| Persistence | PostgreSQL 18 | -| Métricas | Actuator + Micrometer + Prometheus + Grafana | -| Tracing | Micrometer Tracing + OpenTelemetry → Jaeger | -| Cache | Redis 7 (pré-instalado, profile `cache`) | -| Testes | JUnit 5 + Testcontainers | -| Qualidade | Spotless (GJF AOSP) + Checkstyle | - -## Quickstart +| Tecnologia | Versão | Para quê | +|---|---|---| +| Java | 21 LTS | Runtime | +| Spring Boot | 3.5.3 | Framework web, DI, auto-configuração | +| PostgreSQL | 18 | Persistência principal | +| Kafka (KRaft) | 3.9 | Event streaming — sem Zookeeper | +| Redis | 7 | Cache / idempotência (pré-instalado, profile `cache`) | +| Prometheus + Grafana | latest | Métricas + dashboard Payment Overview pré-provisionado | +| Jaeger + OpenTelemetry | latest | Distributed tracing via OTLP HTTP | +| Testcontainers | 1.21 | Testes de integração com banco real | +| Spotless (GJF AOSP) | 2.43 | Formatação automática de código | +| Checkstyle | 3.5 | Verificação de estilo | + +## Arquitetura + +O projeto segue Arquitetura Hexagonal (Ports & Adapters): o domínio não conhece Spring, JPA nem Kafka. Frameworks e infraestrutura ficam nas bordas; a lógica de negócio fica isolada e testável sem container. + +Decisões de projeto: +- **Observabilidade desde o início** — Prometheus, Grafana e Jaeger estão na infra antes do primeiro use case existir. Métricas e traces não são afterthought. +- **Logging estruturado 5W1H** — cada log emite JSON com `where`, `why`, `when`, `who`, `what`, `how` + `traceId`/`spanId` injetados automaticamente pelo Micrometer MDC. Facilita correlação em produção. +- **Event-driven preparado** — Kafka configurado com KRaft (sem Zookeeper), consumer/producer prontos no `application.yml`. Nenhum evento publicado ainda. + +``` +com.lmoraesdev.payment +├── adapter +│ ├── in.web ← PingController, GlobalExceptionHandler +│ └── out +│ ├── messaging ← (roadmap — Kafka producers) +│ └── persistence ← (roadmap — JPA repositories) +├── application +│ ├── port.in ← (roadmap — interfaces de entrada) +│ ├── port.out ← (roadmap — interfaces de saída) +│ └── usecase ← (roadmap — casos de uso) +├── config +│ └── logging ← Log5w1h, Logger5w1hBuilder +└── domain + ├── event ← (roadmap — domain events) + ├── exception ← DomainException (base abstrata com código de erro) + └── model ← (roadmap — entidades e value objects) +``` + +Especificação do domínio planejado (Charge Pix, máquina de estados, Money, idempotência): [`docs/architecture.md`](docs/architecture.md). + +## Como rodar + +**Pré-requisitos:** Docker Desktop com WSL2 integration habilitada; contexto Docker configurado para `default` (`docker context use default`). ```bash # 1. Variáveis de ambiente cp .env.example .env -# 2. Subir toda a infra + app +# 2. Subir infra + app (sem Redis) make up +# equivalente: docker compose up -d --build -# 3. Status +# 3. Subir com Redis (profile cache) +docker compose --profile cache up -d --build + +# 4. Verificar status docker compose ps ``` -| URL | Descrição | -|---|---| -| `GET /ping` | Smoke test | -| `GET /actuator/health` | Health probe | -| `GET /actuator/prometheus` | Métricas Prometheus | -| http://localhost:8090 | Kafka UI | -| http://localhost:9090 | Prometheus | -| http://localhost:3000 | Grafana — Payment Overview | -| http://localhost:16686 | Jaeger — traces | +## Endpoints e observabilidade -## Subir Redis (opcional) +| URL | O que se vê | +|---|---| +| `http://localhost:8080/ping` | `{"status":"pong"}` — smoke test | +| `http://localhost:8080/actuator/health` | Status do app, banco e dependências | +| `http://localhost:8080/actuator/prometheus` | Métricas no formato Prometheus | +| `http://localhost:8090` | Kafka UI — tópicos, consumer groups, mensagens | +| `http://localhost:9090` | Prometheus — séries temporais, targets ativos | +| `http://localhost:3000` | Grafana — dashboard "Payment Overview" (admin/admin) | +| `http://localhost:16686` | Jaeger — traces distribuídos por operação | -Redis está pré-instalado mas **não sobe por padrão**: +## Testes ```bash -docker compose --profile cache up -d -``` +# Unitários — sem Docker, rápido +make test +# equivalente: ./mvnw test -## Makefile - -``` -make up # docker compose up -d --build -make down # docker compose down (mantém volumes) -make clean # docker compose down -v (apaga volumes) -make logs # docker compose logs -f app -make test # ./mvnw test (sem Docker) -make verify # ./mvnw verify (com Testcontainers — requer Docker) -make format # ./mvnw spotless:apply -make db # psql no container postgres +# Integração — sobe PostgreSQL 18 via Testcontainers +make verify +# equivalente: ./mvnw verify ``` -## Qualidade de código +Convenção de nomes: +- `*Test.java` — testes unitários, executados pelo Surefire +- `*IT.java` — testes de integração, executados pelo Failsafe -```bash -# Formatar -./mvnw spotless:apply # ou: make format +O teste `PaymentApiApplicationIT` valida que o contexto Spring sobe corretamente contra um banco PostgreSQL real, sem mocks. -# Verificar formatação (GJF AOSP, 4-space) -./mvnw spotless:check +## CI/CD -# Verificar estilo (Checkstyle) -./mvnw checkstyle:check +| Trigger | Job | O que roda | +|---|---|---| +| Push para `develop` ou `main` | Lint + Unit Tests | `spotless:check` → `checkstyle:check` → `mvnw test` | +| Push para `main` ou PR → `main` | Full Verify + Docker Build | `mvnw verify` (unit + integração) → `docker build` | -# CI roda os dois antes dos testes: -./mvnw spotless:check && ./mvnw checkstyle:check && ./mvnw test -``` +O job de integração roda apenas no caminho para `main`, mantendo o ciclo de feedback rápido no `develop`. -## Pacotes (Clean Architecture) - -``` -com.lmoraesdev.payment -├── adapter -│ ├── in.web ← controllers, exception handler -│ └── out -│ ├── messaging ← Kafka producers (futuro) -│ └── persistence ← JPA repositories (futuro) -├── application -│ ├── port.in ← interfaces de entrada (futuro) -│ ├── port.out ← interfaces de saída (futuro) -│ └── usecase ← casos de uso (futuro) -├── config -│ └── logging ← Logger5w1h estruturado -└── domain - ├── event ← domain events (futuro) - ├── exception ← DomainException base - └── model ← entidades / value objects (futuro) -``` +## Padrões -## Testes +**Formatação e estilo:** ```bash -# Unitários (sem Docker) -./mvnw test - -# Integração — sobe Postgres 18 via Testcontainers -./mvnw verify +./mvnw spotless:apply # formata (Google Java Format, AOSP 4-space) +./mvnw spotless:check # verifica (roda no CI) +./mvnw checkstyle:check # estilo (roda no CI) ``` -## Git hooks +**Git hooks** (ativar uma vez por clone): ```bash git config core.hooksPath .githooks ``` -| Hook | O que faz | +| Hook | Ação | |---|---| -| `pre-push` | Executa `./mvnw verify` antes de cada push | | `commit-msg` | Valida formato Conventional Commits | +| `pre-push` | Executa `./mvnw verify` antes de subir | -Formato de commit: `tipo(escopo): descrição` -Tipos: `feat fix docs style refactor test chore build ci perf revert` +Formato de commit: `tipo(escopo): descrição` — tipos aceitos: `feat fix docs style refactor test chore build ci perf revert`. -## CI +**Makefile:** -| Branch / PR | Jobs | -|---|---| -| `develop` push | Lint (Spotless + Checkstyle) + unit tests | -| `main` push / PR → main | Lint + unit tests + full-verify + docker build | +``` +make up # docker compose up -d --build +make down # docker compose down (mantém volumes) +make clean # docker compose down -v (remove volumes) +make logs # docker compose logs -f app +make test # ./mvnw test +make verify # ./mvnw verify +make format # ./mvnw spotless:apply +make db # psql no container postgres +``` + +## Roadmap + +O que está especificado em [`docs/architecture.md`](docs/architecture.md) e ainda não implementado: + +- [ ] Entidade `Charge` com value object `Money` e `ChargeStatus` +- [ ] Máquina de estados (`PENDING → ACTIVE → PAID / EXPIRED / CANCELLED`) +- [ ] Caso de uso `CreateCharge` com idempotência por header +- [ ] Adapter de persistência JPA (`ChargeRepository`) +- [ ] Publicação de eventos de domínio no Kafka (`ChargeCreated`, `ChargePaid`, etc.) +- [ ] Consumer para eventos externos (webhook/notificação) +- [ ] Uso do Redis para cache de idempotência e locks +- [ ] Endpoints REST de cobrança (`POST /charges`, `GET /charges/{id}`) + +--- + +[Leandro Moraes](https://github.com/lmoraesdev)