Aplicação inspirada no Pinterest onde usuários podem fazer upload de imagens e visualizá-las em um feed. O sistema utiliza gRPC para comunicação entre serviços e RabbitMQ com modelo Pub/Sub para processamento assíncrono de eventos.
React (Frontend)
├── POST /images ──▶ Image Service (Spring Boot)
│ ├── Salva imagem no Cloudinary
│ └── Publica evento no RabbitMQ (FanoutExchange)
│ ├──▶ feed.queue ──▶ FeedConsumer
│ │ └── Busca detalhes via gRPC (GetImage)
│ │ └── Salva Post no banco
│ └──▶ notification.queue ──▶ NotificationConsumer
│ └── Loga notificação
│
└── GET /posts ──▶ Feed Service (Spring Boot)
└── GET /posts/images ──▶ Feed Service ──▶ gRPC (ListImages) ──▶ Image Service
| Serviço | Tecnologia | Porta |
|---|---|---|
| Frontend | React + Vite + Tailwind | 5173 |
| Image Service | Spring Boot | 8080 |
| Feed Service | Spring Boot | 8081 |
| gRPC | Spring gRPC | 9090 |
| Banco de dados | PostgreSQL | 5432 |
| Mensageria | RabbitMQ | 5672 |
| Dashboard RabbitMQ | RabbitMQ Management | 15672 |
O sistema utiliza o modelo Publicar-Assinar (Pub/Sub) com uma FanoutExchange. Ao fazer upload de uma imagem, o Image Service publica um evento que é entregue simultaneamente a dois assinantes independentes:
| Assinante | Fila | Responsabilidade |
|---|---|---|
FeedConsumer |
feed.queue |
Busca detalhes da imagem via gRPC e cria o Post |
NotificationConsumer |
notification.queue |
Loga notificação de nova imagem publicada |
O contrato gRPC é definido em image.proto e expõe duas operações:
| Operação | Descrição |
|---|---|
GetImage(ImageRequest) |
Busca detalhes de uma imagem por ID |
ListImages(ListImagesRequest) |
Lista todas as imagens cadastradas |
- Docker e Docker Compose
- Node.js (para rodar o frontend)
- Conta no Cloudinary
git clone https://github.com/seu-usuario/mini-pinterest.git
cd mini-pinterestCrie um arquivo .env na raiz do projeto:
CLOUDINARY_CLOUD_NAME=seu_cloud_name
CLOUDINARY_API_KEY=sua_api_key
CLOUDINARY_API_SECRET=seu_api_secret
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=appdbVocê encontra as credenciais do Cloudinary em cloudinary.com → Dashboard → Product Environment Credentials.
docker compose up --build -dAguarde todos os containers subirem. Você pode verificar com:
docker pscd frontend
npm install
npm run devAcesse em: http://localhost:5173
O dashboard do RabbitMQ está disponível em http://localhost:15672 (usuário:
admin, senha:admin)
mini-pinterest/
├── docker-compose.yml
├── .env
├── image/ # Image Service (Spring Boot)
│ ├── src/
│ │ └── main/
│ │ ├── java/com/image/
│ │ │ ├── config/ # CloudinaryConfig, RabbitMQConfig, CorsConfig
│ │ │ ├── controller/ # ImageController
│ │ │ ├── entity/ # Image
│ │ │ ├── event/ # ImageUploadedEvent
│ │ │ ├── grpc/ # ImageGrpcService
│ │ │ ├── repository/ # ImageRepository
│ │ │ └── service/ # ImageService
│ │ └── proto/
│ │ └── image.proto
│ └── Dockerfile
├── feed/ # Feed Service (Spring Boot)
│ ├── src/
│ │ └── main/
│ │ ├── java/com/feed/
│ │ │ ├── config/ # RabbitMQConfig, CorsConfig
│ │ │ ├── consumer/ # FeedConsumer, NotificationConsumer
│ │ │ ├── controller/ # PostController
│ │ │ ├── entity/ # Post
│ │ │ ├── event/ # ImageUploadedEvent
│ │ │ ├── repository/ # PostRepository
│ │ │ └── service/ # PostService
│ │ └── proto/
│ │ └── image.proto
│ └── Dockerfile
└── frontend/ # React + Vite
└── src/
├── components/
├── services/
└── interfaces/
Frontend
- React + TypeScript
- Vite
- Tailwind CSS
- React Hook Form + Yup
- Axios
- Font Awesome
Backend
- Spring Boot 3.3.5
- Spring gRPC 0.8.0
- Spring AMQP (RabbitMQ)
- Spring Data JPA
- PostgreSQL
- Cloudinary SDK
Infraestrutura
- Docker + Docker Compose
- RabbitMQ (mensageria Pub/Sub com FanoutExchange)
- gRPC com Protocol Buffers (comunicação entre serviços)
| Método | Rota | Descrição |
|---|---|---|
| POST | /images |
Upload de imagem |
| GET | /images |
Lista todas as imagens |
| GET | /images/{id} |
Busca imagem por ID |
| Método | Rota | Descrição |
|---|---|---|
| GET | /posts |
Lista todos os posts (ordem decrescente) |
| GET | /posts/{id} |
Busca post por ID |
| GET | /posts/images |
Lista imagens via gRPC (ListImages) |
syntax = "proto3";
service ImageService {
rpc GetImage (ImageRequest) returns (ImageResponse);
rpc ListImages (ListImagesRequest) returns (ListImagesResponse);
}
message ImageRequest {
int64 id = 1;
}
message ListImagesRequest {}
message ListImagesResponse {
repeated ImageResponse images = 1;
}
message ImageResponse {
int64 id = 1;
string name = 2;
string url = 3;
string public_id = 4;
}