- Added comprehensive course structure with 11 modules - Included theoretical content, practical examples, and tasks - Multi-language code examples (Java, Rust, Node.js, Python) - Detailed analysis of architectural approaches and trade-offs - Complete caching strategies documentation - Architecture examples from real-world systems (Twitter, Netflix, Uber) - Structured navigation and learning path - Ready for educational use
365 lines
9.4 KiB
Markdown
365 lines
9.4 KiB
Markdown
# Реализация архитектуры
|
|
|
|
## Навигация
|
|
- [🏠 Главная страница курса](../../../README.md)
|
|
- [📚 Модуль 11](../README.md)
|
|
|
|
---
|
|
|
|
## Структура проекта
|
|
|
|
### 1. Monorepo Structure
|
|
```
|
|
ecommerce-platform/
|
|
├── services/
|
|
│ ├── user-service/
|
|
│ │ ├── src/
|
|
│ │ ├── Dockerfile
|
|
│ │ ├── pom.xml
|
|
│ │ └── README.md
|
|
│ ├── product-service/
|
|
│ ├── order-service/
|
|
│ ├── payment-service/
|
|
│ └── inventory-service/
|
|
├── frontend/
|
|
│ ├── customer-app/
|
|
│ ├── admin-app/
|
|
│ └── shared/
|
|
├── infrastructure/
|
|
│ ├── kubernetes/
|
|
│ ├── terraform/
|
|
│ └── docker-compose/
|
|
├── docs/
|
|
│ ├── architecture/
|
|
│ ├── api/
|
|
│ └── deployment/
|
|
└── scripts/
|
|
├── build.sh
|
|
├── deploy.sh
|
|
└── test.sh
|
|
```
|
|
|
|
### 2. Service Implementation
|
|
```java
|
|
// Order Service Implementation
|
|
@RestController
|
|
@RequestMapping("/api/orders")
|
|
@Validated
|
|
public class OrderController {
|
|
|
|
@Autowired
|
|
private OrderService orderService;
|
|
|
|
@PostMapping
|
|
public ResponseEntity<OrderResponse> createOrder(
|
|
@Valid @RequestBody CreateOrderRequest request) {
|
|
|
|
Order order = orderService.createOrder(request);
|
|
OrderResponse response = OrderMapper.toResponse(order);
|
|
|
|
return ResponseEntity.status(HttpStatus.CREATED).body(response);
|
|
}
|
|
|
|
@GetMapping("/{id}")
|
|
public ResponseEntity<OrderResponse> getOrder(@PathVariable Long id) {
|
|
Order order = orderService.getOrder(id);
|
|
OrderResponse response = OrderMapper.toResponse(order);
|
|
|
|
return ResponseEntity.ok(response);
|
|
}
|
|
|
|
@PutMapping("/{id}/status")
|
|
public ResponseEntity<OrderResponse> updateOrderStatus(
|
|
@PathVariable Long id,
|
|
@Valid @RequestBody UpdateOrderStatusRequest request) {
|
|
|
|
Order order = orderService.updateOrderStatus(id, request.getStatus());
|
|
OrderResponse response = OrderMapper.toResponse(order);
|
|
|
|
return ResponseEntity.ok(response);
|
|
}
|
|
}
|
|
|
|
@Service
|
|
@Transactional
|
|
public class OrderService {
|
|
|
|
@Autowired
|
|
private OrderRepository orderRepository;
|
|
|
|
@Autowired
|
|
private OrderEventPublisher eventPublisher;
|
|
|
|
@Autowired
|
|
private InventoryServiceClient inventoryClient;
|
|
|
|
@Autowired
|
|
private PaymentServiceClient paymentClient;
|
|
|
|
public Order createOrder(CreateOrderRequest request) {
|
|
// Валидация заказа
|
|
validateOrderRequest(request);
|
|
|
|
// Создание заказа
|
|
Order order = new Order(request);
|
|
order = orderRepository.save(order);
|
|
|
|
// Резервирование товаров
|
|
inventoryClient.reserveItems(order.getId(), request.getItems());
|
|
|
|
// Публикация события
|
|
eventPublisher.publishOrderCreated(order);
|
|
|
|
return order;
|
|
}
|
|
|
|
public Order updateOrderStatus(Long orderId, OrderStatus status) {
|
|
Order order = orderRepository.findById(orderId)
|
|
.orElseThrow(() -> new OrderNotFoundException("Order not found: " + orderId));
|
|
|
|
order.updateStatus(status);
|
|
order = orderRepository.save(order);
|
|
|
|
// Публикация события
|
|
eventPublisher.publishOrderStatusUpdated(order);
|
|
|
|
return order;
|
|
}
|
|
|
|
private void validateOrderRequest(CreateOrderRequest request) {
|
|
if (request.getItems().isEmpty()) {
|
|
throw new ValidationException("Order must contain at least one item");
|
|
}
|
|
|
|
// Дополнительные проверки...
|
|
}
|
|
}
|
|
```
|
|
|
|
## Проектирование API
|
|
|
|
### 1. REST API Specification
|
|
```yaml
|
|
# OpenAPI Specification
|
|
openapi: 3.0.0
|
|
info:
|
|
title: E-commerce Platform API
|
|
version: 1.0.0
|
|
description: API for e-commerce platform
|
|
|
|
servers:
|
|
- url: https://api.ecommerce.com/v1
|
|
description: Production server
|
|
|
|
paths:
|
|
/orders:
|
|
post:
|
|
summary: Create a new order
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateOrderRequest'
|
|
responses:
|
|
'201':
|
|
description: Order created successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OrderResponse'
|
|
'400':
|
|
description: Bad request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/orders/{id}:
|
|
get:
|
|
summary: Get order by ID
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Order retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OrderResponse'
|
|
'404':
|
|
description: Order not found
|
|
|
|
components:
|
|
schemas:
|
|
CreateOrderRequest:
|
|
type: object
|
|
required:
|
|
- customerId
|
|
- items
|
|
properties:
|
|
customerId:
|
|
type: integer
|
|
format: int64
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/OrderItem'
|
|
shippingAddress:
|
|
$ref: '#/components/schemas/Address'
|
|
paymentMethod:
|
|
$ref: '#/components/schemas/PaymentMethod'
|
|
|
|
OrderResponse:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
format: int64
|
|
customerId:
|
|
type: integer
|
|
format: int64
|
|
status:
|
|
type: string
|
|
enum: [PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED]
|
|
totalAmount:
|
|
type: number
|
|
format: decimal
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/OrderItem'
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
```
|
|
|
|
### 2. Event Schema
|
|
```json
|
|
{
|
|
"orderCreated": {
|
|
"eventType": "OrderCreated",
|
|
"version": "1.0",
|
|
"timestamp": "2023-12-01T10:00:00Z",
|
|
"data": {
|
|
"orderId": "12345",
|
|
"customerId": "67890",
|
|
"items": [
|
|
{
|
|
"productId": "prod-001",
|
|
"quantity": 2,
|
|
"price": 29.99
|
|
}
|
|
],
|
|
"totalAmount": 59.98,
|
|
"status": "PENDING"
|
|
}
|
|
},
|
|
"orderStatusUpdated": {
|
|
"eventType": "OrderStatusUpdated",
|
|
"version": "1.0",
|
|
"timestamp": "2023-12-01T10:05:00Z",
|
|
"data": {
|
|
"orderId": "12345",
|
|
"oldStatus": "PENDING",
|
|
"newStatus": "CONFIRMED",
|
|
"updatedBy": "system"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Проектирование базы данных
|
|
|
|
### 1. Database Schema
|
|
```sql
|
|
-- Order Service Database Schema
|
|
CREATE TABLE orders (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
customer_id BIGINT NOT NULL,
|
|
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
|
|
total_amount DECIMAL(10,2) NOT NULL,
|
|
shipping_address JSONB,
|
|
payment_method JSONB,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE order_items (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
order_id BIGINT NOT NULL REFERENCES orders(id),
|
|
product_id VARCHAR(50) NOT NULL,
|
|
quantity INTEGER NOT NULL,
|
|
unit_price DECIMAL(10,2) NOT NULL,
|
|
total_price DECIMAL(10,2) NOT NULL
|
|
);
|
|
|
|
CREATE TABLE order_events (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
order_id BIGINT NOT NULL,
|
|
event_type VARCHAR(50) NOT NULL,
|
|
event_data JSONB NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Индексы для оптимизации
|
|
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
|
|
CREATE INDEX idx_orders_status ON orders(status);
|
|
CREATE INDEX idx_orders_created_at ON orders(created_at);
|
|
CREATE INDEX idx_order_items_order_id ON order_items(order_id);
|
|
CREATE INDEX idx_order_events_order_id ON order_events(order_id);
|
|
```
|
|
|
|
### 2. Data Access Layer
|
|
```java
|
|
@Repository
|
|
public interface OrderRepository extends JpaRepository<Order, Long> {
|
|
|
|
List<Order> findByCustomerId(Long customerId);
|
|
|
|
List<Order> findByStatus(OrderStatus status);
|
|
|
|
@Query("SELECT o FROM Order o WHERE o.createdAt BETWEEN :startDate AND :endDate")
|
|
List<Order> findOrdersByDateRange(
|
|
@Param("startDate") LocalDateTime startDate,
|
|
@Param("endDate") LocalDateTime endDate
|
|
);
|
|
|
|
@Query("SELECT o FROM Order o WHERE o.customerId = :customerId AND o.status = :status")
|
|
List<Order> findByCustomerIdAndStatus(
|
|
@Param("customerId") Long customerId,
|
|
@Param("status") OrderStatus status
|
|
);
|
|
}
|
|
|
|
@Repository
|
|
public class OrderEventRepository {
|
|
|
|
@Autowired
|
|
private JdbcTemplate jdbcTemplate;
|
|
|
|
public void saveEvent(OrderEvent event) {
|
|
String sql = "INSERT INTO order_events (order_id, event_type, event_data) VALUES (?, ?, ?)";
|
|
|
|
jdbcTemplate.update(sql,
|
|
event.getOrderId(),
|
|
event.getEventType(),
|
|
event.getEventData()
|
|
);
|
|
}
|
|
|
|
public List<OrderEvent> findEventsByOrderId(Long orderId) {
|
|
String sql = "SELECT * FROM order_events WHERE order_id = ? ORDER BY created_at";
|
|
|
|
return jdbcTemplate.query(sql, new OrderEventRowMapper(), orderId);
|
|
}
|
|
}
|
|
```
|