Você recebeu a especificação de uma API de gerenciamento de tarefas definida via Protocol Buffers (arquivo proto/tasks.proto). Seu trabalho é implementar os dois serviços que compõem esse sistema e containerizá-los.
O arquivo .proto é o único contrato fornecido. Tudo mais — código, Dockerfiles e docker-compose — é sua responsabilidade.
┌──────────────┐ ┌──────────────────────┐
│ cliente │──HTTP─▶│ go-app :8080 │
│ (curl/etc) │ │ REST API gateway │
└──────────────┘ └──────────┬────────────┘
│ gRPC :50051
┌──────────▼────────────┐
│ python-app :50051 │
│ gRPC Server │
│ HTTP health :8001 │
└───────────────────────┘
proto/tasks.proto— definição do contrato gRPC. Não altere este arquivo.
O arquivo .proto precisa ser compilado para gerar as classes e interfaces que você vai usar no código. Cada linguagem tem sua própria ferramenta.
O pacote grpcio-tools já inclui o compilador, sem instalação separada:
pip install grpcio grpcio-tools
python -m grpc_tools.protoc \
-I proto \
--python_out=python-app \
--grpc_python_out=python-app \
proto/tasks.protoIsso vai gerar dois arquivos dentro de python-app/:
tasks_pb2.py— classes das mensagens (Task, ListTasksRequest, etc.)tasks_pb2_grpc.py— classe base do servidor (TaskServiceServicer) e o stub do cliente
Você vai implementar o servidor herdando de TaskServiceServicer e sobrescrevendo cada método.
Go precisa do compilador protoc instalado separadamente, mais dois plugins:
# instalar o compilador protoc (Ubuntu/Debian)
apt install -y protobuf-compiler
# instalar os plugins Go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
# gerar o código (rode na raiz do repositório)
protoc \
-I proto \
--go_out=go-app --go_opt=paths=source_relative \
--go-grpc_out=go-app --go-grpc_opt=paths=source_relative \
proto/tasks.protoIsso vai gerar dentro de go-app/:
tasks.pb.go— structs das mensagenstasks_grpc.pb.go— interface do servidor e o client stub
O client stub (NewTaskServiceClient) é o que o Go vai usar para chamar o Python via gRPC.
Dica: adicione os arquivos gerados ao
.gitignoreou commite-os — ambas as abordagens são válidas, mas seja consistente e documente sua escolha.
Implemente o servidor gRPC definido em tasks.proto. Requisitos:
- Implementar todos os cinco métodos:
ListTasks,GetTask,CreateTask,UpdateTask,DeleteTask - Persistência em memória é suficiente (sem banco de dados)
- Expor um endpoint HTTP
/healthem uma porta separada (sugerido:8001) — será usado pelo health check do Docker - Logs estruturados em JSON para cada chamada recebida, contendo ao menos: timestamp, método RPC e status
Implemente um serviço HTTP que atua como gateway para o serviço Python. Requisitos:
-
Consumir o Python via gRPC usando o client stub gerado
-
Expor os seguintes endpoints REST:
Método Rota Descrição GET /healthHealth check GET /tasksLista todas as tarefas POST /tasksCria uma nova tarefa GET /tasks/{id}Retorna uma tarefa PUT /tasks/{id}Atualiza uma tarefa DELETE /tasks/{id}Remove uma tarefa GET /summaryResumo: total, completed, pending -
Exemplo de resposta para
GET /summary:{ "total": 5, "completed": 2, "pending": 3 } -
Logs estruturados em JSON para cada request HTTP recebido
-
Endereço gRPC do Python configurável via variável de ambiente
PYTHON_GRPC_ADDR(ex:python-app:50051) -
Porta HTTP configurável via
PORT(padrão8080)
Arquivo: python-app/Dockerfile
- Imagem base enxuta (ex:
python:3.12-slim) - Apenas arquivos necessários copiados
Arquivo: go-app/Dockerfile
- Multi-stage build obrigatório: stage de compilação separado do stage final
- Imagem final mínima (ex:
gcr.io/distroless/staticoualpine:3) - O binário Go compilado é o único artefato da imagem final
Arquivo na raiz do repositório orquestrando os dois serviços:
python-app
- Health check verificando o endpoint
/healthHTTP - Variáveis de ambiente necessárias configuradas
go-app
- Inicia somente após o python-app estar healthy (
depends_oncomcondition: service_healthy) - Variáveis de ambiente necessárias configuradas
Requisitos gerais:
- Rede bridge customizada e nomeada — serviços se comunicam por nome de serviço, não por IP
- Limites de recursos:
256MBde memória e0.5CPUs por serviço - Zero hardcode de configuração (endereços, portas via env vars)
.
├── proto/
│ └── tasks.proto # fornecido — não altere
├── python-app/
│ ├── main.py
│ ├── requirements.txt
│ └── Dockerfile
├── go-app/
│ ├── main.go
│ ├── go.mod
│ └── Dockerfile
├── docker-compose.yml
└── DECISIONS.md # suas escolhas técnicas documentadas
Após executar docker compose up --build, os seguintes comandos devem funcionar:
# health checks
curl -s http://localhost:8080/health | jq
# criar uma tarefa
curl -s -X POST http://localhost:8080/tasks \
-H "Content-Type: application/json" \
-d '{"title":"Deploy em produção","description":"Subir nova versão"}' | jq
# listar e verificar resumo
curl -s http://localhost:8080/tasks | jq
curl -s http://localhost:8080/summary | jqImplemente na ordem abaixo se sobrar tempo:
1. Observabilidade com Prometheus + Grafana
Adicionar ao docker-compose um Prometheus coletando métricas de ambos os serviços e um Grafana com ao menos um dashboard funcional. Cada serviço deve expor um endpoint /metrics com:
- Contador de chamadas por operação
- Histograma de latência por operação
2. Unix Socket
Alterar a comunicação entre Go e Python para um Unix domain socket compartilhado via volume Docker, ao invés de TCP.