- Docker
- Docker Compose
-
Clone o projeto:
git clone [email protected]:dev-brunoreis/fakestore-hub.git cd fakestore-hub
-
Configure o ambiente:
cp .env.example .env
-
Inicie os containers:
docker-compose up --build
- Aplicação Laravel: http://localhost:8000
- Adminer (Banco de dados): http://localhost:8080
- Servidor:
mysql
- Usuário:
fakestore
- Senha:
fakestore
- Banco:
fakestore-hub
- Servidor:
O arquivo .env.example
contém as configurações necessárias:
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=fakestore-hub
DB_USERNAME=fakestore
DB_PASSWORD=fakestore
CACHE_STORE=database
- Tabela
categories
: Armazena categorias comexternal_id
único - Tabela
products
: Armazena produtos com relacionamento 1:N para categorias - Índices criados:
external_id
único em produtos (evita duplicatas)name
em categorias (otimiza filtros)category_id
em produtos (otimiza joins)price
em produtos (otimiza ordenação e filtros)
- Middleware de integração com validação do header X-Client-Id
- Log de entrada/saída das requisições com tempo de resposta
- Sincronização de produtos e categorias da Fake Store API
- Evita duplicidades usando external_id único
- Catálogo com filtros (categoria, preço, busca) e paginação
- Estatísticas com consultas SQL puro
- Tratamento de erros e resiliência na API externa
- Cache de listagem e estatísticas com invalidação automática
- Rate limiting por cliente (60 requisições por minuto)
- Retry com backoff exponencial para API externa
- Testes automatizados para endpoints críticos
- Docker e docker-compose para ambiente isolado
Execute os testes automatizados:
docker exec fakestore_app ./vendor/bin/phpunit
Cobertura de Testes:
- Middleware de integração (validação de header, rate limiting)
- Endpoint de sincronização (retry com backoff)
- Endpoint de produtos (filtros, paginação, ordenação)
- Endpoint de estatísticas (consultas SQL puro)
Todas as rotas da API requerem o header X-Client-Id
para autenticação.
Sincroniza produtos da FakeStore API com o banco de dados local.
curl -X POST http://localhost:8000/api/integrations/fakestore/sync \
-H "X-Client-Id: seu-client-id" \
-H "Content-Type: application/json"
Resposta de exemplo:
{
"message": "Sync completed",
"products_synced": 20,
"errors": 0
}
Retorna uma lista paginada de produtos com opções de filtro.
# Listar todos os produtos
curl -X GET http://localhost:8000/api/products \
-H "X-Client-Id: seu-client-id"
# Filtrar por categoria
curl -X GET "http://localhost:8000/api/products?category=electronics" \
-H "X-Client-Id: seu-client-id"
# Filtrar por preço mínimo e máximo
curl -X GET "http://localhost:8000/api/products?min_price=10&max_price=100" \
-H "X-Client-Id: seu-client-id"
# Buscar por título
curl -X GET "http://localhost:8000/api/products?search=phone" \
-H "X-Client-Id: seu-client-id"
# Ordenar por preço (ascendente)
curl -X GET "http://localhost:8000/api/products?sort=price&direction=asc" \
-H "X-Client-Id: seu-client-id"
# Definir itens por página
curl -X GET "http://localhost:8000/api/products?per_page=20" \
-H "X-Client-Id: seu-client-id"
Parâmetros disponíveis:
category
: Filtrar por categoriamin_price
: Preço mínimomax_price
: Preço máximosearch
: Buscar no título do produtosort
: Campo para ordenação (padrão: price)direction
: Direção da ordenação (asc/desc, padrão: asc)per_page
: Itens por página (padrão: 15)
Resposta de exemplo:
{
"current_page": 1,
"data": [
{
"id": 1,
"title": "iPhone 9",
"price": 549.00,
"category_id": 1,
"external_id": "1",
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z",
"category": {
"id": 1,
"name": "electronics",
"external_id": "d1bd4b2e9a6740e0a75f3e0b0c0c0c0c",
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
}
}
],
"first_page_url": "http://localhost:8000/api/products?page=1",
"from": 1,
"last_page": 2,
"last_page_url": "http://localhost:8000/api/products?page=2",
"next_page_url": "http://localhost:8000/api/products?page=2",
"path": "http://localhost:8000/api/products",
"per_page": 15,
"prev_page_url": null,
"to": 15,
"total": 20
}
Retorna detalhes de um produto específico pelo ID.
curl -X GET http://localhost:8000/api/products/1 \
-H "X-Client-Id: seu-client-id"
Resposta de exemplo:
{
"id": 1,
"title": "iPhone 9",
"price": 549.00,
"category_id": 1,
"external_id": "1",
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z",
"category": {
"id": 1,
"name": "electronics",
"external_id": "d1bd4b2e9a6740e0a75f3e0b0c0c0c0c",
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
}
}
Retorna estatísticas gerais sobre os produtos.
curl -X GET http://localhost:8000/api/statistics \
-H "X-Client-Id: seu-client-id"
Resposta de exemplo:
{
"general": {
"total_products": 20,
"average_price": 156.50,
"min_price": 7.95,
"max_price": 695.00
},
"by_category": [
{
"category": "electronics",
"total_products": 6,
"average_price": 230.50
},
{
"category": "jewelery",
"total_products": 4,
"average_price": 88.25
}
],
"top_expensive": [
{
"title": "iPhone 9",
"price": 549.00,
"category": "electronics"
},
{
"title": "Samsung Galaxy",
"price": 695.00,
"category": "electronics"
}
]
}
400
: HeaderX-Client-Id
não fornecido404
: Produto não encontrado429
: Muitas requisições (rate limit excedido)500
: Erro interno do servidor