Este projeto é um protótipo mínimo funcional (MVP) de uma API de integração entre dois serviços da BITKABIR: TX KABIR (app de mobilidade) e TUDKABIR (motor de busca e comparação).
A API permite que o TUDKABIR consulte, em tempo real, motoristas disponíveis no TX KABIR, retornando informações como:
- Nome do motorista
- Tipo de veículo
- Localização atual
- Preço estimado da corrida
- Tempo de chegada estimado
O projeto foi desenvolvido seguindo os princípios de DDD (Domain-Driven Design) e Clean Architecture, garantindo modularidade, escalabilidade e manutenção facilitada.
- Cliente REST (C): Um cliente que consome a API usando requisições HTTP tradicionais.
- Cliente WebSocket (WS): Um cliente que mantém uma conexão persistente para receber atualizações em tempo real.
- API Server (API): Servidor que expõe endpoints REST e WebSocket.
- DriverUsecase (UC): Camada de lógica de negócio que coordena a busca e processamento de informações dos motoristas.
- DriverRepository (Repo): Camada de acesso a dados (Postgres) que realiza consultas sobre motoristas disponíveis.
- Requisição do cliente: O cliente REST envia uma requisição
GET /drivers
passando latitude, longitude e um token Bearer. - Verificação do token: O servidor API valida o token JWT via middleware.
- Chamada à camada de negócio: Se o token é válido, a API chama
ListNearby(lat, lon)
noDriverUsecase
. - Consulta ao repositório: O
DriverUsecase
consulta oDriverRepository
comFindAvailableNearby(lat, lon, limit, maxDist)
para obter os motoristas disponíveis próximos. - Retorno dos dados: O
Repo
retorna a lista de motoristas, oUC
adiciona informações adicionais como preço ou ETA, e envia de volta à API. - Resposta ao cliente: A API retorna um JSON com a lista de motoristas ao cliente REST.
- Conexão: O cliente WebSocket tenta se conectar ao endpoint
/ws
. - Aceitação da conexão: A API aceita a conexão, permitindo que o cliente permaneça conectado para receber dados em tempo real.
- Loop de atualização: A cada 5 segundos, a API solicita ao
DriverUsecase
a lista atualizada de motoristas disponíveis (ListAvailableDrivers()
). - Consulta ao repositório: O
UC
consulta oRepo
comFindAvailableNearby(...)
ouFindAvailable
para pegar os motoristas disponíveis naquele momento. - Envio dos dados: O
Repo
retorna a lista de motoristas, oUC
processa os dados (preço, ETA, etc.), e a API envia via WebSocket ao cliente conectado. - Recebimento pelo cliente: O cliente WebSocket recebe periodicamente o JSON com motoristas atualizados.
- O REST é usado para requisições pontuais.
- O WebSocket mantém uma conexão ativa para envio de dados atualizados automaticamente a cada 5 segundos.
- A lógica de negócio (
DriverUsecase
) atua como intermediária entre o API e o repositório, enriquecendo os dados antes de enviá-los ao cliente. - O repositório Postgres fornece os dados brutos de motoristas disponíveis.
- Linguagem: Go 1.24.3
- Banco de Dados: PostgreSQL 15
- Web Framework: net/http + Gorilla WebSocket
- Docker & Docker Compose: Para simulação de ambiente
- Autenticação: JWT simulada (token fixo
test-token
) - Testes: Unitários com
testing
package - Documentação de API: Exemplos com
curl
tx-tud/
├─ cmd/api/ # Entrypoint (main.go)
├─ internal/
│ ├─ domain/ # Entities, Value Objects
│ ├─ repository/ # Interfaces e implementações do DB
│ ├─ usecase/ # Regras de negócio (Services/Usecases)
│ └─ transport/
│ └─ http/ # Handlers, WebSocket, Middleware
├─ migrations/ # Scripts SQL de criação de tabelas
├─ tests/ # Testes unitários
├─ Dockerfile
├─ docker-compose.yml
└─ README.md
- Build e start do ambiente com Docker Compose:
docker compose up --build
- Simulação do banco de dados (apenas para exercício/testes):
docker exec -it kabir-db-1 bash
psql -U postgres -d tx_tud -f /migrations/000001_create_drivers.sql
psql -U postgres -d tx_tud -c "
INSERT INTO drivers (id, name, vehicle, lat, lon, price, eta, available)
VALUES
(1, 'Carlos Silva', 'Toyota Yaris', -8.839, 13.289, 3.5, 5, true),
(2, 'Ana Gomes', 'Kia Picanto', -8.845, 13.282, 3.8, 4, true),
(3, 'João Pedro', 'Hyundai i10', -8.843, 13.275, 3.2, 6, false);
"
- Verificar dados no DB:
psql -U postgres -d tx_tud -c "SELECT * FROM drivers;"
Para este protótipo, foi implementada autenticação simulada usando um token fixo:
Authorization: Bearer test-token
- Sem token:
curl http://localhost:8080/drivers
# {"error": "missing authorization"}
- Com token, mas sem parâmetros obrigatórios:
curl -H "Authorization: Bearer test-token" http://localhost:8080/drivers
# {"error":"lat and lon required"}
- Com token e parâmetros corretos:
curl -H "Authorization: Bearer test-token" "http://localhost:8080/drivers?lat=-8.84&lon=13.28"
# Retorna lista de motoristas próximos
- Crie uma nova request do tipo WebSocket.
- Defina a URL como:
ws://localhost:8080/ws
- Clique em Connect.
- O servidor vai enviar atualizações a cada 5 segundos com a lista de motoristas disponíveis.
Exemplo de mensagem recebida:
[
{
"id": 2,
"name": "Ana Gomes",
"vehicle": "Kia Picanto",
"location": { "lat": -8.844, "lon": 13.282 },
"price": 3.82,
"eta": 4,
"updated_at": "2025-10-15T20:32:39Z"
}
]
⚠️ Em produção, recomenda-se substituir por JWT real.
Método | Endpoint | Parâmetros | Descrição |
---|---|---|---|
GET | /drivers | lat, lon (float) | Lista motoristas disponíveis próximos |
WS | /ws | — | Conexão WebSocket para updates em tempo real |
A cada 5 segundos, a API envia atualizações simuladas de posição e preço para todos os clientes conectados:
[
{
"id": 2,
"name": "Ana Gomes",
"vehicle": "Kia Picanto",
"location": { "lat": -8.844, "lon": 13.282 },
"price": 3.82,
"eta": 4,
"updated_at": "2025-10-15T20:32:39Z"
}
]
- Domain: Contém entidades e value objects (Driver, VehicleType, Location)
- Repository: Interfaces e implementações para persistência
- Usecase: Lógica de negócio (ex:
ListNearby
) - Transport: Handlers HTTP e WebSocket, middlewares (JWT, logging)
Exemplo de teste do Usecase ListNearby
:
func TestListNearby(t *testing.T) {
repo := &fakeRepo{}
uc := usecase.NewDriverUsecase(repo)
drivers, err := uc.ListNearby(context.Background(), -8.839, 13.234)
if err != nil { t.Fatalf("expected no error, got %v", err) }
if len(drivers) == 0 { t.Fatal("expected drivers") }
if drivers[0].Name != "João" { t.Fatalf("unexpected name %s", drivers[0].Name) }
}
Para rodar os testes:
go test ./tests/...

- Projeto desenvolvido em Go 1.24.3.
- Simulação de dados e autenticação devido ao escopo de exercício de poucas horas.
- Estrutura modular, preparada para escalabilidade real em produção.
- Logging, tratamento de erros e princípios de Clean Architecture implementados.