docs: Update architecture and template documentation for GoodGo Platform
- Revised the architecture documentation to include detailed diagrams and descriptions for the GoodGo Microservices Platform, enhancing clarity on system components and interactions. - Updated the .NET template documentation to reflect new naming conventions and project structures, ensuring consistency across services. - Added real-world examples and practical setup instructions for local development, including Traefik routing and environment variable configurations. - Enhanced the guide documentation with verification checklists and troubleshooting steps to support developers in deploying and managing services effectively.
This commit is contained in:
@@ -41,16 +41,36 @@ Giải thích chi tiết bằng tiếng Việt về kiến trúc, bao gồm:
|
||||
|
||||
```mermaid
|
||||
C4Context
|
||||
title System Context Diagram for [System Name]
|
||||
title System Context Diagram for GoodGo Microservices Platform
|
||||
|
||||
Person(user, "User", "System user")
|
||||
System(system, "System Name", "System description")
|
||||
System_Ext(external, "External System", "External dependency")
|
||||
Person(user, "End User", "Platform users")
|
||||
Person(admin, "Administrator", "System administrators")
|
||||
|
||||
Rel(user, system, "Uses")
|
||||
Rel(system, external, "Calls", "HTTPS")
|
||||
System_Boundary(platform, "GoodGo Platform") {
|
||||
System(gateway, "Traefik Gateway", "API Gateway, routing, load balancing")
|
||||
System(services, "Microservices", "IAM, Storage, Chat, Membership, etc.")
|
||||
System(rabbitmq, "RabbitMQ", "Message broker for async events")
|
||||
}
|
||||
|
||||
System_Ext(neon, "Neon PostgreSQL", "Serverless database")
|
||||
System_Ext(redis, "Redis", "Cache and session store")
|
||||
System_Ext(minio, "MinIO/Aliyun OSS", "Object storage")
|
||||
System_Ext(monitoring, "Observability Stack", "Prometheus + Grafana + Loki + Jaeger")
|
||||
|
||||
Rel(user, gateway, "Uses", "HTTPS")
|
||||
Rel(admin, gateway, "Manages", "HTTPS")
|
||||
Rel(gateway, services, "Routes to", "HTTP")
|
||||
Rel(services, neon, "Stores data", "PostgreSQL")
|
||||
Rel(services, redis, "Caches data", "Redis Protocol")
|
||||
Rel(services, rabbitmq, "Pub/Sub events", "AMQP")
|
||||
Rel(services, minio, "Stores files", "S3 API")
|
||||
Rel(services, monitoring, "Sends telemetry", "HTTP/gRPC")
|
||||
```
|
||||
|
||||
**EN**: The GoodGo Platform uses microservices architecture where all client requests go through Traefik API Gateway. Services communicate synchronously via REST/HTTP and asynchronously via RabbitMQ events. Each service has its own database schema in Neon PostgreSQL and uses Redis for caching.
|
||||
|
||||
**VI**: Nền tảng GoodGo sử dụng kiến trúc microservices nơi tất cả requests từ client đi qua Traefik API Gateway. Các services giao tiếp đồng bộ qua REST/HTTP và bất đồng bộ qua RabbitMQ events. Mỗi service có database schema riêng trong Neon PostgreSQL và sử dụng Redis cho caching.
|
||||
|
||||
## Components / Thành phần
|
||||
|
||||
### Component A / Thành phần A
|
||||
@@ -81,9 +101,71 @@ const componentA = new ComponentA({
|
||||
|
||||
**File Location**: [`component-a.ts`](file:///path/to/component-a.ts)
|
||||
|
||||
### Component B / Thành phần B
|
||||
---
|
||||
|
||||
(Repeat structure for each major component)
|
||||
### Real-World Example: Storage Service / Ví dụ Thực tế: Storage Service
|
||||
|
||||
**EN**: File storage management service supporting multiple cloud providers (MinIO, Aliyun OSS).
|
||||
|
||||
**VI**: Service quản lý lưu trữ file hỗ trợ nhiều cloud providers (MinIO, Aliyun OSS).
|
||||
|
||||
**Key Features / Tính năng chính**:
|
||||
- Multi-provider pattern (MinIO/Aliyun OSS)
|
||||
- Pre-signed URL generation for secure uploads/downloads
|
||||
- User quota management
|
||||
- File sharing với time-limited tokens
|
||||
- Direct client upload pattern
|
||||
|
||||
**Technologies Used / Công nghệ sử dụng**:
|
||||
- .NET 10, Entity Framework Core
|
||||
- MinIO Client, Aliyun OSS SDK
|
||||
- Redis (caching)
|
||||
- PostgreSQL (Neon)
|
||||
|
||||
**Architecture Pattern**:
|
||||
```csharp
|
||||
// Provider abstraction
|
||||
public interface IStorageProvider
|
||||
{
|
||||
Task<string> UploadFileAsync(Stream fileStream, string fileName, CancellationToken ct);
|
||||
Task<string> GeneratePresignedUrlAsync(string objectKey, int expiryMinutes, CancellationToken ct);
|
||||
}
|
||||
|
||||
// Concrete implementations
|
||||
public class MinioStorageProvider : IStorageProvider { }
|
||||
public class AliyunOssStorageProvider : IStorageProvider { }
|
||||
|
||||
// Factory pattern for provider selection
|
||||
public class StorageProviderFactory
|
||||
{
|
||||
public IStorageProvider CreateProvider(string providerName) { }
|
||||
}
|
||||
```
|
||||
|
||||
**File Location**: [`services/storage-service-net/`](file:///Users/velikho/Desktop/WORKING/Base/services/storage-service-net)
|
||||
|
||||
---
|
||||
|
||||
### Real-World Example: IAM Service / Ví dụ Thực tế: IAM Service
|
||||
|
||||
**EN**: Identity and Access Management service handling authentication, authorization, and RBAC.
|
||||
|
||||
**VI**: Service quản lý định danh và truy cập xử lý xác thực, phân quyền và RBAC.
|
||||
|
||||
**Key Features / Tính năng chính**:
|
||||
- JWT authentication (RS256)
|
||||
- Role-Based Access Control (RBAC)
|
||||
- MFA support (TOTP)
|
||||
- Session management
|
||||
- Permission caching
|
||||
|
||||
**Technologies Used / Công nghệ sử dụng**:
|
||||
- .NET 10, Duende IdentityServer
|
||||
- Entity Framework Core
|
||||
- Redis (caching)
|
||||
- PostgreSQL (Neon)
|
||||
|
||||
**File Location**: [`services/iam-service-net/`](file:///Users/velikho/Desktop/WORKING/Base/services/iam-service-net)
|
||||
|
||||
## Data Flow / Luồng Dữ liệu
|
||||
|
||||
@@ -158,15 +240,28 @@ erDiagram
|
||||
|
||||
## Performance Characteristics / Đặc điểm Hiệu suất
|
||||
|
||||
**EN**: Description of performance expectations and optimizations
|
||||
**EN**: Description of performance expectations and optimizations based on GoodGo Platform standards.
|
||||
|
||||
**VI**: Mô tả kỳ vọng hiệu suất và tối ưu hóa
|
||||
**VI**: Mô tả kỳ vọng hiệu suất và tối ưu hóa dựa trên chuẩn GoodGo Platform.
|
||||
|
||||
| Metric / Chỉ số | Target / Mục tiêu | Notes / Ghi chú |
|
||||
|------------------|-------------------|-----------------|
|
||||
| Response Time / Thời gian phản hồi | < 100ms | P95 |
|
||||
| Throughput / Thông lượng | 1000 req/s | Peak load |
|
||||
| Memory Usage / Sử dụng RAM | < 512MB | Per instance |
|
||||
| API Response Time (P95) / Thời gian phản hồi API | < 200ms | Excluding external API calls |
|
||||
| API Response Time (P99) / Thời gian phản hồi API | < 500ms | Peak load scenarios |
|
||||
| Throughput / Thông lượng | 1000 req/s | Per service instance |
|
||||
| Database Query Time (P95) / Truy vấn Database | < 50ms | Simple queries with indexes |
|
||||
| Cache Hit Rate (L1) / Tỷ lệ cache hit | > 40% | In-memory cache |
|
||||
| Cache Hit Rate (L2) / Tỷ lệ cache hit | > 80% | Redis cache |
|
||||
| Service Availability / Tính khả dụng | > 99.9% | Monthly uptime target |
|
||||
| Error Rate / Tỷ lệ lỗi | < 1% | 4xx + 5xx errors |
|
||||
|
||||
**Optimization Strategies / Chiến lược Tối ưu**:
|
||||
- **Multi-layer caching**: L1 (Memory) + L2 (Redis)
|
||||
- **Connection pooling**: For PostgreSQL connections
|
||||
- **Pagination**: Max 100 items per page for list endpoints
|
||||
- **Database indexes**: On frequently queried fields
|
||||
- **Async events**: Fire-and-forget với RabbitMQ
|
||||
- **CDN**: For static assets (Next.js)
|
||||
|
||||
## Security Considerations / Cân nhắc Bảo mật
|
||||
|
||||
@@ -179,23 +274,55 @@ erDiagram
|
||||
|
||||
## Deployment / Triển khai
|
||||
|
||||
**EN**: How this architecture is deployed and scaled
|
||||
**EN**: How this architecture is deployed and scaled in GoodGo Platform.
|
||||
|
||||
**VI**: Cách kiến trúc này được triển khai và mở rộng
|
||||
**VI**: Cách kiến trúc này được triển khai và mở rộng trong GoodGo Platform.
|
||||
|
||||
### Traefik API Gateway Routing
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
storage-service-net:
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.storage-service.rule=PathPrefix(`/api/v1/storage`)"
|
||||
- "traefik.http.services.storage-service.loadbalancer.server.port=8080"
|
||||
- "traefik.http.routers.storage-service.middlewares=strip-prefix@docker"
|
||||
```
|
||||
|
||||
### Kubernetes Deployment
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
LB[Load Balancer] --> A[Instance 1]
|
||||
LB --> B[Instance 2]
|
||||
LB --> C[Instance 3]
|
||||
A --> DB[(Database)]
|
||||
LB[Load Balancer] --> Traefik[Traefik Gateway<br/>2-3 replicas]
|
||||
Traefik --> A[Service A<br/>2-10 replicas HPA]
|
||||
Traefik --> B[Service B<br/>2-10 replicas HPA]
|
||||
Traefik --> C[Service C<br/>2-10 replicas HPA]
|
||||
A --> DB[(Neon PostgreSQL<br/>Serverless)]
|
||||
B --> DB
|
||||
C --> DB
|
||||
A --> Cache[(Redis)]
|
||||
A --> Cache[(Redis Cluster<br/>3 nodes)]
|
||||
B --> Cache
|
||||
C --> Cache
|
||||
|
||||
style LB fill:#1565c0,stroke:#fff,stroke-width:2px,color:#fff
|
||||
style Traefik fill:#0f4c81,stroke:#fff,stroke-width:2px,color:#fff
|
||||
style A fill:#283593,stroke:#fff,stroke-width:2px,color:#fff
|
||||
style B fill:#4527a0,stroke:#fff,stroke-width:2px,color:#fff
|
||||
style C fill:#4527a0,stroke:#fff,stroke-width:2px,color:#fff
|
||||
style DB fill:#5e35b1,stroke:#fff,stroke-width:2px,color:#fff
|
||||
style Cache fill:#ef6c00,stroke:#fff,stroke-width:2px,color:#fff
|
||||
```
|
||||
|
||||
**Resource Allocation / Phân bổ Tài nguyên**:
|
||||
|
||||
| Service | Requests | Limits |
|
||||
|---------|----------|--------|
|
||||
| **Microservices** | 256Mi RAM, 250m CPU | 512Mi RAM, 500m CPU |
|
||||
| **Traefik** | 512Mi RAM, 500m CPU | 1Gi RAM, 1000m CPU |
|
||||
| **Redis** | 2Gi RAM, 1 CPU | 4Gi RAM, 2 CPU |
|
||||
|
||||
## Monitoring & Observability / Giám sát & Khả năng quan sát
|
||||
|
||||
**EN**: How to monitor this architecture, key metrics, alerts
|
||||
@@ -212,9 +339,20 @@ graph LR
|
||||
|
||||
## Related Documentation / Tài liệu Liên quan
|
||||
|
||||
- [Related Arch Doc 1](../architecture/related-doc-1.md) - EN: Description / VI: Mô tả
|
||||
- [Related Guide](../guides/related-guide.md) - EN: Description / VI: Mô tả
|
||||
- [Related Skill](../skills/related-skill.md) - EN: Description / VI: Mô tả
|
||||
### Architecture Documents
|
||||
- [System Design](../architecture/system-design.md) - EN: Overall platform architecture / VI: Kiến trúc tổng thể platform
|
||||
- [Microservices Communication](../architecture/microservices-communication.md) - EN: Service communication patterns / VI: Patterns giao tiếp services
|
||||
- [Caching Architecture](../architecture/caching-architecture.md) - EN: Redis caching strategies / VI: Chiến lược Redis caching
|
||||
- [Event-Driven Architecture](../architecture/event-driven-architecture.md) - EN: RabbitMQ event patterns / VI: Patterns RabbitMQ events
|
||||
|
||||
### Skills Reference
|
||||
- [CQRS with MediatR](../skills/cqrs-mediatr.md) - EN: CQRS pattern / VI: Pattern CQRS
|
||||
- [Repository Pattern](../skills/repository-pattern.md) - EN: EF Core repository / VI: Repository EF Core
|
||||
- [Domain-Driven Design](../skills/domain-driven-design.md) - EN: DDD patterns / VI: Patterns DDD
|
||||
|
||||
### Guides
|
||||
- [Local Development](../guides/local-development.md) - EN: Setup dev environment / VI: Setup môi trường dev
|
||||
- [Deployment](../guides/deployment.md) - EN: Kubernetes deployment / VI: Triển khai Kubernetes
|
||||
|
||||
## References / Tham khảo
|
||||
|
||||
|
||||
@@ -29,14 +29,22 @@ Template này cung cấp cấu trúc sẵn sàng production cho microservices .N
|
||||
|
||||
```bash
|
||||
# Sao chép template sang service mới
|
||||
cp -r services/_template_dot_net services/your-service-name
|
||||
cd services/your-service-name
|
||||
cp -r services/_template_dot_net services/your-service-name-net
|
||||
cd services/your-service-name-net
|
||||
|
||||
# Đổi tên tất cả "MyService" thành "YourService"
|
||||
# Ví dụ: MyService → StorageService, UserService, PaymentService
|
||||
find . -type f -name "*.cs" -exec sed -i '' 's/MyService/YourService/g' {} +
|
||||
find . -type f -name "*.csproj" -exec sed -i '' 's/MyService/YourService/g' {} +
|
||||
find . -type f -name "*.sln" -exec sed -i '' 's/MyService/YourService/g' {} +
|
||||
```
|
||||
|
||||
**Naming Convention**:
|
||||
- Service folder: `{service-name}-net` (ví dụ: `storage-service-net`, `iam-service-net`)
|
||||
- Projects: `{ServiceName}.API`, `{ServiceName}.Domain`, `{ServiceName}.Infrastructure`
|
||||
- DbContext: `{ServiceName}Context` (ví dụ: `StorageServiceContext`)
|
||||
- Namespace: `GoodGo.Services.{ServiceName}` (ví dụ: `GoodGo.Services.StorageService`)
|
||||
|
||||
### 2. Cấu Hình Môi Trường
|
||||
|
||||
```bash
|
||||
@@ -62,36 +70,54 @@ dotnet run --project src/MyService.API
|
||||
## Cấu Trúc Dự Án
|
||||
|
||||
```
|
||||
_template_dot_net/
|
||||
{service-name}-net/ # Ví dụ: storage-service-net
|
||||
├── src/
|
||||
│ ├── MyService.API/ # Lớp Presentation (Controllers, CQRS)
|
||||
│ ├── {ServiceName}.API/ # Lớp Presentation (Controllers, CQRS)
|
||||
│ │ ├── Controllers/ # Các API endpoints
|
||||
│ │ ├── Application/ # Triển khai CQRS
|
||||
│ │ │ ├── Commands/ # Thao tác ghi (MediatR)
|
||||
│ │ │ ├── Queries/ # Thao tác đọc
|
||||
│ │ │ ├── Behaviors/ # MediatR pipeline behaviors
|
||||
│ │ │ └── Validations/ # FluentValidation validators
|
||||
│ │ ├── Middlewares/ # Custom middlewares
|
||||
│ │ └── Program.cs # Điểm vào ứng dụng
|
||||
│ │
|
||||
│ ├── MyService.Domain/ # Lớp Domain (Business logic thuần túy)
|
||||
│ ├── {ServiceName}.Domain/ # Lớp Domain (Business logic thuần túy)
|
||||
│ │ ├── AggregatesModel/ # Aggregate roots và entities
|
||||
│ │ ├── Events/ # Domain events
|
||||
│ │ ├── Exceptions/ # Domain exceptions
|
||||
│ │ └── SeedWork/ # Base classes
|
||||
│ │ └── SeedWork/ # Base classes (Entity, IAggregateRoot)
|
||||
│ │
|
||||
│ └── MyService.Infrastructure/ # Lớp Infrastructure
|
||||
│ ├── EntityConfigurations/ # Cấu hình EF Core
|
||||
│ └── {ServiceName}.Infrastructure/ # Lớp Infrastructure
|
||||
│ ├── EntityConfigurations/ # Cấu hình EF Core (Fluent API)
|
||||
│ ├── Repositories/ # Triển khai repositories
|
||||
│ └── MyServiceContext.cs # DbContext với Unit of Work
|
||||
│ ├── Providers/ # External service providers (nếu có)
|
||||
│ ├── Services/ # Infrastructure services
|
||||
│ ├── Migrations/ # EF Core migrations
|
||||
│ └── {ServiceName}Context.cs # DbContext với Unit of Work
|
||||
│
|
||||
├── tests/
|
||||
│ ├── MyService.UnitTests/ # Unit tests
|
||||
│ └── MyService.FunctionalTests/ # Integration tests
|
||||
│ ├── {ServiceName}.UnitTests/ # Unit tests
|
||||
│ └── {ServiceName}.FunctionalTests/ # Integration tests
|
||||
│
|
||||
├── docs/
|
||||
│ ├── en/ # English documentation
|
||||
│ │ ├── README.md
|
||||
│ │ └── ARCHITECTURE.md
|
||||
│ └── vi/ # Vietnamese documentation
|
||||
│ ├── README.md
|
||||
│ └── ARCHITECTURE.md
|
||||
│
|
||||
├── Dockerfile # Multi-stage Docker build
|
||||
└── docker-compose.yml # Thiết lập phát triển local
|
||||
├── docker-compose.yml # Thiết lập phát triển local
|
||||
└── README.md # Service overview (bilingual)
|
||||
```
|
||||
|
||||
**Examples thực tế**:
|
||||
- Storage Service: [`services/storage-service-net/`](file:///Users/velikho/Desktop/WORKING/Base/services/storage-service-net)
|
||||
- IAM Service: [`services/iam-service-net/`](file:///Users/velikho/Desktop/WORKING/Base/services/iam-service-net)
|
||||
- Chat Service: [`services/chat-service-net/`](file:///Users/velikho/Desktop/WORKING/Base/services/chat-service-net)
|
||||
|
||||
## Kiến Trúc
|
||||
|
||||
```mermaid
|
||||
@@ -204,12 +230,43 @@ Request → LoggingBehavior → ValidatorBehavior → TransactionBehavior → Ha
|
||||
|
||||
## Biến Môi Trường
|
||||
|
||||
### Required / Bắt buộc
|
||||
|
||||
| Biến | Mô Tả | Mặc định |
|
||||
|------|-------|----------|
|
||||
| `ASPNETCORE_ENVIRONMENT` | Tên môi trường | `Development` |
|
||||
| `DATABASE_URL` | Kết nối PostgreSQL | - |
|
||||
| `REDIS_URL` | Kết nối Redis | - |
|
||||
| `JWT_SECRET` | Secret ký JWT | - |
|
||||
| `DATABASE_URL` | Kết nối Neon PostgreSQL | - |
|
||||
| `ConnectionStrings__DefaultConnection` | Connection string format chuẩn | - |
|
||||
|
||||
### Optional / Tùy chọn
|
||||
|
||||
| Biến | Mô Tả | Mặc định |
|
||||
|------|-------|----------|
|
||||
| `REDIS_URL` | Kết nối Redis (cache) | - |
|
||||
| `RabbitMQ__Host` | RabbitMQ hostname | `localhost` |
|
||||
| `RabbitMQ__Port` | RabbitMQ port | `5672` |
|
||||
| `RabbitMQ__Username` | RabbitMQ username | `guest` |
|
||||
| `RabbitMQ__Password` | RabbitMQ password | `guest` |
|
||||
|
||||
### Inter-Service Communication
|
||||
|
||||
| Biến | Mô Tả | Mặc định |
|
||||
|------|-------|----------|
|
||||
| `IamService__BaseUrl` | IAM Service URL | `http://iam-service-net:5001` |
|
||||
| `Services__InternalApiKey` | Shared secret cho service-to-service auth | - |
|
||||
|
||||
### Multi-Provider Pattern (Example: Storage Service)
|
||||
|
||||
| Biến | Mô Tả | Mặc định |
|
||||
|------|-------|----------|
|
||||
| `Storage__Provider` | Provider: `minio` hoặc `aliyun` | `minio` |
|
||||
| `Storage__DefaultBucket` | Default bucket name | `storage` |
|
||||
| `Storage__MinIO__Endpoint` | MinIO endpoint | `localhost:9000` |
|
||||
| `Storage__MinIO__AccessKey` | MinIO access key | - |
|
||||
| `Storage__MinIO__SecretKey` | MinIO secret key | - |
|
||||
| `Storage__AliyunOSS__Endpoint` | Aliyun OSS endpoint | - |
|
||||
| `Storage__AliyunOSS__AccessKeyId` | Aliyun access key | - |
|
||||
| `Storage__AliyunOSS__AccessKeySecret` | Aliyun secret key | - |
|
||||
|
||||
## Kiểm Thử
|
||||
|
||||
@@ -257,23 +314,223 @@ spec:
|
||||
port: 8080
|
||||
```
|
||||
|
||||
## Patterns Nâng cao
|
||||
|
||||
### Multi-Provider Pattern
|
||||
|
||||
**Sử dụng khi**: Service cần hỗ trợ nhiều external providers (storage, payment, SMS)
|
||||
|
||||
**Example**: Storage Service với MinIO và Aliyun OSS
|
||||
|
||||
```csharp
|
||||
// Domain - Interface
|
||||
public interface IStorageProvider
|
||||
{
|
||||
Task<string> UploadFileAsync(Stream fileStream, string fileName, CancellationToken ct);
|
||||
Task<Stream> DownloadFileAsync(string objectKey, CancellationToken ct);
|
||||
Task DeleteFileAsync(string objectKey, CancellationToken ct);
|
||||
Task<string> GeneratePresignedUrlAsync(string objectKey, int expiryMinutes, CancellationToken ct);
|
||||
}
|
||||
|
||||
// Infrastructure - MinIO Implementation
|
||||
public class MinioStorageProvider : IStorageProvider
|
||||
{
|
||||
private readonly MinioClient _client;
|
||||
// Implementation...
|
||||
}
|
||||
|
||||
// Infrastructure - Aliyun OSS Implementation
|
||||
public class AliyunOssStorageProvider : IStorageProvider
|
||||
{
|
||||
private readonly OssClient _client;
|
||||
// Implementation...
|
||||
}
|
||||
|
||||
// API - Provider Factory
|
||||
public class StorageProviderFactory
|
||||
{
|
||||
public IStorageProvider CreateProvider(IConfiguration config)
|
||||
{
|
||||
var provider = config["Storage:Provider"];
|
||||
return provider?.ToLower() switch
|
||||
{
|
||||
"minio" => new MinioStorageProvider(config),
|
||||
"aliyun" => new AliyunOssStorageProvider(config),
|
||||
_ => throw new InvalidOperationException($"Unknown provider: {provider}")
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**File Reference**: [`StorageService.Infrastructure/Providers/`](file:///Users/velikho/Desktop/WORKING/Base/services/storage-service-net/src/StorageService.Infrastructure/Providers)
|
||||
|
||||
---
|
||||
|
||||
### Inter-Service Authentication Pattern
|
||||
|
||||
**Sử dụng khi**: Service cần validate JWT tokens với IAM Service
|
||||
|
||||
```csharp
|
||||
// Infrastructure - IAM Service Client
|
||||
public class IamServiceClient
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly IConfiguration _config;
|
||||
|
||||
public IamServiceClient(HttpClient httpClient, IConfiguration config)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_config = config;
|
||||
_httpClient.BaseAddress = new Uri(_config["IamService:BaseUrl"]);
|
||||
}
|
||||
|
||||
public async Task<UserInfo> ValidateTokenAsync(string token, CancellationToken ct)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, "/api/v1/auth/validate")
|
||||
{
|
||||
Headers = { { "Authorization", $"Bearer {token}" } }
|
||||
};
|
||||
|
||||
var response = await _httpClient.SendAsync(request, ct);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await response.Content.ReadFromJsonAsync<UserInfo>(ct);
|
||||
}
|
||||
}
|
||||
|
||||
// API - Middleware
|
||||
public class JwtValidationMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IamServiceClient _iamClient;
|
||||
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
|
||||
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
var userInfo = await _iamClient.ValidateTokenAsync(token, context.RequestAborted);
|
||||
context.Items["UserId"] = userInfo.UserId;
|
||||
}
|
||||
|
||||
await _next(context);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Có Gì Mới Trong .NET 10
|
||||
|
||||
- Tính năng ngôn ngữ **C# 14**
|
||||
- Hỗ trợ **Native AOT** được cải thiện
|
||||
- Hiệu suất **async/await** tốt hơn
|
||||
- **JSON serialization** được nâng cao
|
||||
- **JSON serialization** được nâng cao (System.Text.Json)
|
||||
- Hỗ trợ **LTS** 3 năm (đến tháng 11/2028)
|
||||
- **Entity Framework Core 10** với performance improvements
|
||||
|
||||
## Tích hợp với Platform
|
||||
|
||||
### Traefik Routing
|
||||
|
||||
Thêm labels vào `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
your-service-net:
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: services/your-service-net/Dockerfile
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.your-service.rule=PathPrefix(`/api/v1/your-service`)"
|
||||
- "traefik.http.services.your-service.loadbalancer.server.port=8080"
|
||||
- "traefik.http.routers.your-service.middlewares=strip-prefix@docker"
|
||||
```
|
||||
|
||||
### Neon PostgreSQL Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Host=ep-xxx.neon.tech;Database=your_service;Username=xxx;Password=xxx;SSL Mode=Require;Trust Server Certificate=true"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Best Practices**:
|
||||
- Sử dụng connection pooling: `Pooling=true;Maximum Pool Size=100`
|
||||
- Enable SSL: `SSL Mode=Require`
|
||||
- Set command timeout: `Command Timeout=30`
|
||||
|
||||
### RabbitMQ Integration (thay vì Kafka)
|
||||
|
||||
```csharp
|
||||
// Domain Event
|
||||
public record FileUploadedEvent(string FileId, string UserId, long FileSize) : IDomainEvent;
|
||||
|
||||
// Infrastructure - Event Publisher
|
||||
public class RabbitMqEventPublisher : IEventPublisher
|
||||
{
|
||||
private readonly IConnection _connection;
|
||||
private readonly IModel _channel;
|
||||
|
||||
public async Task PublishAsync<T>(T @event, CancellationToken ct) where T : IDomainEvent
|
||||
{
|
||||
var message = JsonSerializer.Serialize(@event);
|
||||
var body = Encoding.UTF8.GetBytes(message);
|
||||
|
||||
_channel.BasicPublish(
|
||||
exchange: "domain_events",
|
||||
routingKey: typeof(T).Name,
|
||||
body: body
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tài Liệu Liên Quan
|
||||
|
||||
- [Chi Tiết Kiến Trúc](../architecture/microservices-communication.md)
|
||||
- [DDD Patterns](../architecture/system-design.md)
|
||||
- [Hướng Dẫn Triển Khai](../guides/deployment.md)
|
||||
### Architecture
|
||||
- [System Design](../architecture/system-design.md) - Kiến trúc tổng thể GoodGo Platform
|
||||
- [Microservices Communication](../architecture/microservices-communication.md) - Patterns giao tiếp
|
||||
- [Caching Architecture](../architecture/caching-architecture.md) - Chiến lược Redis caching
|
||||
|
||||
## Tài Nguyên
|
||||
### Skills
|
||||
- [CQRS with MediatR](../skills/cqrs-mediatr.md) - CQRS pattern implementation
|
||||
- [Repository Pattern](../skills/repository-pattern.md) - EF Core repository pattern
|
||||
- [Domain-Driven Design](../skills/domain-driven-design.md) - DDD tactical patterns
|
||||
- [Error Handling](../skills/error-handling-patterns.md) - Exception handling patterns
|
||||
|
||||
- [eShopOnContainers](https://github.com/dotnet-architecture/eShopOnContainers)
|
||||
- [Tài liệu .NET 10](https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-10)
|
||||
- [MediatR](https://github.com/jbogard/MediatR)
|
||||
- [FluentValidation](https://docs.fluentvalidation.net/)
|
||||
### Guides
|
||||
- [Local Development](../guides/local-development.md) - Setup môi trường dev
|
||||
- [Deployment](../guides/deployment.md) - Deploy lên Kubernetes
|
||||
|
||||
## Tài Nguyên Bổ sung
|
||||
|
||||
### Microsoft Official
|
||||
- [.NET 10 Documentation](https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-10)
|
||||
- [Entity Framework Core 10](https://docs.microsoft.com/en-us/ef/core/)
|
||||
- [ASP.NET Core 10](https://docs.microsoft.com/en-us/aspnet/core/)
|
||||
|
||||
### Architecture References
|
||||
- [eShopOnContainers](https://github.com/dotnet-architecture/eShopOnContainers) - Microservices reference architecture
|
||||
- [.NET Microservices Architecture Book](https://docs.microsoft.com/en-us/dotnet/architecture/microservices/)
|
||||
|
||||
### Libraries
|
||||
- [MediatR](https://github.com/jbogard/MediatR) - CQRS implementation
|
||||
- [FluentValidation](https://docs.fluentvalidation.net/) - Validation library
|
||||
- [Polly](https://github.com/App-vNext/Polly) - Resilience and transient-fault-handling
|
||||
|
||||
### Tools
|
||||
- [EF Core Tools](https://docs.microsoft.com/en-us/ef/core/cli/dotnet) - Migrations và scaffolding
|
||||
- [Neon PostgreSQL](https://neon.tech/docs) - Serverless Postgres documentation
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2026-01-14
|
||||
**Template Version**: 2.0
|
||||
**Maintained By**: GoodGo Architecture Team
|
||||
|
||||
@@ -45,6 +45,25 @@ Trước khi bắt đầu hướng dẫn này, hãy đảm bảo bạn có:
|
||||
# EN: Verify prerequisites / VI: Xác minh yêu cầu
|
||||
node --version # Should be 20 or higher / Phải là 20 hoặc cao hơn
|
||||
docker --version # Should be installed / Phải được cài đặt
|
||||
dotnet --version # Should be 10.0+ for .NET services / Phải là 10.0+ cho .NET services
|
||||
```
|
||||
|
||||
**Example: Local Development Setup for Storage Service**
|
||||
```bash
|
||||
# Clone repository
|
||||
cd /Users/velikho/Desktop/WORKING/Base
|
||||
|
||||
# Install dependencies (.NET)
|
||||
cd services/storage-service-net
|
||||
dotnet restore
|
||||
|
||||
# Setup infrastructure
|
||||
cd ../../deployments/local
|
||||
docker-compose up -d postgres redis minio
|
||||
|
||||
# Run migrations
|
||||
cd ../../services/storage-service-net
|
||||
dotnet ef database update --project src/StorageService.Infrastructure --startup-project src/StorageService.API
|
||||
```
|
||||
|
||||
## Overview / Tổng quan
|
||||
@@ -96,11 +115,53 @@ touch .env.local
|
||||
**Example Content / Nội dung ví dụ**:
|
||||
```env
|
||||
# EN: Environment variables / VI: Biến môi trường
|
||||
PORT=5000
|
||||
NODE_ENV=development
|
||||
ASPNETCORE_ENVIRONMENT=Development
|
||||
DATABASE_URL=postgresql://localhost:5432/mydb
|
||||
REDIS_URL=redis://localhost:6379
|
||||
Storage__Provider=minio
|
||||
Storage__MinIO__Endpoint=localhost:9000
|
||||
Storage__MinIO__AccessKey=minioadmin
|
||||
Storage__MinIO__SecretKey=minioadmin
|
||||
```
|
||||
|
||||
### Real-World Example / Ví dụ Thực tế: Traefik Routing Setup
|
||||
|
||||
**EN**: How to configure Traefik routing for a new service.
|
||||
|
||||
**VI**: Cách cấu hình Traefik routing cho service mới.
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
your-service-net:
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: services/your-service-net/Dockerfile
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
- DATABASE_URL=${DATABASE_URL}
|
||||
labels:
|
||||
# Enable Traefik
|
||||
- "traefik.enable=true"
|
||||
# Define routing rule
|
||||
- "traefik.http.routers.your-service.rule=PathPrefix(`/api/v1/your-service`)"
|
||||
# Specify service port
|
||||
- "traefik.http.services.your-service.loadbalancer.server.port=8080"
|
||||
# Strip prefix middleware
|
||||
- "traefik.http.routers.your-service.middlewares=strip-prefix@docker"
|
||||
networks:
|
||||
- goodgo-network
|
||||
|
||||
networks:
|
||||
goodgo-network:
|
||||
external: true
|
||||
```
|
||||
|
||||
**Expected Result / Kết quả mong đợi**:
|
||||
- ✅ Service accessible at `http://localhost/api/v1/your-service`
|
||||
- ✅ Traefik dashboard shows the service at `http://localhost:8080`
|
||||
- ✅ Health check endpoint works: `http://localhost/api/v1/your-service/health`
|
||||
|
||||
### Step 2 / Bước 2: [Action Title]
|
||||
|
||||
**EN**: Continue with next step explanation...
|
||||
@@ -142,9 +203,35 @@ curl http://localhost:5000/health
|
||||
|
||||
### Verification Checklist / Danh sách kiểm tra
|
||||
|
||||
- [ ] Check 1 / Kiểm tra 1: Description / Mô tả
|
||||
- [ ] Check 2 / Kiểm tra 2: Description / Mô tả
|
||||
- [ ] Check 3 / Kiểm tra 3: Description / Mô tả
|
||||
**For .NET Services**:
|
||||
- [ ] Check 1: Service builds successfully / Service build thành công
|
||||
```bash
|
||||
dotnet build
|
||||
```
|
||||
- [ ] Check 2: Database migrations applied / Migrations đã apply
|
||||
```bash
|
||||
dotnet ef database update --project src/{ServiceName}.Infrastructure --startup-project src/{ServiceName}.API
|
||||
```
|
||||
- [ ] Check 3: Service responds to health checks / Service phản hồi health checks
|
||||
```bash
|
||||
curl http://localhost:8080/health
|
||||
# Expected: {"status":"Healthy"}
|
||||
```
|
||||
- [ ] Check 4: Swagger UI accessible / Swagger UI truy cập được
|
||||
```bash
|
||||
open http://localhost:8080/swagger
|
||||
```
|
||||
|
||||
**For Traefik Integration**:
|
||||
- [ ] Check 5: Service registered in Traefik / Service đăng ký trong Traefik
|
||||
```bash
|
||||
curl http://localhost:8080/api/http/routers
|
||||
# Should see your-service router
|
||||
```
|
||||
- [ ] Check 6: API accessible via gateway / API truy cập được qua gateway
|
||||
```bash
|
||||
curl http://localhost/api/v1/your-service/health
|
||||
```
|
||||
|
||||
## Common Issues / Vấn đề Thường gặp
|
||||
|
||||
@@ -176,19 +263,26 @@ step-2
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Problem[Problem Occurs] --> Check1{Check 1:<br/>Condition?}
|
||||
Check1 -->|Yes| Solution1[Solution 1]
|
||||
Check1 -->|No| Check2{Check 2:<br/>Condition?}
|
||||
Check2 -->|Yes| Solution2[Solution 2]
|
||||
Check2 -->|No| Check3{Check 3:<br/>Condition?}
|
||||
Check3 -->|Yes| Solution3[Solution 3]
|
||||
Check3 -->|No| Support[Contact Support]
|
||||
Problem[Service not accessible] --> Check1{Traefik<br/>running?}
|
||||
Check1 -->|No| Solution1[Start Traefik:<br/>docker-compose up traefik]
|
||||
Check1 -->|Yes| Check2{Service<br/>container running?}
|
||||
Check2 -->|No| Solution2[Start service:<br/>docker-compose up your-service]
|
||||
Check2 -->|Yes| Check3{Database<br/>connection OK?}
|
||||
Check3 -->|No| Solution3[Check DATABASE_URL<br/>Run migrations]
|
||||
Check3 -->|Yes| Logs[Check service logs:<br/>docker-compose logs -f]
|
||||
|
||||
Solution1 --> Resolved{Resolved?}
|
||||
Solution2 --> Resolved
|
||||
Solution3 --> Resolved
|
||||
Resolved -->|No| Support
|
||||
Logs --> Resolved
|
||||
Resolved -->|No| Support[Check documentation:<br/>docs/vi/guides/troubleshooting.md]
|
||||
Resolved -->|Yes| Success([Success])
|
||||
|
||||
style Problem fill:#f8d7da,stroke:#721c24,stroke-width:2px
|
||||
style Success fill:#d4edda,stroke:#155724,stroke-width:2px
|
||||
style Check1 fill:#fff3cd,stroke:#856404,stroke-width:2px
|
||||
style Check2 fill:#fff3cd,stroke:#856404,stroke-width:2px
|
||||
style Check3 fill:#fff3cd,stroke:#856404,stroke-width:2px
|
||||
```
|
||||
|
||||
## Advanced Options / Tùy chọn Nâng cao
|
||||
@@ -214,9 +308,16 @@ advanced-command --option
|
||||
|
||||
**VI**: Làm gì sau khi hoàn thành hướng dẫn này.
|
||||
|
||||
- [ ] Next step 1 / Bước tiếp theo 1: [Related Guide](../guides/related-guide.md)
|
||||
- [ ] Next step 2 / Bước tiếp theo 2: [Another Guide](../guides/another-guide.md)
|
||||
- [ ] Next step 3 / Bước tiếp theo 3: [Deep Dive](../skills/deep-dive.md)
|
||||
**For .NET Services**:
|
||||
- [ ] Next step 1: [Implement CQRS Commands](../skills/cqrs-mediatr.md)
|
||||
- [ ] Next step 2: [Add Repository Pattern](../skills/repository-pattern.md)
|
||||
- [ ] Next step 3: [Setup Redis Caching](../skills/redis-caching.md)
|
||||
- [ ] Next step 4: [Configure Observability](../guides/observability.md)
|
||||
|
||||
**For Deployment**:
|
||||
- [ ] Next step 1: [Kubernetes Deployment](../guides/deployment.md)
|
||||
- [ ] Next step 2: [Configure CI/CD Pipeline](../guides/ci-cd.md)
|
||||
- [ ] Next step 3: [Setup Monitoring](../guides/observability.md)
|
||||
|
||||
## Additional Resources / Tài nguyên Bổ sung
|
||||
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
- Security considerations
|
||||
- Deployment strategy
|
||||
|
||||
**Ví dụ**: [`system-design.md`](../architecture/system-design.md)
|
||||
**Ví dụ**:
|
||||
- Storage Service Architecture: [`storage-architecture.md`](../architecture/storage-architecture.md)
|
||||
- IAM Architecture: [`iam-proposal.md`](../architecture/iam-proposal.md)
|
||||
- System Design: [`system-design.md`](../architecture/system-design.md)
|
||||
|
||||
### 2. Guide Template - [`guide.md`](./guide.md)
|
||||
|
||||
@@ -31,7 +34,10 @@
|
||||
- Common issues & troubleshooting
|
||||
- FAQ section
|
||||
|
||||
**Ví dụ**: Hướng dẫn deployment, local development
|
||||
**Ví dụ**:
|
||||
- Local Development: [`local-development.md`](../guides/local-development.md)
|
||||
- Deployment to Kubernetes: [`deployment.md`](../guides/deployment.md)
|
||||
- IAM Authentication Guide: [`iam-authentication.md`](../guides/iam-authentication.md)
|
||||
|
||||
### 3. Skill/Pattern Template - [`skill-pattern.md`](./skill-pattern.md)
|
||||
|
||||
@@ -46,7 +52,11 @@
|
||||
- Common mistakes
|
||||
- Testing examples
|
||||
|
||||
**Ví dụ**: Repository pattern, RBAC pattern
|
||||
**Ví dụ**:
|
||||
- CQRS with MediatR: [`cqrs-mediatr.md`](../skills/cqrs-mediatr.md)
|
||||
- Repository Pattern: [`repository-pattern.md`](../skills/repository-pattern.md)
|
||||
- Redis Caching: [`redis-caching.md`](../skills/redis-caching.md)
|
||||
- Domain-Driven Design: [`domain-driven-design.md`](../skills/domain-driven-design.md)
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -61,7 +71,13 @@ Xác định loại tài liệu bạn cần tạo:
|
||||
|
||||
```bash
|
||||
# Ví dụ: Tạo architecture document mới
|
||||
cp docs/vi/templates/architecture.md docs/vi/architecture/ten-kien-truc-moi.md
|
||||
cp docs/vi/templates/architecture.md docs/vi/architecture/new-architecture-name.md
|
||||
|
||||
# Ví dụ: Tạo guide document mới
|
||||
cp docs/vi/templates/guide.md docs/vi/guides/new-guide-name.md
|
||||
|
||||
# Ví dụ: Tạo skill document mới
|
||||
cp docs/vi/templates/skill-pattern.md docs/vi/skills/new-skill-name.md
|
||||
```
|
||||
|
||||
### Bước 3: Thay thế Placeholders
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
Template này cung cấp nền tảng hoàn chỉnh, sẵn sàng production để xây dựng các microservice với:
|
||||
|
||||
> **Lưu ý**: Template này dành cho tương lai. Hiện tại dự án GoodGo chủ yếu sử dụng .NET services. Xem [dotnet-template.md](./dotnet-template.md) cho template đang sử dụng.
|
||||
|
||||
- **Framework**: Express.js với TypeScript
|
||||
- **Database**: Prisma ORM với PostgreSQL
|
||||
- **Validation**: Zod cho validation biến môi trường và đầu vào
|
||||
|
||||
@@ -138,61 +138,45 @@ export class ExamplePattern {
|
||||
```
|
||||
|
||||
**File Location / Vị trí File**:
|
||||
- **Template**: [`_template/src/modules/example/example.pattern.ts`](file:///Users/velikho/Desktop/WORKING/Base/services/_template/src/modules/example/example.pattern.ts)
|
||||
- **Production**: [`iam-service/src/modules/example/example.pattern.ts`](file:///Users/velikho/Desktop/WORKING/Base/services/iam-service/src/modules/example/example.pattern.ts)
|
||||
- **Skill Template**: [`.agent/skills/skill-authoring/SKILL.md`](file:///Users/velikho/Desktop/WORKING/Base/.agent/skills/skill-authoring/SKILL.md)
|
||||
- **Example Skills**: [`.agent/skills/`](file:///Users/velikho/Desktop/WORKING/Base/.agent/skills)
|
||||
|
||||
### Advanced Implementation / Triển khai Nâng cao
|
||||
|
||||
**EN**: More complex implementation with additional features.
|
||||
**EN**: More complex implementation with additional features like caching and error handling.
|
||||
|
||||
**VI**: Triển khai phức tạp hơn với các tính năng bổ sung.
|
||||
**VI**: Triển khai phức tạp hơn với các tính năng bổ sung như caching và xử lý lỗi.
|
||||
|
||||
```typescript
|
||||
// EN: Advanced implementation with caching and error handling
|
||||
// VI: Triển khai nâng cao với caching và xử lý lỗi
|
||||
```csharp
|
||||
// EN: Advanced .NET implementation with caching
|
||||
// VI: Triển khai .NET nâng cao với caching
|
||||
|
||||
export class AdvancedExamplePattern extends ExamplePattern {
|
||||
constructor(
|
||||
dependency1: Dependency1,
|
||||
dependency2: Dependency2,
|
||||
private cache: CacheService,
|
||||
private logger: Logger
|
||||
) {
|
||||
super(dependency1, dependency2);
|
||||
}
|
||||
public class CachedStorageProvider : IStorageProvider
|
||||
{
|
||||
private readonly IStorageProvider _innerProvider;
|
||||
private readonly IDistributedCache _cache;
|
||||
private readonly ILogger<CachedStorageProvider> _logger;
|
||||
|
||||
async execute(input: InputType): Promise<OutputType> {
|
||||
// EN: Try cache first
|
||||
// VI: Thử cache trước
|
||||
const cacheKey = this.getCacheKey(input);
|
||||
const cached = await this.cache.get<OutputType>(cacheKey);
|
||||
|
||||
if (cached) {
|
||||
this.logger.info('Cache hit', { key: cacheKey });
|
||||
return cached;
|
||||
public async Task<string> UploadFileAsync(Stream fileStream, string fileName, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
// EN: Upload file
|
||||
// VI: Upload file
|
||||
var result = await _innerProvider.UploadFileAsync(fileStream, fileName, ct);
|
||||
|
||||
// EN: Invalidate cache
|
||||
// VI: Vô hiệu hóa cache
|
||||
await _cache.RemoveAsync($"file:{fileName}", ct);
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to upload file {FileName}", fileName);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// EN: Execute pattern logic
|
||||
// VI: Thực thi logic pattern
|
||||
const result = await super.execute(input);
|
||||
|
||||
// EN: Cache result
|
||||
// VI: Cache kết quả
|
||||
await this.cache.set(cacheKey, result, 300); // 5 minutes
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
// EN: Error handling
|
||||
// VI: Xử lý lỗi
|
||||
this.logger.error('Pattern execution failed', { error, input });
|
||||
throw new PatternExecutionError('Execution failed', { cause: error });
|
||||
}
|
||||
}
|
||||
|
||||
private getCacheKey(input: InputType): string {
|
||||
return `pattern:example:${JSON.stringify(input)}`;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -255,60 +239,76 @@ sequenceDiagram
|
||||
|
||||
## Usage Examples / Ví dụ Sử dụng
|
||||
|
||||
### Example 1 / Ví dụ 1: Basic Usage
|
||||
### Example 1: Multi-Provider Storage Pattern (Real-World)
|
||||
|
||||
**EN**: Basic usage scenario with explanation.
|
||||
**EN**: Real implementation from Storage Service.
|
||||
|
||||
**VI**: Tình huống sử dụng cơ bản với giải thích.
|
||||
**VI**: Triển khai thực tế từ Storage Service.
|
||||
|
||||
```typescript
|
||||
// EN: Setup
|
||||
// VI: Thiết lập
|
||||
const dependency1 = new Dependency1();
|
||||
const dependency2 = new Dependency2();
|
||||
const pattern = new ExamplePattern(dependency1, dependency2);
|
||||
```csharp
|
||||
// Domain interface
|
||||
public interface IStorageProvider
|
||||
{
|
||||
Task<string> UploadFileAsync(Stream fileStream, string fileName, CancellationToken ct);
|
||||
Task<string> GeneratePresignedUrlAsync(string objectKey, int expiryMinutes, CancellationToken ct);
|
||||
}
|
||||
|
||||
// EN: Execute pattern
|
||||
// VI: Thực thi pattern
|
||||
const input: InputType = {
|
||||
id: '123',
|
||||
data: 'example',
|
||||
};
|
||||
|
||||
const result = await pattern.execute(input);
|
||||
|
||||
console.log(result);
|
||||
// EN: Output / VI: Kết quả:
|
||||
// { success: true, data: { ... } }
|
||||
// Factory pattern
|
||||
public class StorageProviderFactory
|
||||
{
|
||||
public IStorageProvider CreateProvider(string providerName)
|
||||
{
|
||||
return providerName?.ToLower() switch
|
||||
{
|
||||
"minio" => _serviceProvider.GetRequiredService<MinioStorageProvider>(),
|
||||
"aliyun" => _serviceProvider.GetRequiredService<AliyunOssStorageProvider>(),
|
||||
_ => throw new InvalidOperationException($"Unknown provider: {providerName}")
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Example 2 / Ví dụ 2: Advanced Usage with Caching
|
||||
**File Reference**: [`services/storage-service-net/src/StorageService.Infrastructure/Providers/`](file:///Users/velikho/Desktop/WORKING/Base/services/storage-service-net/src/StorageService.Infrastructure/Providers)
|
||||
|
||||
**EN**: Advanced usage with caching enabled.
|
||||
---
|
||||
|
||||
**VI**: Sử dụng nâng cao với caching được bật.
|
||||
### Example 2: CQRS with MediatR (Real-World)
|
||||
|
||||
```typescript
|
||||
// EN: Setup with additional dependencies
|
||||
// VI: Thiết lập với các dependencies bổ sung
|
||||
const cache = new CacheService();
|
||||
const logger = new Logger();
|
||||
const pattern = new AdvancedExamplePattern(
|
||||
dependency1,
|
||||
dependency2,
|
||||
cache,
|
||||
logger
|
||||
);
|
||||
**EN**: Command handler pattern from actual services.
|
||||
|
||||
// EN: First call (cache miss)
|
||||
// VI: Lần gọi đầu tiên (cache miss)
|
||||
const result1 = await pattern.execute(input);
|
||||
**VI**: Pattern command handler từ các services thực tế.
|
||||
|
||||
// EN: Second call (cache hit)
|
||||
// VI: Lần gọi thứ hai (cache hit)
|
||||
const result2 = await pattern.execute(input); // Returns cached result
|
||||
```csharp
|
||||
// Command
|
||||
public record CreateFileCommand(string FileName, Stream FileStream, string UserId)
|
||||
: IRequest<CreateFileCommandResult>;
|
||||
|
||||
// Handler
|
||||
public class CreateFileCommandHandler : IRequestHandler<CreateFileCommand, CreateFileCommandResult>
|
||||
{
|
||||
private readonly IStorageProvider _storageProvider;
|
||||
private readonly IFileRepository _fileRepository;
|
||||
|
||||
public async Task<CreateFileCommandResult> Handle(CreateFileCommand request, CancellationToken ct)
|
||||
{
|
||||
// Upload to storage
|
||||
var objectKey = await _storageProvider.UploadFileAsync(
|
||||
request.FileStream,
|
||||
request.FileName,
|
||||
ct
|
||||
);
|
||||
|
||||
// Save metadata
|
||||
var file = new File(request.FileName, objectKey, request.UserId);
|
||||
await _fileRepository.AddAsync(file, ct);
|
||||
|
||||
return new CreateFileCommandResult(file.Id);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**File Reference**: See [CQRS with MediatR Skill](../skills/cqrs-mediatr.md)
|
||||
|
||||
## Best Practices / Thực hành Tốt nhất
|
||||
|
||||
### EN: Recommended Practices
|
||||
@@ -372,81 +372,79 @@ if (input) {
|
||||
|
||||
## Testing / Kiểm thử
|
||||
|
||||
### Unit Test Example / Ví dụ Unit Test
|
||||
### Unit Test Example for .NET / Ví dụ Unit Test cho .NET
|
||||
|
||||
```typescript
|
||||
// EN: Unit test for the pattern
|
||||
// VI: Unit test cho pattern
|
||||
```csharp
|
||||
// EN: Unit test for CQRS command handler
|
||||
// VI: Unit test cho CQRS command handler
|
||||
|
||||
describe('ExamplePattern', () => {
|
||||
let pattern: ExamplePattern;
|
||||
let mockDep1: jest.Mocked<Dependency1>;
|
||||
let mockDep2: jest.Mocked<Dependency2>;
|
||||
using Xunit;
|
||||
using NSubstitute;
|
||||
|
||||
beforeEach(() => {
|
||||
mockDep1 = {
|
||||
transform: jest.fn(),
|
||||
} as any;
|
||||
mockDep2 = {} as any;
|
||||
public class CreateFileCommandHandlerTests
|
||||
{
|
||||
private readonly IStorageProvider _storageProvider;
|
||||
private readonly IFileRepository _fileRepository;
|
||||
private readonly CreateFileCommandHandler _handler;
|
||||
|
||||
pattern = new ExamplePattern(mockDep1, mockDep2);
|
||||
});
|
||||
public CreateFileCommandHandlerTests()
|
||||
{
|
||||
_storageProvider = Substitute.For<IStorageProvider>();
|
||||
_fileRepository = Substitute.For<IFileRepository>();
|
||||
_handler = new CreateFileCommandHandler(_storageProvider, _fileRepository);
|
||||
}
|
||||
|
||||
it('should execute successfully', async () => {
|
||||
// EN: Arrange
|
||||
// VI: Chuẩn bị
|
||||
const input = { id: '123', data: 'test' };
|
||||
const expectedProcessed = { transformed: true };
|
||||
mockDep1.transform.mockResolvedValue(expectedProcessed);
|
||||
[Fact]
|
||||
public async Task Handle_ValidCommand_CreatesFileSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var command = new CreateFileCommand("test.txt", Stream.Null, "user-123");
|
||||
_storageProvider.UploadFileAsync(Arg.Any<Stream>(), Arg.Any<string>(), Arg.Any<CancellationToken>())
|
||||
.Returns("object-key-123");
|
||||
|
||||
// EN: Act
|
||||
// VI: Thực thi
|
||||
const result = await pattern.execute(input);
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// EN: Assert
|
||||
// VI: Kiểm tra
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data).toEqual(expectedProcessed);
|
||||
expect(mockDep1.transform).toHaveBeenCalledWith(input);
|
||||
});
|
||||
|
||||
it('should throw error for invalid input', async () => {
|
||||
// EN: Expect error for null input
|
||||
// VI: Mong đợi lỗi cho đầu vào null
|
||||
await expect(pattern.execute(null as any))
|
||||
.rejects
|
||||
.toThrow('Input is required');
|
||||
});
|
||||
});
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.NotEmpty(result.FileId);
|
||||
await _fileRepository.Received(1).AddAsync(Arg.Any<File>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Reference**: See [Testing Patterns Skill](../skills/testing-patterns.md)
|
||||
|
||||
## Related Patterns / Patterns Liên quan
|
||||
|
||||
**EN**: Other patterns that complement or relate to this one.
|
||||
|
||||
**VI**: Các patterns khác bổ sung hoặc liên quan đến pattern này.
|
||||
|
||||
- [Related Pattern 1](./related-pattern-1.md) - EN: How it relates / VI: Cách nó liên quan
|
||||
- [Related Pattern 2](./related-pattern-2.md) - EN: Comparison / VI: So sánh
|
||||
- [Alternative Pattern](./alternative-pattern.md) - EN: When to use instead / VI: Khi nào sử dụng thay thế
|
||||
**GoodGo Skills**:
|
||||
- [CQRS with MediatR](../skills/cqrs-mediatr.md) - EN: Command/Query separation / VI: Tách biệt Command/Query
|
||||
- [Repository Pattern](../skills/repository-pattern.md) - EN: Data access abstraction / VI: Trừa tượng hóa truy cập dữ liệu
|
||||
- [Domain-Driven Design](../skills/domain-driven-design.md) - EN: DDD tactical patterns / VI: Patterns chiến thuật DDD
|
||||
- [Redis Caching](../skills/redis-caching.md) - EN: Distributed caching / VI: Caching phân tán
|
||||
- [Error Handling](../skills/error-handling-patterns.md) - EN: Exception patterns / VI: Patterns exception
|
||||
|
||||
## Real-World Examples / Ví dụ Thực tế
|
||||
|
||||
**EN**: Examples of this pattern used in the codebase.
|
||||
**EN**: Examples of this pattern used in the GoodGo codebase.
|
||||
|
||||
**VI**: Ví dụ về pattern này được sử dụng trong codebase.
|
||||
**VI**: Ví dụ về pattern này được sử dụng trong codebase GoodGo.
|
||||
|
||||
### Example from IAM Service
|
||||
### Storage Service - Multi-Provider Pattern
|
||||
|
||||
**File**: [`iam-service/src/modules/rbac/rbac.service.ts`](file:///Users/velikho/Desktop/WORKING/Base/services/iam-service/src/modules/rbac/rbac.service.ts)
|
||||
**File**: [`services/storage-service-net/src/StorageService.Infrastructure/Providers/`](file:///Users/velikho/Desktop/WORKING/Base/services/storage-service-net/src/StorageService.Infrastructure/Providers)
|
||||
|
||||
```typescript
|
||||
// EN: Real implementation from IAM service
|
||||
// VI: Triển khai thực tế từ IAM service
|
||||
export class RBACService implements ExamplePattern {
|
||||
// ... implementation
|
||||
}
|
||||
```
|
||||
**Pattern**: Factory pattern for switching between MinIO and Aliyun OSS providers.
|
||||
|
||||
### IAM Service - RBAC Pattern
|
||||
|
||||
**File**: [`services/iam-service-net/`](file:///Users/velikho/Desktop/WORKING/Base/services/iam-service-net)
|
||||
|
||||
**Pattern**: Role-Based Access Control implementation with permission caching.
|
||||
|
||||
## Additional Resources / Tài nguyên Bổ sung
|
||||
|
||||
|
||||
11
note.md
11
note.md
@@ -1,10 +1,3 @@
|
||||
Test Account
|
||||
Tài khoản: hongochai10@icloud.com
|
||||
Mật Khẩu: Velik@2026
|
||||
|
||||
|
||||
📊 Mức Độ Ưu Tiên
|
||||
Ưu Tiên Skills Lý Do
|
||||
Cao testing-patterns, repository-pattern, error-handling-patterns Core development patterns
|
||||
Trung bình cqrs-mediatr, docker-traefik, observability Infrastructure & architecture
|
||||
Thấp redis-caching, inter-service-communication, domain-driven-design, deployment-kubernetes Advanced patterns
|
||||
Bạn muốn tôi tạo skill nào trước? Hay cần tôi tạo implementation plan chi tiết cho tất cả các skills đề xuất?
|
||||
Mật Khẩu: Velik@2026
|
||||
Reference in New Issue
Block a user