Estado atual (v4.1.0) e evolução planejada até v9.x
Cliente HTTP
│ POST /api/transcriptions
│ multipart/form-data { file: audio }
▼
TranscriptionController (adapter/in/http)
│ MultipartFile → TranscribeCommand(bytes, filename, contentType, size)
▼
TranscribeAudioPort (interface — domain/port/in)
│
▼
TranscribeAudioUseCase (application)
│ 1. validate(contentType) → 400 se inválido
│ 2. sha256(bytes)
│ 3. TranscriptionCachePort.get(hash)
│ HIT → retorna em ~15ms com cached=true
│ MISS → continua
│ 4. SpeechToTextPort.transcribe(bytes)
│ 5. TranscriptionCachePort.put(hash, result)
│ 6. TranscriptionEventPort.publish(Transcription)
│ 7. TranscriptionMetrics
│
├── SpeechToTextPort → WhisperAdapter (infrastructure/speechtotext/whisper)
│ @Retry + @CircuitBreaker
│ ByteArrayResource → POST speaches:8000/v1/audio/transcriptions
│
├── TranscriptionCachePort → RedisTranscriptionCacheAdapter (infrastructure/cache)
│ SHA-256 → "transcription:{hash}" → Redis (TTL 24h)
│
└── TranscriptionEventPort → NoOpTranscriptionEventAdapter (infrastructure/messaging)
log.debug — substituído por RabbitMQ na Fase 8
shared/
├── config/ MdcLoggingFilter · OpenApiConfig · WebClientConfig · RedisConfig
└── exception/ GlobalExceptionHandler (ProblemDetail RFC 9457)
Infraestrutura (Docker Compose)
├── speaches :8000 — Whisper
├── redis :6379 — Cache SHA-256 (TTL 24h)
├── prometheus :9090 — Métricas
├── grafana :3000 — Dashboards
├── zipkin :9411 — Tracing
└── sonarqube :9000 — Análise local (apenas dev)
[ HTTP ] [ RabbitMQ: requests ] ← Adapters de ENTRADA
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ TranscribeAudioUseCase (APPLICATION) │
│ 1. SHA-256 dos bytes │
│ 2. TranscriptionCachePort.get() → HIT retorna │
│ 3. SpeechToTextPort.transcribe() → Whisper (ou outro) │
│ 4. TranscriptionCachePort.put() │
│ 5. TranscriptionEventPort.publish() │
└─────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
WhisperAdapter RedisCache RabbitMQ:events ← Adapters de SAÍDA
(ou OpenAI...) Adapter (TranscriptionCompletedEvent)
│
┌───────────────┼───────────────┐
▼ ▼ ▼
E-mail svc SMS svc WhatsApp svc
(Spring Mail) (Twilio...) (Meta API...)
O domínio não conhece Redis, Whisper, RabbitMQ, Twilio ou Spring. Trocar qualquer tecnologia = criar um novo adapter. Domínio intocado.
Push (qualquer branch) / PR para main
│
├── ci.yml ──────────────────────────────────────────────────────
│ JDK 25 + cache Gradle
│ ./gradlew clean build (testes + Jacoco 70%)
│ ./gradlew sonar (SonarCloud Quality Gate)
│ Upload Codecov (cobertura visual no PR)
│
└── docker.yml ──────────────────────────────────────────────────
Docker Buildx + BuildKit + cache GHA
metadata-action → tags: sha / branch / latest (main) / pr-N
Push apenas se não for PR
Trivy scan (CRITICAL+HIGH)
Push tag v*
│
├── release.yml ─────────────────────────────────────────────────
│ Re-tag imagem latest → vX.Y.Z
│ GitHub Release com release notes automáticas + instruções Docker
│
└── docs.yml ────────────────────────────────────────────────────
pandoc + xelatex → readme_pdf.md → .pdf
Artifact 30 dias + anexado ao release
| Secret | Descrição |
|---|---|
| DOCKERHUB_USERNAME | erichiroshi |
| DOCKERHUB_TOKEN | Token Docker Hub (não senha) |
| SONAR_TOKEN | Token SonarCloud |
| CODECOV_TOKEN | Token Codecov |
com.example.diospeechai/
│
├── shared/ # Transversal
│ ├── config/ # WebClient, Redis, MDC, OpenAPI
│ └── exception/ # GlobalExceptionHandler
│
├── auth/
│ ├── domain/port/ # TokenServicePort (interface)
│ ├── application/ # GenerateTokenUseCase
│ ├── infrastructure/jwt/ # JwtTokenAdapter, JwtProperties
│ └── adapter/in/http/ # AuthController, DTOs, documentação
│
└── transcription/
├── domain/
│ ├── model/ # Transcription (entidade)
│ └── port/
│ ├── in/ # TranscribeAudioPort
│ └── out/ # SpeechToTextPort
│ # TranscriptionCachePort
│ # TranscriptionEventPort
├── application/ # TranscribeAudioUseCase
│ ├── command/ # TranscribeCommand
│ └── result/ # TranscriptionResult
├── infrastructure/
│ ├── speechtotext/whisper/ # WhisperAdapter
│ ├── cache/ # RedisTranscriptionCacheAdapter
│ └── messaging/rabbit/ # RabbitConfig, RabbitEventAdapter
├── adapter/
│ ├── in/http/ # TranscriptionController
│ ├── in/messaging/ # TranscriptionRequestConsumer
│ └── out/messaging/event/ # TranscriptionCompletedEvent
├── metrics/ # TranscriptionMetrics
└── exception/ # TranscriptionException, ServiceUnavailable
| Fase | Versões | O que muda |
|---|---|---|
| Fase 1 ✓ | v1.0.0 | API REST, Docker Compose, ProblemDetail RFC 9457 |
| Fase 2 ✓ | v2.1–v2.7 | Prometheus, Grafana, Zipkin/OTel, Redis, Cache SHA-256, Logs JSON |
| Fase 3 ✓ | v3.1–v3.5 | CircuitBreaker, Retry, JWT (temporário), Testcontainers |
| Fase 4 ✓ | v4.1.0 | SpringDoc OpenAPI 3.1, Swagger UI, interfaces de documentação |
| Fase 5 ✓ | v5.1.0–v5.3.0 | Jacoco 70%, SonarCloud, ci.yml, docker.yml, release.yml, docs.yml. JWT removido. SonarQube local no docker-compose.dev.yml. |
| Fase 6 pendente | v6.x | Bean Validation — pendente. Retorna quando houver DTOs de entrada com campos validáveis (ex: JSON body). Sem previsão de versão. |
| Fase 7 ✓ | v7.1.0–v7.6.0 | Arquitetura hexagonal completa. TranscribeAudioUseCase, WhisperAdapter, RedisTranscriptionCacheAdapter, pacotes shared/. contentType no TranscribeCommand. ByteArrayResource no WhisperAdapter. |
| Fase 8 → | v8.1–v8.3 | RabbitMQ: produtor de eventos + consumer de pedidos + DLQ + Testcontainers |
| Fase 9 → | v9.1–v9.3 | Notificações: e-mail (Spring Mail), SMS, WhatsApp via consumers RabbitMQ |