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:
Ho Ngoc Hai
2026-01-14 12:21:51 +07:00
parent 6996e12ff0
commit 02e1053eb5
7 changed files with 722 additions and 217 deletions

View File

@@ -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