- Deleted obsolete service architecture templates in both English and Vietnamese to streamline content. - Updated the Vietnamese architecture documentation with improved Mermaid diagrams for better visual clarity. - Enhanced color coding in diagrams to improve readability and consistency across documentation. - Added a new section detailing visual indicators for better understanding of architecture components.
963 lines
31 KiB
Markdown
963 lines
31 KiB
Markdown
# Service Template / Template Dịch Vụ
|
|
|
|
> **EN**: Standard template for creating new microservices in the @goodgo ecosystem.
|
|
> **VI**: Template chuẩn để tạo các microservice mới trong hệ sinh thái @goodgo.
|
|
|
|
## Features / Tính Năng
|
|
|
|
- **Framework**: Express.js with TypeScript / Express.js với TypeScript.
|
|
- **Database**: Prisma ORM with PostgreSQL / Prisma ORM với PostgreSQL.
|
|
- **Validation**: Zod for environment & input validation / Zod cho validation biến môi trường và đầu vào.
|
|
- **Observability / Khả năng quan sát**:
|
|
- **Metrics**: Prometheus metrics at `/metrics` / Metrics Prometheus tại `/metrics`.
|
|
- **Logging**: Common logger with request tracking / Logger chung với theo dõi request.
|
|
- **Tracing**: OpenTelemetry/Jaeger integration / Tích hợp OpenTelemetry/Jaeger.
|
|
- **Resilience / Khả năng phục hồi**:
|
|
- Graceful shutdown / Đóng ứng dụng an toàn.
|
|
- Rate limiting (Distributed via Redis) / Giới hạn tốc độ request (Phân tán qua Redis).
|
|
- Circuit Breaker / Ngắt mạch.
|
|
- Health checks (liveness/readiness) / Kiểm tra sức khỏe hệ thống.
|
|
- **Caching**: Redis caching strategy / Chiến lược caching với Redis.
|
|
- **Security / Bảo mật**: Helmet & CORS configured / Đã cấu hình Helmet & CORS.
|
|
|
|
## Project Structure / Cấu trúc Dự án
|
|
|
|
```
|
|
src/
|
|
├── config/ # Configuration & Env validation / Cấu hình & Validate biến môi trường
|
|
├── middlewares/ # Express middlewares (error, logger, metrics)
|
|
├── modules/ # Feature modules (controller, service, repository)
|
|
├── routes/ # API route definitions
|
|
└── main.ts # Entry point & App bootstrapping
|
|
```
|
|
|
|
## Getting Started / Bắt đầu
|
|
|
|
### Prerequisites / Yêu cầu tiên quyết
|
|
|
|
- Node.js >= 20
|
|
- pnpm
|
|
- Docker (Redis required)
|
|
|
|
### Installation / Cài đặt
|
|
|
|
#### Option 1: Local Development / Phát triển Cục bộ
|
|
|
|
1. **Clone & Install dependencies**:
|
|
```bash
|
|
pnpm install
|
|
```
|
|
|
|
2. **Start infrastructure with Docker**:
|
|
|
|
For local development, start the platform infrastructure from `deployments/local/`:
|
|
Để phát triển local, khởi động hạ tầng nền tảng từ `deployments/local/`:
|
|
|
|
```bash
|
|
# Navigate to deployments directory
|
|
cd deployments/local
|
|
|
|
# Start platform services (PostgreSQL, Redis, Traefik, etc.)
|
|
docker-compose up -d redis
|
|
|
|
# Return to service directory
|
|
cd ../../services/_template
|
|
```
|
|
|
|
**Note**: For full platform deployment with all services, see "Adding This Service to the Platform" section below.
|
|
**Lưu ý**: Để triển khai nền tảng đầy đủ với tất cả services, xem phần "Thêm Service Vào Nền Tảng" bên dưới.
|
|
|
|
3. **Setup database**:
|
|
```bash
|
|
pnpm prisma migrate dev
|
|
pnpm prisma db seed
|
|
```
|
|
|
|
4. **Start development server**:
|
|
```bash
|
|
pnpm dev
|
|
```
|
|
|
|
2. **Environment Setup / Thiết lập môi trường**:
|
|
|
|
Environment variables are managed at the **platform level**, not per-service:
|
|
Biến môi trường được quản lý ở **cấp độ nền tảng**, không phải mỗi service:
|
|
|
|
```bash
|
|
# EN: Setup shared environment variables (from deployments/local/)
|
|
# VI: Thiết lập biến môi trường chung (từ deployments/local/)
|
|
cd deployments/local
|
|
cp env.local.example .env.local
|
|
# Edit .env.local with your values (JWT_SECRET, DATABASE_URL, etc.)
|
|
```
|
|
|
|
**Environment Variables / Biến Môi trường**:
|
|
|
|
**Shared Variables** (in `deployments/local/.env.local`):
|
|
- `JWT_SECRET`, `JWT_REFRESH_SECRET` - Must be same across all services
|
|
- `REDIS_HOST`, `REDIS_PORT` - Shared Redis instance
|
|
- `CORS_ORIGIN` - Allowed origins for all services
|
|
- `NODE_ENV`, `LOG_LEVEL` - Common configuration
|
|
|
|
**Service-Specific Variables** (in `docker-compose.yml`):
|
|
- `PORT` - Unique port for each service
|
|
- `DATABASE_URL` - Service's database connection
|
|
- `SERVICE_NAME` - Service identifier
|
|
|
|
**Key Environment Variables / Biến Môi Trường Chính**:
|
|
|
|
| Variable / Biến | Description / Mô tả | Default / Mặc định | Required / Bắt buộc |
|
|
|-----------------|---------------------|-------------------|---------------------|
|
|
| `PORT` | Server port / Cổng server | `5000` | No / Không |
|
|
| `NODE_ENV` | Environment mode / Chế độ môi trường | `development` | No / Không |
|
|
| `API_VERSION` | API version prefix / Tiền tố phiên bản API | `v1` | No / Không |
|
|
| `CORS_ORIGIN` | Allowed CORS origins (comma-separated) / Origins CORS được phép | `http://localhost:3000` | No / Không |
|
|
| `SERVICE_NAME` | Service identifier / Mã định danh service | `microservice-template` | No / Không |
|
|
| `DATABASE_URL` | PostgreSQL connection string / Chuỗi kết nối PostgreSQL | - | **Yes / Có** |
|
|
| `REDIS_URL` | Redis connection URL / URL kết nối Redis | `redis://localhost:6379` | No / Không |
|
|
| `JWT_SECRET` | JWT secret key for token signing and verification / Khóa bí mật JWT để ký và xác minh token | - | **Yes / Có** |
|
|
| `TRACING_ENABLED` | Enable Jaeger tracing / Bật tracing Jaeger | `false` | No / Không |
|
|
| `JAEGER_ENDPOINT` | Jaeger collector endpoint / Endpoint collector Jaeger | - | No / Không |
|
|
|
|
**Environment Configuration Priority / Ưu tiên Cấu hình Môi trường**:
|
|
1. **Docker Compose environment** (in `deployments/local/docker-compose.yml`) - Highest priority
|
|
2. **Shared `.env.local`** (in `deployments/local/.env.local`) - Platform-level shared configs
|
|
3. **System environment variables** - OS-level environment
|
|
|
|
3. **Database Setup / Thiết lập Database**:
|
|
|
|
**Prerequisites / Yêu cầu tiên quyết**:
|
|
- PostgreSQL database running / Database PostgreSQL đang chạy
|
|
- `DATABASE_URL` configured in `.env` / `DATABASE_URL` đã được cấu hình trong `.env`
|
|
|
|
**Database Workflow / Quy trình Database**:
|
|
```bash
|
|
# EN: Generate Prisma client / Tạo Prisma client
|
|
pnpm prisma:generate
|
|
|
|
# EN: Create and run initial migration / Tạo và chạy migration ban đầu
|
|
pnpm prisma:migrate
|
|
|
|
# EN: (Optional) Seed database with initial data / (Tùy chọn) Seed database với dữ liệu ban đầu
|
|
pnpm prisma:seed
|
|
```
|
|
|
|
**Development Workflow / Quy trình Phát triển**:
|
|
```bash
|
|
# EN: After schema changes, regenerate client / Sau khi thay đổi schema, tạo lại client
|
|
pnpm prisma:generate
|
|
|
|
# EN: Create new migration for schema changes / Tạo migration mới cho thay đổi schema
|
|
pnpm prisma:migrate dev --name your-migration-name
|
|
|
|
# EN: View database in Prisma Studio / Xem database trong Prisma Studio
|
|
pnpm prisma:studio
|
|
```
|
|
|
|
**Production Deployment / Triển khai Production**:
|
|
```bash
|
|
# EN: Deploy migrations to production / Triển khai migrations lên production
|
|
pnpm prisma:migrate deploy
|
|
|
|
# EN: Reset database (CAUTION: destroys all data) / Reset database (CẨN THẬN: xóa tất cả dữ liệu)
|
|
pnpm prisma:migrate reset
|
|
```
|
|
|
|
4. **Run Development / Chạy môi trường phát triển**:
|
|
```bash
|
|
pnpm dev
|
|
```
|
|
|
|
5. **Build & Start Production / Build và Chạy Production**:
|
|
```bash
|
|
pnpm build
|
|
pnpm start
|
|
```
|
|
|
|
## Adding This Service to the Platform / Thêm Service Vào Nền Tảng
|
|
|
|
This template represents a **single microservice**. To deploy it as part of the GoodGo microservices platform:
|
|
Template này đại diện cho **một microservice đơn lẻ**. Để triển khai nó như một phần của nền tảng microservices GoodGo:
|
|
|
|
### 1. Register in Platform Compose File / Đăng Ký Trong Platform Compose File
|
|
|
|
Add your service to `deployments/local/docker-compose.yml`:
|
|
Thêm service của bạn vào `deployments/local/docker-compose.yml`:
|
|
|
|
```yaml
|
|
services:
|
|
your-service:
|
|
build:
|
|
context: ../..
|
|
dockerfile: services/your-service/Dockerfile
|
|
container_name: your-service-local
|
|
environment:
|
|
- NODE_ENV=development
|
|
- PORT=5002
|
|
- DATABASE_URL=${DATABASE_URL}
|
|
- REDIS_HOST=redis
|
|
- REDIS_PORT=6379
|
|
- JWT_SECRET=${JWT_SECRET}
|
|
- SERVICE_NAME=your-service
|
|
- API_VERSION=v1
|
|
- CORS_ORIGIN=http://localhost:3000,http://localhost:3001
|
|
depends_on:
|
|
redis:
|
|
condition: service_healthy
|
|
networks:
|
|
- microservices-network
|
|
labels:
|
|
# Enable Traefik service discovery
|
|
- "traefik.enable=true"
|
|
# Define routing rule (path-based routing)
|
|
- "traefik.http.routers.your-service.rule=PathPrefix(`/api/v1/your-service`)"
|
|
# Specify the service port
|
|
- "traefik.http.services.your-service.loadbalancer.server.port=5002"
|
|
# Health check configuration
|
|
- "traefik.http.services.your-service.loadbalancer.healthcheck.path=/health/live"
|
|
- "traefik.http.services.your-service.loadbalancer.healthcheck.interval=10s"
|
|
```
|
|
|
|
### 2. Start the Platform / Khởi Động Nền Tảng
|
|
|
|
```bash
|
|
# Navigate to deployments directory
|
|
cd deployments/local
|
|
|
|
# Start all services including your new service
|
|
docker-compose up -d
|
|
|
|
# View logs for your service
|
|
docker-compose logs -f your-service
|
|
```
|
|
|
|
### 3. Access Your Service / Truy Cập Service Của Bạn
|
|
|
|
Once deployed, your service is accessible through Traefik:
|
|
Sau khi triển khai, service của bạn có thể truy cập qua Traefik:
|
|
|
|
- **API**: http://localhost/api/v1/your-service
|
|
- **Health Check**: http://localhost/api/v1/your-service/health
|
|
- **API Documentation**: http://localhost/api/v1/your-service/api-docs
|
|
- **Traefik Dashboard**: http://localhost:8080 (view all registered services)
|
|
|
|
### 4. Traefik Configuration / Cấu Hình Traefik
|
|
|
|
Traefik is configured at the platform level in `infra/traefik/`:
|
|
Traefik được cấu hình ở cấp độ nền tảng trong `infra/traefik/`:
|
|
|
|
- **Static Config**: `infra/traefik/traefik.yml` - Entry points, providers, dashboard
|
|
- **Dynamic Config**: `infra/traefik/dynamic/` - Middlewares, routes, services
|
|
- **Service Discovery**: Automatic via Docker labels (no manual route configuration needed)
|
|
|
|
For advanced routing or middleware, add to `infra/traefik/dynamic/routes.yml`:
|
|
Để định tuyến nâng cao hoặc middleware, thêm vào `infra/traefik/dynamic/routes.yml`:
|
|
|
|
```yaml
|
|
http:
|
|
routers:
|
|
your-service:
|
|
rule: "PathPrefix(`/api/v1/your-service`)"
|
|
service: your-service
|
|
middlewares:
|
|
- secure-headers
|
|
- cors
|
|
- compress
|
|
```
|
|
|
|
## Observability / Khả năng quan sát
|
|
|
|
When deployed via the platform (`deployments/local/docker-compose.yml`), your service exposes:
|
|
Khi triển khai qua nền tảng (`deployments/local/docker-compose.yml`), service của bạn expose:
|
|
|
|
- **Metrics**: `http://localhost/api/v1/your-service/metrics` (Prometheus format via Traefik)
|
|
- **Health Checks**:
|
|
- Liveness: `http://localhost/api/v1/your-service/health/live`
|
|
- Readiness: `http://localhost/api/v1/your-service/health/ready`
|
|
- **API Documentation**: `http://localhost/api/v1/your-service/api-docs` (Swagger UI via Traefik)
|
|
- **Tracing**: Jaeger integration (when `TRACING_ENABLED=true`)
|
|
- **Correlation IDs**: Automatic request tracing with `x-correlation-id` headers
|
|
- **Structured Logging**: Request/response logging with correlation context
|
|
|
|
**Note**: For local development (without platform), replace `/api/v1/your-service` with `http://localhost:5000`.
|
|
**Lưu ý**: Để phát triển local (không dùng platform), thay `/api/v1/your-service` bằng `http://localhost:5000`.
|
|
|
|
### Metrics / Metrics
|
|
|
|
The service exposes comprehensive Prometheus metrics:
|
|
|
|
- **Request Duration**: `http_request_duration_seconds` (histogram)
|
|
- **Request Count**: `http_requests_total` (counter)
|
|
- **Active Requests**: `http_active_requests` (gauge)
|
|
- **Request Errors**: `http_request_errors_total` (counter)
|
|
- **Payload Sizes**: Request/response payload size histograms
|
|
- **Default Metrics**: Memory, CPU, event loop lag
|
|
|
|
### Correlation IDs / Correlation IDs
|
|
|
|
Every request gets a correlation ID for tracing across services:
|
|
|
|
- **Header**: `x-correlation-id` (propagated from upstream or auto-generated)
|
|
- **Request ID**: `x-request-id` (unique per request)
|
|
- **Logging**: All logs include correlation context
|
|
- **Metrics**: Request metrics tagged with correlation ID
|
|
|
|
### Health Checks / Health Checks
|
|
|
|
- **Liveness** (`/health/live`): Basic service availability
|
|
- **Readiness** (`/health/ready`): Service ready to handle requests (includes DB connectivity)
|
|
- **Metrics**: Health check results are tracked in Prometheus metrics
|
|
|
|
### Logging / Logging
|
|
|
|
Structured logging with multiple levels:
|
|
|
|
- **Request/Response**: Automatic logging with correlation IDs
|
|
- **Errors**: Detailed error logging with stack traces
|
|
- **Business Logic**: Custom logging with context
|
|
- **Performance**: Request duration and resource usage
|
|
|
|
### API Documentation / Tài liệu API
|
|
|
|
- **Swagger UI**: Interactive API documentation at `/api-docs`
|
|
- **OpenAPI 3.0**: Complete API specification
|
|
- **Request/Response Examples**: Real examples for all endpoints
|
|
- **Authentication**: JWT Bearer token examples
|
|
|
|
## Authentication / Xác thực
|
|
|
|
The service uses JWT (JSON Web Tokens) for authentication. Include the token in the `Authorization` header as `Bearer <token>`.
|
|
|
|
### API Documentation / Tài liệu API
|
|
|
|
#### Authentication Endpoints / Endpoints Xác thực
|
|
|
|
**Get Current User Info / Lấy Thông tin Người dùng Hiện tại**
|
|
```http
|
|
GET /auth/me
|
|
Authorization: Bearer <your-jwt-token>
|
|
```
|
|
|
|
#### Feature Management / Quản lý Feature
|
|
|
|
**Base URL**: `http://localhost/api/v1/features`
|
|
|
|
#### Create Feature / Tạo Feature
|
|
```http
|
|
POST /api/v1/features
|
|
Authorization: Bearer <admin-jwt-token>
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"name": "example-feature",
|
|
"title": "Example Feature",
|
|
"description": "An example feature for demonstration",
|
|
"config": {
|
|
"enabled": true,
|
|
"priority": 1
|
|
},
|
|
"tags": ["example", "demo"]
|
|
}
|
|
```
|
|
**Required Role:** `admin`
|
|
|
|
#### Get All Features / Lấy Tất cả Features
|
|
```http
|
|
GET /api/v1/features
|
|
```
|
|
|
|
#### Get Feature by ID / Lấy Feature theo ID
|
|
```http
|
|
GET /api/v1/features/{id}
|
|
```
|
|
|
|
#### Update Feature / Cập nhật Feature
|
|
```http
|
|
PUT /api/v1/features/{id}
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"title": "Updated Title",
|
|
"enabled": false
|
|
}
|
|
```
|
|
|
|
#### Delete Feature / Xóa Feature
|
|
```http
|
|
DELETE /api/v1/features/{id}
|
|
```
|
|
|
|
#### Toggle Feature Status / Chuyển đổi Trạng thái Feature
|
|
```http
|
|
PATCH /api/v1/features/{id}/toggle
|
|
```
|
|
|
|
### Response Format / Định dạng Response
|
|
|
|
All API responses follow this structure / Tất cả responses API tuân theo cấu trúc này:
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": { ... },
|
|
"message": "Operation completed / Hoạt động hoàn thành",
|
|
"timestamp": "2024-01-01T00:00:00.000Z"
|
|
}
|
|
```
|
|
|
|
Error responses / Responses lỗi:
|
|
```json
|
|
{
|
|
"success": false,
|
|
"error": {
|
|
"code": "FEATURE_001",
|
|
"message": "Error description / Mô tả lỗi"
|
|
},
|
|
"timestamp": "2024-01-01T00:00:00.000Z"
|
|
}
|
|
```
|
|
|
|
## Troubleshooting / Khắc phục sự cố
|
|
|
|
### Common Issues / Vấn đề thường gặp
|
|
|
|
#### Database Connection Issues / Vấn đề kết nối Database
|
|
|
|
**Problem**: `Error: P1001: Can't reach database server`
|
|
```bash
|
|
# EN: Check if PostgreSQL is running (from deployments/local/)
|
|
# VI: Kiểm tra PostgreSQL có đang chạy (từ deployments/local/)
|
|
cd deployments/local
|
|
docker-compose ps
|
|
|
|
# EN: Check database logs
|
|
# VI: Kiểm tra logs database
|
|
docker-compose logs postgres
|
|
|
|
# EN: Restart database service
|
|
# VI: Khởi động lại database service
|
|
docker-compose restart postgres
|
|
```
|
|
|
|
**Problem**: `Error: P2002: Unique constraint failed`
|
|
```typescript
|
|
// EN: This usually means you're trying to create a duplicate record
|
|
// VI: Điều này thường có nghĩa là bạn đang cố tạo record trùng lặp
|
|
// EN: Check your seed data or migration scripts
|
|
// VI: Kiểm tra seed data hoặc migration scripts
|
|
```
|
|
|
|
#### Authentication Issues / Vấn đề Authentication
|
|
|
|
**Problem**: `401 Unauthorized`
|
|
```bash
|
|
# EN: Check JWT token format
|
|
# VI: Kiểm tra định dạng JWT token
|
|
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost/auth/me
|
|
|
|
# EN: Verify JWT secret in environment
|
|
# VI: Xác minh JWT secret trong environment
|
|
echo $JWT_SECRET
|
|
|
|
# EN: Check token expiration
|
|
# VI: Kiểm tra token hết hạn
|
|
# EN: Use https://jwt.io to decode your token
|
|
```
|
|
|
|
#### Port Already in Use / Port đã được sử dụng
|
|
|
|
**Problem**: `Error: listen EADDRINUSE: address already in use`
|
|
```bash
|
|
# EN: Find process using the port
|
|
# VI: Tìm process đang sử dụng port
|
|
lsof -i :5000
|
|
|
|
# EN: Kill the process
|
|
# VI: Kill process
|
|
kill -9 <PID>
|
|
|
|
# EN: Or change port in .env
|
|
# VI: Hoặc thay đổi port trong .env
|
|
PORT=5001
|
|
```
|
|
|
|
#### Docker Issues / Vấn đề Docker
|
|
|
|
**Problem**: `ERROR: Couldn't connect to Docker daemon`
|
|
```bash
|
|
# EN: Start Docker service
|
|
# VI: Khởi động Docker service
|
|
sudo systemctl start docker
|
|
|
|
# EN: Add user to docker group (Linux)
|
|
# VI: Thêm user vào docker group (Linux)
|
|
sudo usermod -aG docker $USER
|
|
```
|
|
|
|
**Problem**: Container won't start
|
|
```bash
|
|
# EN: Check container logs (from deployments/local/)
|
|
# VI: Kiểm tra logs container (từ deployments/local/)
|
|
cd deployments/local
|
|
docker-compose logs your-service
|
|
|
|
# EN: Check container health
|
|
# VI: Kiểm tra health container
|
|
docker-compose ps
|
|
|
|
# EN: Rebuild without cache
|
|
# VI: Rebuild không dùng cache
|
|
docker-compose build --no-cache your-service
|
|
docker-compose up -d your-service
|
|
```
|
|
|
|
#### Test Failures / Test thất bại
|
|
|
|
**Problem**: Tests fail with database connection
|
|
```bash
|
|
# EN: Ensure test database is running
|
|
# VI: Đảm bảo test database đang chạy
|
|
docker-compose -f docker-compose.test.yml up -d
|
|
|
|
# EN: Run tests with verbose output
|
|
# VI: Chạy tests với output verbose
|
|
pnpm test -- --verbose
|
|
|
|
# EN: Reset test database
|
|
# VI: Reset test database
|
|
docker-compose -f docker-compose.test.yml down -v
|
|
```
|
|
|
|
### Debug Mode / Chế độ Debug
|
|
|
|
```bash
|
|
# EN: Enable debug logging (local development)
|
|
# VI: Bật debug logging (phát triển local)
|
|
DEBUG=* pnpm dev
|
|
|
|
# EN: Check application health (via platform)
|
|
# VI: Kiểm tra health ứng dụng (qua platform)
|
|
curl http://localhost/api/v1/your-service/health/ready
|
|
|
|
# EN: View application logs (from deployments/local/)
|
|
# VI: Xem logs ứng dụng (từ deployments/local/)
|
|
cd deployments/local
|
|
docker-compose logs -f your-service
|
|
|
|
# EN: Monitor metrics (via platform)
|
|
# VI: Monitor metrics (qua platform)
|
|
curl http://localhost/api/v1/your-service/metrics
|
|
```
|
|
|
|
### Performance Issues / Vấn đề Performance
|
|
|
|
**Slow Requests**:
|
|
- Check database query performance
|
|
- Review middleware chain efficiency
|
|
- Monitor Redis cache hit rates
|
|
- Check for memory leaks
|
|
|
|
**High Memory Usage**:
|
|
```bash
|
|
# EN: Check memory usage
|
|
# VI: Kiểm tra memory usage
|
|
docker stats
|
|
|
|
# EN: Monitor with Prometheus metrics
|
|
# VI: Monitor với Prometheus metrics
|
|
curl http://localhost/metrics | grep heap
|
|
```
|
|
|
|
## Docker / Docker
|
|
|
|
### Docker Image / Docker Image
|
|
|
|
This template includes a production-ready Dockerfile with:
|
|
Template này bao gồm Dockerfile production-ready với:
|
|
|
|
```dockerfile
|
|
# Multi-stage build for optimized image size
|
|
FROM node:20-alpine AS base
|
|
# ... dependency installation
|
|
FROM base AS builder
|
|
# ... build stage
|
|
FROM node:20-alpine AS runner
|
|
# ... production runtime
|
|
```
|
|
|
|
**Build the image:**
|
|
```bash
|
|
docker build -t your-service:latest .
|
|
```
|
|
|
|
### Docker Compose for Testing / Docker Compose Cho Testing
|
|
|
|
- **`docker-compose.test.yml`**: Isolated test environment with test database and Redis
|
|
|
|
**Run tests in Docker:**
|
|
```bash
|
|
docker-compose -f docker-compose.test.yml up -d
|
|
DATABASE_URL=postgresql://postgres:test_password@localhost:5433/microservice_test pnpm test
|
|
docker-compose -f docker-compose.test.yml down -v
|
|
```
|
|
|
|
### Production Deployment / Triển khai Production
|
|
|
|
For production deployment, services are orchestrated via:
|
|
Để triển khai production, các service được điều phối qua:
|
|
|
|
- **Local/Dev**: `deployments/local/docker-compose.yml`
|
|
- **Staging**: `deployments/staging/kubernetes/` (Kubernetes manifests)
|
|
- **Production**: `deployments/production/kubernetes/` (Kubernetes manifests)
|
|
|
|
**Build production image:**
|
|
```bash
|
|
docker build -t your-service:v1.0.0 .
|
|
docker tag your-service:v1.0.0 registry.example.com/your-service:v1.0.0
|
|
docker push registry.example.com/your-service:v1.0.0
|
|
```
|
|
|
|
### Docker Image Features / Tính năng Docker Image
|
|
|
|
- **Multi-stage Build**: Optimized for small production images
|
|
- **Security**: Non-root user, minimal attack surface
|
|
- **Health Checks**: Built-in health check endpoints
|
|
- **Signal Handling**: Proper signal handling with dumb-init
|
|
- **Layer Caching**: Efficient Docker layer caching
|
|
|
|
### Environment Variables for Docker / Biến môi trường cho Docker
|
|
|
|
When running in Docker, ensure these environment variables are set:
|
|
|
|
```bash
|
|
# EN: Database connection
|
|
# VI: Kết nối database
|
|
DATABASE_URL=postgresql://postgres:password@postgres:5432/microservice_template
|
|
|
|
# EN: Redis connection
|
|
# VI: Kết nối Redis
|
|
REDIS_URL=redis://redis:6379
|
|
|
|
# EN: JWT secret (change in production!)
|
|
# VI: JWT secret (thay đổi trong production!)
|
|
JWT_SECRET=your-production-jwt-secret
|
|
```
|
|
|
|
## Testing / Kiểm thử
|
|
|
|
```bash
|
|
# EN: Run all tests / Chạy tất cả tests
|
|
pnpm test
|
|
|
|
# EN: Run unit tests only / Chạy chỉ unit tests
|
|
pnpm test:unit
|
|
|
|
# EN: Run E2E tests only / Chạy chỉ E2E tests
|
|
pnpm test:e2e
|
|
|
|
# EN: Run tests with coverage / Chạy tests với coverage
|
|
pnpm test:coverage
|
|
|
|
# EN: Run tests in watch mode / Chạy tests ở chế độ watch
|
|
pnpm test:watch
|
|
|
|
# EN: Run tests in specific file / Chạy tests trong file cụ thể
|
|
pnpm test src/modules/feature/__tests__/feature.service.test.ts
|
|
|
|
# EN: Run tests matching pattern / Chạy tests khớp pattern
|
|
pnpm test -- --testNamePattern="authentication"
|
|
```
|
|
|
|
### Test Structure / Cấu trúc Test
|
|
|
|
```
|
|
src/
|
|
├── middlewares/__tests__/ # Middleware unit tests
|
|
├── modules/
|
|
│ ├── feature/__tests__/ # Feature module tests
|
|
│ └── health/__tests__/ # Health module tests
|
|
├── __tests__/ # E2E tests
|
|
│ ├── health.e2e.ts # Health endpoint E2E
|
|
│ └── feature.e2e.ts # Feature endpoint E2E
|
|
└── config/__tests__/ # Configuration tests
|
|
```
|
|
|
|
### Writing Tests / Viết Tests
|
|
|
|
#### Unit Test Example / Ví dụ Unit Test
|
|
|
|
```typescript
|
|
import { FeatureService } from '../feature.service';
|
|
import { featureRepository } from '../feature.repository';
|
|
|
|
jest.mock('../feature.repository');
|
|
|
|
describe('FeatureService', () => {
|
|
let service: FeatureService;
|
|
|
|
beforeEach(() => {
|
|
service = new FeatureService();
|
|
});
|
|
|
|
it('should create feature successfully', async () => {
|
|
const mockFeature = { id: '1', name: 'test', enabled: true };
|
|
(featureRepository.create as jest.Mock).mockResolvedValue(mockFeature);
|
|
|
|
const result = await service.create({ name: 'test' });
|
|
expect(result).toEqual(mockFeature);
|
|
});
|
|
});
|
|
```
|
|
|
|
#### E2E Test Example / Ví dụ E2E Test
|
|
|
|
```typescript
|
|
import request from 'supertest';
|
|
import express from 'express';
|
|
import { createRouter } from '../routes';
|
|
|
|
describe('Feature Endpoints E2E', () => {
|
|
let app: express.Application;
|
|
|
|
beforeAll(() => {
|
|
app = express();
|
|
app.use(express.json());
|
|
app.use(createRouter());
|
|
});
|
|
|
|
it('should create feature successfully', async () => {
|
|
const response = await request(app)
|
|
.post('/api/v1/features')
|
|
.send({ name: 'test-feature' })
|
|
.expect(201);
|
|
|
|
expect(response.body.success).toBe(true);
|
|
});
|
|
});
|
|
```
|
|
|
|
## Creating a New Service / Tạo Service Mới
|
|
|
|
To create a new microservice from this template / Để tạo microservice mới từ template này:
|
|
|
|
1. **Copy Template / Sao chép Template**:
|
|
```bash
|
|
# EN: Copy template to new service directory / Sao chép template vào thư mục service mới
|
|
cp -r services/_template services/your-service-name
|
|
cd services/your-service-name
|
|
```
|
|
|
|
2. **Update Package Configuration / Cập nhật Cấu hình Package**:
|
|
```bash
|
|
# EN: Update package.json name and description / Cập nhật tên và mô tả trong package.json
|
|
# VI: Thay đổi "name", "description", và các thông tin khác
|
|
```
|
|
|
|
3. **Configure Environment / Cấu hình Môi trường**:
|
|
```bash
|
|
# EN: Set up shared environment variables at platform level
|
|
# VI: Thiết lập biến môi trường chung ở cấp độ nền tảng
|
|
cd ../../deployments/local
|
|
cp env.local.example .env.local
|
|
|
|
# EN: Edit .env.local with shared values (JWT_SECRET, DATABASE_URL, etc.)
|
|
# VI: Chỉnh sửa .env.local với các giá trị chung (JWT_SECRET, DATABASE_URL, etc.)
|
|
nano .env.local
|
|
```
|
|
|
|
4. **Database Setup / Thiết lập Database**:
|
|
```bash
|
|
# EN: Update Prisma schema with your models / Cập nhật schema Prisma với models của bạn
|
|
# VI: Chỉnh sửa prisma/schema.prisma
|
|
|
|
# EN: Generate and run migrations / Tạo và chạy migrations
|
|
pnpm prisma:generate
|
|
pnpm prisma:migrate
|
|
```
|
|
|
|
5. **Implement Business Logic / Triển khai Logic Kinh doanh**:
|
|
- Add your modules in `src/modules/`
|
|
- Update routes in `src/routes/index.ts`
|
|
- Add validation schemas and DTOs
|
|
|
|
6. **Testing / Kiểm thử**:
|
|
```bash
|
|
# EN: Add tests for your new functionality / Thêm tests cho chức năng mới
|
|
pnpm test
|
|
```
|
|
|
|
7. **Documentation / Tài liệu**:
|
|
- Update `README.md` with service-specific information
|
|
- Update `ARCHITECTURE.md` if needed
|
|
- Update OpenAPI documentation in route files
|
|
|
|
## Extending the Template / Mở rộng Template
|
|
|
|
### Adding a New Module / Thêm Module Mới
|
|
|
|
1. **Create Module Structure / Tạo cấu trúc Module**:
|
|
```bash
|
|
mkdir -p src/modules/your-module/{__tests__}
|
|
touch src/modules/your-module/your-module.{controller,service,repository,dto,module}.ts
|
|
touch src/modules/your-module/__tests__/your-module.{service,controller}.test.ts
|
|
```
|
|
|
|
2. **Implement Repository / Triển khai Repository**:
|
|
```typescript
|
|
// src/modules/your-module/your-module.repository.ts
|
|
import { BaseRepository } from '../common/repository';
|
|
import { prisma } from '../../config/database.config';
|
|
|
|
export class YourModuleRepository extends BaseRepository<YourEntity, CreateInput, UpdateInput> {
|
|
constructor() {
|
|
super(prisma, 'yourEntity');
|
|
}
|
|
|
|
async findByCustomField(value: string): Promise<YourEntity[]> {
|
|
return this.prisma.yourEntity.findMany({
|
|
where: { customField: value },
|
|
});
|
|
}
|
|
}
|
|
|
|
export const yourModuleRepository = new YourModuleRepository();
|
|
```
|
|
|
|
3. **Implement Service / Triển khai Service**:
|
|
```typescript
|
|
// src/modules/your-module/your-module.service.ts
|
|
import { yourModuleRepository } from './your-module.repository';
|
|
import { CreateYourEntityDto, UpdateYourEntityDto } from './your-module.dto';
|
|
|
|
export class YourModuleService {
|
|
async create(data: CreateYourEntityDto) {
|
|
// Business logic
|
|
return yourModuleRepository.create(data);
|
|
}
|
|
|
|
async findAll() {
|
|
return yourModuleRepository.findAll();
|
|
}
|
|
}
|
|
```
|
|
|
|
4. **Implement Controller / Triển khai Controller**:
|
|
```typescript
|
|
// src/modules/your-module/your-module.controller.ts
|
|
import { Request, Response } from 'express';
|
|
import { asyncHandler } from '../../middlewares/error.middleware';
|
|
import { YourModuleService } from './your-module.service';
|
|
|
|
export class YourModuleController {
|
|
private service = new YourModuleService();
|
|
|
|
create = asyncHandler(async (req: Request, res: Response) => {
|
|
const result = await this.service.create(req.body);
|
|
res.status(201).json({
|
|
success: true,
|
|
data: result,
|
|
message: 'Created successfully',
|
|
timestamp: new Date().toISOString(),
|
|
});
|
|
});
|
|
|
|
findAll = asyncHandler(async (req: Request, res: Response) => {
|
|
const result = await this.service.findAll();
|
|
res.json({
|
|
success: true,
|
|
data: result,
|
|
message: 'Retrieved successfully',
|
|
timestamp: new Date().toISOString(),
|
|
});
|
|
});
|
|
}
|
|
```
|
|
|
|
5. **Create Routes / Tạo Routes**:
|
|
```typescript
|
|
// src/modules/your-module/your-module.module.ts
|
|
import { Router } from 'express';
|
|
import { YourModuleController } from './your-module.controller';
|
|
import { validateDto } from '../../middlewares/validation.middleware';
|
|
|
|
export const createYourModuleRouter = (): Router => {
|
|
const router = Router();
|
|
const controller = new YourModuleController();
|
|
|
|
router.post('/', validateDto(createYourEntitySchema), controller.create);
|
|
router.get('/', controller.findAll);
|
|
|
|
return router;
|
|
};
|
|
```
|
|
|
|
6. **Register Routes / Đăng ký Routes**:
|
|
```typescript
|
|
// src/routes/index.ts
|
|
import { createYourModuleRouter } from '../modules/your-module/your-module.module';
|
|
|
|
router.use('/api/v1/your-entities', createYourModuleRouter());
|
|
```
|
|
|
|
### Adding Environment Variables / Thêm Biến Môi trường
|
|
|
|
1. **Update config schema / Cập nhật config schema**:
|
|
```typescript
|
|
// src/config/app.config.ts
|
|
const envSchema = z.object({
|
|
// ... existing fields
|
|
YOUR_NEW_VARIABLE: z.string().default('default-value'),
|
|
});
|
|
|
|
export const appConfig = {
|
|
// ... existing config
|
|
yourNewVariable: config.YOUR_NEW_VARIABLE,
|
|
};
|
|
```
|
|
|
|
2. **Update .env files / Cập nhật file .env**:
|
|
```bash
|
|
# .env.example
|
|
YOUR_NEW_VARIABLE=your-default-value
|
|
|
|
# .env.local.example
|
|
YOUR_NEW_VARIABLE=your-local-value
|
|
```
|
|
|
|
### Security Best Practices / Thực tiễn Bảo mật
|
|
|
|
- **Input Validation**: Always validate and sanitize user inputs using Zod
|
|
- **Authentication**: Use JWT tokens with reasonable expiration times
|
|
- **Authorization**: Implement proper RBAC for your endpoints
|
|
- **Rate Limiting**: Protect against abuse with distributed rate limiting
|
|
- **HTTPS**: Always use HTTPS in production
|
|
- **Secrets**: Never commit secrets to version control
|
|
- **Dependencies**: Keep dependencies updated and audit regularly
|
|
|
|
### Performance Considerations / Lưu ý Performance
|
|
|
|
- **Database Queries**: Use indexes for frequently queried fields
|
|
- **Caching**: Implement Redis caching for expensive operations
|
|
- **Connection Pooling**: Configure appropriate connection pool sizes
|
|
- **Async Operations**: Use proper async/await patterns
|
|
- **Memory Management**: Monitor memory usage and implement cleanup
|
|
- **Metrics**: Monitor performance with built-in Prometheus metrics
|
|
|
|
## Development Guidelines / Hướng dẫn Phát triển
|
|
|
|
### Comments / Comment Code
|
|
- Use bilingual comments for all public APIs and complex logic.
|
|
- Format: `EN` first, then `VI`.
|
|
- See `.cursor/skills/comment-code/SKILL.md` for details.
|
|
|
|
### Adding a Module / Thêm Module
|
|
1. Create `src/modules/<name>/`.
|
|
2. Implement `Controller`, `Service`.
|
|
3. Register routes in `src/routes/index.ts`.
|
|
|
|
### Code Style / Phong cách Code
|
|
- Follow the established patterns in existing modules
|
|
- Use TypeScript strictly with proper type annotations
|
|
- Implement proper error handling with custom error classes
|
|
- Add comprehensive tests for all new functionality
|