chore: update project documentation, audit reports, and initialize IDE configuration files
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 29s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m42s
Deploy / Build Web Image (push) Failing after 27s
Deploy / Build AI Services Image (push) Failing after 29s
E2E Tests / Playwright E2E (push) Failing after 43s
Deploy / Build API Image (push) Failing after 1m31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 6s
Security Scanning / Trivy Scan — API Image (push) Failing after 5m35s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 3m45s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Security Scanning / Trivy Scan — Web Image (push) Failing after 13m51s
Security Scanning / Trivy Filesystem Scan (push) Failing after 14m46s
Security Scanning / Security Gate (push) Has been cancelled
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 29s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m42s
Deploy / Build Web Image (push) Failing after 27s
Deploy / Build AI Services Image (push) Failing after 29s
E2E Tests / Playwright E2E (push) Failing after 43s
Deploy / Build API Image (push) Failing after 1m31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 6s
Security Scanning / Trivy Scan — API Image (push) Failing after 5m35s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 3m45s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Security Scanning / Trivy Scan — Web Image (push) Failing after 13m51s
Security Scanning / Trivy Filesystem Scan (push) Failing after 14m46s
Security Scanning / Security Gate (push) Has been cancelled
This commit is contained in:
@@ -1,21 +1,21 @@
|
||||
# CQRS Handler Error Handling Guide
|
||||
## GoodGo Platform Implementation Standards
|
||||
# Hướng Dẫn Xử Lý Lỗi cho CQRS Handler
|
||||
## Tiêu Chuẩn Triển Khai của Nền Tảng GoodGo
|
||||
|
||||
---
|
||||
|
||||
## 📌 Quick Reference
|
||||
## 📌 Tham Chiếu Nhanh
|
||||
|
||||
| Status | Count | Modules |
|
||||
| Trạng thái | Số lượng | Modules |
|
||||
|--------|-------|---------|
|
||||
| ✓ Has Error Handling | 11 | auth (5), listings (2), admin, notifications, payments, search |
|
||||
| ✗ Needs Error Handling | 66 | All other handlers + 6 auth handlers |
|
||||
| **Total** | **77** | **All modules** |
|
||||
| ✓ Đã có Xử Lý Lỗi | 11 | auth (5), listings (2), admin, notifications, payments, search |
|
||||
| ✗ Cần Xử Lý Lỗi | 66 | Tất cả các handler còn lại + 6 auth handler |
|
||||
| **Tổng cộng** | **77** | **Tất cả các module** |
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Pattern 1: Standard Command Handler with Error Handling
|
||||
## 🎯 Pattern 1: Command Handler Chuẩn với Xử Lý Lỗi
|
||||
|
||||
Use this pattern for **most command handlers**:
|
||||
Sử dụng pattern này cho **hầu hết các command handler**:
|
||||
|
||||
```typescript
|
||||
import { Logger } from '@nestjs/common';
|
||||
@@ -33,19 +33,19 @@ export class YourCommandHandler implements ICommandHandler<YourCommand> {
|
||||
|
||||
async execute(command: YourCommand): Promise<YourResult> {
|
||||
try {
|
||||
// Load aggregate
|
||||
// Tải aggregate
|
||||
const aggregate = await this.repository.findById(command.id);
|
||||
if (!aggregate) {
|
||||
throw new NotFoundException('Aggregate', command.id);
|
||||
}
|
||||
|
||||
// Execute domain logic
|
||||
// Thực thi logic domain
|
||||
aggregate.doSomething(command.data);
|
||||
|
||||
// Save state
|
||||
// Lưu trạng thái
|
||||
await this.repository.save(aggregate);
|
||||
|
||||
// Publish events
|
||||
// Phát hành sự kiện
|
||||
const events = aggregate.clearDomainEvents();
|
||||
for (const event of events) {
|
||||
this.eventBus.publish(event);
|
||||
@@ -53,17 +53,17 @@ export class YourCommandHandler implements ICommandHandler<YourCommand> {
|
||||
|
||||
return { id: aggregate.id, status: 'success' };
|
||||
} catch (error) {
|
||||
// Always re-throw domain exceptions
|
||||
// Luôn ném lại các domain exception
|
||||
if (error instanceof DomainException) throw error;
|
||||
|
||||
// Log unexpected errors
|
||||
// Ghi log các lỗi không mong đợi
|
||||
this.logger.error(
|
||||
`Command execution failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
error instanceof Error ? error.stack : undefined,
|
||||
this.constructor.name,
|
||||
);
|
||||
|
||||
// Throw generic HTTP exception
|
||||
// Ném exception HTTP chung
|
||||
throw new InternalServerErrorException('Operation failed, please try again');
|
||||
}
|
||||
}
|
||||
@@ -72,9 +72,9 @@ export class YourCommandHandler implements ICommandHandler<YourCommand> {
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Pattern 2: Standard Query Handler with Error Handling
|
||||
## 🎯 Pattern 2: Query Handler Chuẩn với Xử Lý Lỗi
|
||||
|
||||
Use this pattern for **all query handlers**:
|
||||
Sử dụng pattern này cho **tất cả các query handler**:
|
||||
|
||||
```typescript
|
||||
import { Logger } from '@nestjs/common';
|
||||
@@ -108,9 +108,9 @@ export class YourQueryHandler implements IQueryHandler<YourQuery> {
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Pattern 3: Bulk Operation with Per-Item Error Handling
|
||||
## 🎯 Pattern 3: Thao Tác Hàng Loạt với Xử Lý Lỗi Theo Từng Mục
|
||||
|
||||
Use this pattern for **batch operations** (like `bulk-moderate-listings`):
|
||||
Sử dụng pattern này cho **các thao tác batch** (như `bulk-moderate-listings`):
|
||||
|
||||
```typescript
|
||||
@CommandHandler(BulkCommand)
|
||||
@@ -130,7 +130,7 @@ export class BulkCommandHandler implements ICommandHandler<BulkCommand> {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Process item
|
||||
// Xử lý từng mục
|
||||
item.update(command.data);
|
||||
await this.repository.save(item);
|
||||
|
||||
@@ -138,7 +138,7 @@ export class BulkCommandHandler implements ICommandHandler<BulkCommand> {
|
||||
} catch (itemError) {
|
||||
const message = itemError instanceof Error ? itemError.message : 'Unknown error';
|
||||
failed.push({ id, reason: message });
|
||||
// Continue processing other items
|
||||
// Tiếp tục xử lý các mục khác
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,18 +157,18 @@ export class BulkCommandHandler implements ICommandHandler<BulkCommand> {
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Pattern 4: Graceful Degradation (Non-Critical Services)
|
||||
## 🎯 Pattern 4: Giảm Cấp Duyên Dáng (Dịch Vụ Không Quan Trọng)
|
||||
|
||||
Use this pattern when **secondary services can fail without blocking** the main operation (like duplicate detection in `create-listing`):
|
||||
Sử dụng pattern này khi **các dịch vụ thứ cấp có thể thất bại mà không chặn** thao tác chính (như phát hiện trùng lặp trong `create-listing`):
|
||||
|
||||
```typescript
|
||||
async execute(command: CreateListingCommand): Promise<CreateListingResult> {
|
||||
try {
|
||||
// Critical path - must succeed
|
||||
// Luồng quan trọng - phải thành công
|
||||
const listing = await this.createListing(command);
|
||||
await this.repository.save(listing);
|
||||
|
||||
// Non-critical: Duplicate detection
|
||||
// Không quan trọng: Phát hiện trùng lặp
|
||||
let duplicates = [];
|
||||
try {
|
||||
duplicates = await this.duplicateDetector.find({
|
||||
@@ -180,10 +180,10 @@ async execute(command: CreateListingCommand): Promise<CreateListingResult> {
|
||||
'Duplicate detection failed, continuing without warnings',
|
||||
'CreateListingHandler'
|
||||
);
|
||||
// Continue - duplicates are optional
|
||||
// Tiếp tục - danh sách trùng lặp là tùy chọn
|
||||
}
|
||||
|
||||
// Non-critical: Price validation
|
||||
// Không quan trọng: Xác thực giá
|
||||
let priceWarning: PriceWarning | undefined;
|
||||
try {
|
||||
const result = await this.priceValidator.validate(command);
|
||||
@@ -195,7 +195,7 @@ async execute(command: CreateListingCommand): Promise<CreateListingResult> {
|
||||
'Price validation failed, continuing without warning',
|
||||
'CreateListingHandler'
|
||||
);
|
||||
// Continue - price warning is optional
|
||||
// Tiếp tục - cảnh báo giá là tùy chọn
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -217,9 +217,9 @@ async execute(command: CreateListingCommand): Promise<CreateListingResult> {
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Pattern 5: Authorization/Authentication Errors
|
||||
## 🎯 Pattern 5: Lỗi Phân Quyền/Xác Thực
|
||||
|
||||
Use this pattern when **authentication can fail** (like `login-user`):
|
||||
Sử dụng pattern này khi **xác thực có thể thất bại** (như `login-user`):
|
||||
|
||||
```typescript
|
||||
@CommandHandler(LoginUserCommand)
|
||||
@@ -241,7 +241,7 @@ export class LoginUserHandler implements ICommandHandler<LoginUserCommand> {
|
||||
error instanceof Error ? error.stack : undefined,
|
||||
'LoginUserHandler'
|
||||
);
|
||||
// Use specific exception for authentication
|
||||
// Sử dụng exception cụ thể cho xác thực
|
||||
throw new UnauthorizedException('Unable to create session, please try again');
|
||||
}
|
||||
}
|
||||
@@ -250,21 +250,21 @@ export class LoginUserHandler implements ICommandHandler<LoginUserCommand> {
|
||||
|
||||
---
|
||||
|
||||
## ❌ Common Mistakes to Avoid
|
||||
## ❌ Những Lỗi Phổ Biến Cần Tránh
|
||||
|
||||
### ❌ Mistake 1: Silent Catch Block
|
||||
### ❌ Lỗi 1: Khối Catch Im Lặng
|
||||
```typescript
|
||||
// BAD ❌
|
||||
// XẤU ❌
|
||||
try {
|
||||
await this.repository.save(entity);
|
||||
} catch (error) {
|
||||
// Silent - no logging, no error thrown
|
||||
// Im lặng - không ghi log, không ném lỗi
|
||||
}
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
**Cách sửa:**
|
||||
```typescript
|
||||
// GOOD ✓
|
||||
// TỐT ✓
|
||||
try {
|
||||
await this.repository.save(entity);
|
||||
} catch (error) {
|
||||
@@ -275,9 +275,9 @@ try {
|
||||
|
||||
---
|
||||
|
||||
### ❌ Mistake 2: Swallowing Domain Exceptions
|
||||
### ❌ Lỗi 2: Nuốt Domain Exception
|
||||
```typescript
|
||||
// BAD ❌
|
||||
// XẤU ❌
|
||||
try {
|
||||
const result = entity.validate();
|
||||
if (result.isErr) {
|
||||
@@ -285,14 +285,14 @@ try {
|
||||
}
|
||||
// ...
|
||||
} catch (error) {
|
||||
// This swallows the validation error
|
||||
// Điều này nuốt mất lỗi validation
|
||||
throw new InternalServerErrorException('Failed');
|
||||
}
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
**Cách sửa:**
|
||||
```typescript
|
||||
// GOOD ✓
|
||||
// TỐT ✓
|
||||
try {
|
||||
const result = entity.validate();
|
||||
if (result.isErr) {
|
||||
@@ -300,7 +300,7 @@ try {
|
||||
}
|
||||
// ...
|
||||
} catch (error) {
|
||||
// Re-throw domain exceptions
|
||||
// Ném lại các domain exception
|
||||
if (error instanceof DomainException) throw error;
|
||||
|
||||
this.logger.error(`Unexpected: ${error}`, error?.stack);
|
||||
@@ -310,20 +310,20 @@ try {
|
||||
|
||||
---
|
||||
|
||||
### ❌ Mistake 3: Logging to Console
|
||||
### ❌ Lỗi 3: Ghi Log ra Console
|
||||
```typescript
|
||||
// BAD ❌
|
||||
// XẤU ❌
|
||||
try {
|
||||
// ...
|
||||
} catch (error) {
|
||||
console.error(error); // Not structured, not captured by logging system
|
||||
console.error(error); // Không có cấu trúc, không được hệ thống logging ghi nhận
|
||||
throw error;
|
||||
}
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
**Cách sửa:**
|
||||
```typescript
|
||||
// GOOD ✓
|
||||
// TỐT ✓
|
||||
try {
|
||||
// ...
|
||||
} catch (error) {
|
||||
@@ -338,20 +338,20 @@ try {
|
||||
|
||||
---
|
||||
|
||||
### ❌ Mistake 4: Partial Logging
|
||||
### ❌ Lỗi 4: Ghi Log Không Đầy Đủ
|
||||
```typescript
|
||||
// BAD ❌
|
||||
// XẤU ❌
|
||||
try {
|
||||
// ...
|
||||
} catch (error) {
|
||||
this.logger.error(error.message); // Missing stack trace!
|
||||
this.logger.error(error.message); // Thiếu stack trace!
|
||||
throw error;
|
||||
}
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
**Cách sửa:**
|
||||
```typescript
|
||||
// GOOD ✓
|
||||
// TỐT ✓
|
||||
try {
|
||||
// ...
|
||||
} catch (error) {
|
||||
@@ -366,78 +366,78 @@ try {
|
||||
|
||||
---
|
||||
|
||||
### ❌ Mistake 5: Publishing Events Before Confirming Success
|
||||
### ❌ Lỗi 5: Phát Hành Sự Kiện Trước Khi Xác Nhận Thành Công
|
||||
```typescript
|
||||
// BAD ❌
|
||||
// XẤU ❌
|
||||
try {
|
||||
aggregate.apply(command);
|
||||
this.eventBus.publish(aggregate.events); // Before save!
|
||||
this.eventBus.publish(aggregate.events); // Trước khi lưu!
|
||||
await this.repository.save(aggregate);
|
||||
} catch (error) {
|
||||
// Event published but entity not saved!
|
||||
// Sự kiện đã được phát hành nhưng entity chưa được lưu!
|
||||
}
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
**Cách sửa:**
|
||||
```typescript
|
||||
// GOOD ✓
|
||||
// TỐT ✓
|
||||
try {
|
||||
aggregate.apply(command);
|
||||
await this.repository.save(aggregate); // Save first
|
||||
await this.repository.save(aggregate); // Lưu trước
|
||||
|
||||
// Publish events only after successful save
|
||||
// Chỉ phát hành sự kiện sau khi lưu thành công
|
||||
const events = aggregate.clearDomainEvents();
|
||||
for (const event of events) {
|
||||
this.eventBus.publish(event);
|
||||
}
|
||||
} catch (error) {
|
||||
// No events published - data is consistent
|
||||
// Không có sự kiện nào được phát hành - dữ liệu nhất quán
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Audit Checklist for Each Handler
|
||||
## 🔍 Danh Sách Kiểm Tra Khi Kiểm Tra Từng Handler
|
||||
|
||||
When reviewing error handling, verify:
|
||||
Khi xem xét xử lý lỗi, hãy kiểm tra:
|
||||
|
||||
- [ ] **Try-Catch Block**: Wraps entire execute method logic
|
||||
- [ ] **Domain Exception Re-throw**: `if (error instanceof DomainException) throw error;`
|
||||
- [ ] **Error Logging**: Includes message, stack trace, and context
|
||||
- [ ] **Logger Usage**: Uses injected logger, not console
|
||||
- [ ] **Appropriate Exception**: Throws correct HTTP exception type
|
||||
- [ ] **No Silent Catches**: Every catch block has logging or throw
|
||||
- [ ] **Event Publishing**: Only after successful state persistence
|
||||
- [ ] **Transaction Rollback**: Handled by try-catch (implicit or explicit)
|
||||
- [ ] **User Message**: Meaningful error response (not technical details)
|
||||
- [ ] **Logging Context**: Includes handler class name
|
||||
- [ ] **Khối Try-Catch**: Bao bọc toàn bộ logic của phương thức execute
|
||||
- [ ] **Ném Lại Domain Exception**: `if (error instanceof DomainException) throw error;`
|
||||
- [ ] **Ghi Log Lỗi**: Bao gồm thông báo, stack trace và ngữ cảnh
|
||||
- [ ] **Sử Dụng Logger**: Dùng logger được inject, không dùng console
|
||||
- [ ] **Exception Phù Hợp**: Ném đúng loại HTTP exception
|
||||
- [ ] **Không Có Catch Im Lặng**: Mỗi khối catch đều có ghi log hoặc ném lỗi
|
||||
- [ ] **Phát Hành Sự Kiện**: Chỉ sau khi lưu trạng thái thành công
|
||||
- [ ] **Rollback Transaction**: Được xử lý bởi try-catch (ngầm định hoặc tường minh)
|
||||
- [ ] **Thông Báo Cho Người Dùng**: Phản hồi lỗi có ý nghĩa (không phải chi tiết kỹ thuật)
|
||||
- [ ] **Ngữ Cảnh Logging**: Bao gồm tên lớp handler
|
||||
|
||||
---
|
||||
|
||||
## 📋 Implementation Checklist for Handlers Needing Error Handling
|
||||
## 📋 Danh Sách Triển Khai cho Các Handler Cần Xử Lý Lỗi
|
||||
|
||||
1. **Review existing pattern** in well-implemented handlers:
|
||||
- `auth/commands/login-user` (auth patterns)
|
||||
- `listings/commands/create-listing` (graceful degradation)
|
||||
- `admin/commands/bulk-moderate-listings` (batch operations)
|
||||
1. **Xem lại pattern hiện có** trong các handler được triển khai tốt:
|
||||
- `auth/commands/login-user` (các pattern xác thực)
|
||||
- `listings/commands/create-listing` (giảm cấp duyên dáng)
|
||||
- `admin/commands/bulk-moderate-listings` (các thao tác batch)
|
||||
|
||||
2. **Add to execute method**:
|
||||
2. **Thêm vào phương thức execute**:
|
||||
```typescript
|
||||
async execute(command: YourCommand): Promise<YourResult> {
|
||||
try {
|
||||
// existing logic
|
||||
// logic hiện có
|
||||
} catch (error) {
|
||||
// error handling
|
||||
// xử lý lỗi
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **Check if domain exception should be re-thrown**:
|
||||
3. **Kiểm tra xem domain exception có nên được ném lại không**:
|
||||
```typescript
|
||||
if (error instanceof DomainException) throw error;
|
||||
```
|
||||
|
||||
4. **Add appropriate logging**:
|
||||
4. **Thêm ghi log phù hợp**:
|
||||
```typescript
|
||||
this.logger.error(
|
||||
`Message: ${error instanceof Error ? error.message : String(error)}`,
|
||||
@@ -446,100 +446,100 @@ When reviewing error handling, verify:
|
||||
);
|
||||
```
|
||||
|
||||
5. **Throw appropriate HTTP exception**:
|
||||
5. **Ném HTTP exception phù hợp**:
|
||||
```typescript
|
||||
throw new InternalServerErrorException();
|
||||
// or
|
||||
// hoặc
|
||||
throw new NotFoundException();
|
||||
// or
|
||||
// hoặc
|
||||
throw new BadRequestException();
|
||||
```
|
||||
|
||||
6. **Test error scenarios**:
|
||||
- Repository returns null/error
|
||||
- Domain validation fails
|
||||
- Database save fails
|
||||
- Event publishing fails
|
||||
6. **Kiểm thử các tình huống lỗi**:
|
||||
- Repository trả về null hoặc lỗi
|
||||
- Xác thực domain thất bại
|
||||
- Lưu cơ sở dữ liệu thất bại
|
||||
- Phát hành sự kiện thất bại
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Priority Implementation Order
|
||||
## 🚀 Thứ Tự Ưu Tiên Triển Khai
|
||||
|
||||
### TIER 1 - Do First (33 handlers)
|
||||
- **admin**: 14 handlers
|
||||
- **leads**: 5 handlers
|
||||
- **inquiries**: 4 handlers
|
||||
- **reviews**: 5 handlers
|
||||
- **subscriptions**: 5 handlers
|
||||
### BẬC 1 - Làm Trước (33 handler)
|
||||
- **admin**: 14 handler
|
||||
- **leads**: 5 handler
|
||||
- **inquiries**: 4 handler
|
||||
- **reviews**: 5 handler
|
||||
- **subscriptions**: 5 handler
|
||||
|
||||
**Effort**: ~2 developer-days
|
||||
**Công sức**: ~2 ngày-lập trình viên
|
||||
|
||||
### TIER 2 - Do Second (18 handlers)
|
||||
- **payments**: 4 handlers
|
||||
- **search**: 8 handlers
|
||||
- **listings**: 5 handlers (2 already done)
|
||||
- **agents**: 3 handlers
|
||||
### BẬC 2 - Làm Tiếp (18 handler)
|
||||
- **payments**: 4 handler
|
||||
- **search**: 8 handler
|
||||
- **listings**: 5 handler (đã hoàn thành 2)
|
||||
- **agents**: 3 handler
|
||||
|
||||
**Effort**: ~1 developer-day
|
||||
**Công sức**: ~1 ngày-lập trình viên
|
||||
|
||||
### TIER 3 - Do Last (8 handlers)
|
||||
- **analytics**: 8 handlers
|
||||
- **auth**: 6 handlers (5 already done)
|
||||
### BẬC 3 - Làm Cuối (8 handler)
|
||||
- **analytics**: 8 handler
|
||||
- **auth**: 6 handler (đã hoàn thành 5)
|
||||
|
||||
**Effort**: ~1 developer-day
|
||||
**Công sức**: ~1 ngày-lập trình viên
|
||||
|
||||
---
|
||||
|
||||
## 📞 FAQ
|
||||
## 📞 Câu Hỏi Thường Gặp
|
||||
|
||||
**Q: Should every handler have error handling?**
|
||||
A: Yes. Every async operation can fail - databases go down, networks fail, etc.
|
||||
**H: Mỗi handler có cần xử lý lỗi không?**
|
||||
Đ: Có. Mọi thao tác bất đồng bộ đều có thể thất bại — cơ sở dữ liệu có thể ngừng hoạt động, mạng có thể lỗi, v.v.
|
||||
|
||||
**Q: Should I catch and swallow domain exceptions?**
|
||||
A: No. Re-throw them using `if (error instanceof DomainException) throw error;`
|
||||
**H: Tôi có nên bắt và nuốt domain exception không?**
|
||||
Đ: Không. Hãy ném lại chúng bằng `if (error instanceof DomainException) throw error;`
|
||||
|
||||
**Q: What if the handler has no database calls?**
|
||||
A: Still add error handling. External service calls, calculations, and I/O all need try-catch.
|
||||
**H: Nếu handler không có lời gọi cơ sở dữ liệu thì sao?**
|
||||
Đ: Vẫn thêm xử lý lỗi. Các lời gọi dịch vụ bên ngoài, phép tính và I/O đều cần try-catch.
|
||||
|
||||
**Q: Can I use generic Exception handling?**
|
||||
A: No. Import and use NestJS exceptions like `InternalServerErrorException`, `NotFoundException`, etc.
|
||||
**H: Tôi có thể dùng xử lý Exception chung không?**
|
||||
Đ: Không. Hãy import và sử dụng các exception của NestJS như `InternalServerErrorException`, `NotFoundException`, v.v.
|
||||
|
||||
**Q: Should I log to console?**
|
||||
A: No. Inject and use the NestJS Logger service for structured logging.
|
||||
**H: Tôi có nên ghi log ra console không?**
|
||||
Đ: Không. Hãy inject và sử dụng dịch vụ NestJS Logger để ghi log có cấu trúc.
|
||||
|
||||
**Q: What about promise rejection handling?**
|
||||
A: Async/await with try-catch handles all promise rejections. That's why we wrap the entire execute method.
|
||||
**H: Còn việc xử lý promise rejection thì sao?**
|
||||
Đ: Async/await kết hợp với try-catch xử lý tất cả các promise rejection. Đó là lý do tại sao chúng ta bao bọc toàn bộ phương thức execute.
|
||||
|
||||
---
|
||||
|
||||
## 🎓 Reference: Exemplary Handlers
|
||||
## 🎓 Tham Khảo: Các Handler Mẫu
|
||||
|
||||
### 1. **Login User Handler** (Excellent)
|
||||
Location: `apps/api/src/modules/auth/application/commands/login-user/login-user.handler.ts`
|
||||
### 1. **Login User Handler** (Xuất sắc)
|
||||
Vị trí: `apps/api/src/modules/auth/application/commands/login-user/login-user.handler.ts`
|
||||
|
||||
✓ Clear error message for user
|
||||
✓ Proper exception type (UnauthorizedException)
|
||||
✓ Stack trace logged
|
||||
✓ Handler context included
|
||||
✓ Thông báo lỗi rõ ràng cho người dùng
|
||||
✓ Loại exception phù hợp (UnauthorizedException)
|
||||
✓ Stack trace được ghi log
|
||||
✓ Ngữ cảnh handler được bao gồm
|
||||
|
||||
### 2. **Create Listing Handler** (Advanced)
|
||||
Location: `apps/api/src/modules/listings/application/commands/create-listing/create-listing.handler.ts`
|
||||
### 2. **Create Listing Handler** (Nâng cao)
|
||||
Vị trí: `apps/api/src/modules/listings/application/commands/create-listing/create-listing.handler.ts`
|
||||
|
||||
✓ Critical path is protected
|
||||
✓ Non-critical services can degrade gracefully
|
||||
✓ Continues operation even if secondary services fail
|
||||
✓ Warnings still provided when possible
|
||||
✓ Luồng quan trọng được bảo vệ
|
||||
✓ Các dịch vụ không quan trọng có thể giảm cấp duyên dáng
|
||||
✓ Tiếp tục hoạt động ngay cả khi các dịch vụ thứ cấp thất bại
|
||||
✓ Cảnh báo vẫn được cung cấp khi có thể
|
||||
|
||||
### 3. **Bulk Moderate Handler** (Batch Pattern)
|
||||
Location: `apps/api/src/modules/admin/application/commands/bulk-moderate-listings/bulk-moderate-listings.handler.ts`
|
||||
### 3. **Bulk Moderate Handler** (Pattern Batch)
|
||||
Vị trí: `apps/api/src/modules/admin/application/commands/bulk-moderate-listings/bulk-moderate-listings.handler.ts`
|
||||
|
||||
✓ Per-item error collection
|
||||
✓ Processing continues for other items
|
||||
✓ Complete result returned with failures
|
||||
✓ Individual error tracking
|
||||
✓ Thu thập lỗi theo từng mục
|
||||
✓ Tiếp tục xử lý các mục khác
|
||||
✓ Trả về kết quả đầy đủ kèm danh sách thất bại
|
||||
✓ Theo dõi lỗi từng mục riêng biệt
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: April 11, 2026
|
||||
**Audit Coverage**: 77 handlers across 12 modules
|
||||
**Compliance**: 14.3% currently implemented
|
||||
**Cập Nhật Lần Cuối**: 11 tháng 4 năm 2026
|
||||
**Phạm Vi Kiểm Tra**: 77 handler trên 12 module
|
||||
**Tuân Thủ**: Hiện tại đã triển khai 14,3%
|
||||
|
||||
Reference in New Issue
Block a user