hrms-api-org/reports/batch-04-controllers-31-40-analysis.md

234 lines
9.9 KiB
Markdown
Raw Normal View History

2026-05-08 18:15:03 +07:00
# รายงานการวิเคราะห์ความเสี่ยงการหยุดทำงานของระบบ (Crash Risk Analysis)
## ชุดที่ 4 (Batch 4) - Controllers 31-40
## วันที่ 8 พฤษภาคม 2568
---
## **รายชื่อ Controllers ที่ตรวจสอบ (31-40)**
31. MainController.ts
32. MyController.ts
33. OrgChild1Controller.ts
34. OrgChild2Controller.ts
35. OrgChild3Controller.ts
36. OrgChild4Controller.ts
37. OrgRootController.ts
38. OrganizationController.ts (ไฟล์ขนาดใหญ่ >397KB)
39. OrganizationDotnetController.ts (ไฟล์ขนาดใหญ่ >329KB)
40. OrganizationUnauthorizeController.ts
---
## **สรุปผลการตรวจสอบ**
### จำนวนปัญหาที่พบ: 8 ปัญหา
| ระดับความรุนแรง | จำนวน | ประเภท |
|---|---|---|
| 🔴 วิกฤติ | 2 | มีโอกาสทำให้ Service Crash สูงมาก |
| 🟠 สูง | 4 | มีโอกาสทำให้เกิด Unhandled Exception |
| 🟡 ปานกลาง | 2 | อาจทำให้เกิดปัญหาในสถานการณ์เฉพาะ |
---
## **รายละเอียดปัญหาแต่ละรายการ**
---
## 🔴 **ปัญหาที่ 1: การลบข้อมูลหลายตารางโดยไม่ใช้ Transaction (OrgRootController)**
### ไฟล์และตำแหน่ง:
- **ไฟล์:** `src/controllers/OrgRootController.ts`
- **บรรทัด:** 467-475
- **Method:** `delete`
### ประเภทปัญหา:
1. **Unhandled Exception** - การดำเนินการหลายอย่างโดยไม่มี Transaction
### สาเหตุที่ทำให้เสี่ยงต่อการ Crash:
โค้ดทำการลบข้อมูล 6 ตารางต่อเนื่องกันโดยไม่มี error handling และไม่ใช้ transaction:
- หาก delete ตัวใดตัวหนึ่งล้มเหลว ข้อมูลจะไม่สมบูรณ์
- ไม่มีการ rollback เมื่อเกิด error
- หากมี foreign key constraint violation อาจทำให้ service crash
### โค้ดปัจจุบัน (มีปัญหา):
```typescript
await this.empPositionRepository.remove(empPositions, { data: request });
await this.empPosMasterRepository.remove(empPosMasters, { data: request });
await this.positionRepository.remove(positions, { data: request });
await this.posMasterRepository.remove(posMasters, { data: request });
await this.child4Repository.delete({ orgRootId: id });
await this.child3Repository.delete({ orgRootId: id });
await this.child2Repository.delete({ orgRootId: id });
await this.child1Repository.delete({ orgRootId: id });
await this.orgRootRepository.delete({ id });
// ❌ ไม่มี try-catch หรือ transaction
```
### วิธีแก้ไขที่แนะนำ:
```typescript
try {
await AppDataSource.transaction(async (transactionalEntityManager) => {
await transactionalEntityManager.remove(EmployeePosition, empPositions);
await transactionalEntityManager.remove(EmployeePosMaster, empPosMasters);
await transactionalEntityManager.remove(Position, positions);
await transactionalEntityManager.remove(PosMaster, posMasters);
await transactionalEntityManager.delete(OrgChild4, { orgRootId: id });
await transactionalEntityManager.delete(OrgChild3, { orgRootId: id });
await transactionalEntityManager.delete(OrgChild2, { orgRootId: id });
await transactionalEntityManager.delete(OrgChild1, { orgRootId: id });
await transactionalEntityManager.delete(OrgRoot, { id });
});
return new HttpSuccess();
} catch (error) {
console.error('ลบข้อมูล OrgRoot ล้มเหลว:', error);
if (error.code === '23503') {
throw new HttpError(
HttpStatusCode.CONFLICT,
"ไม่สามารถลบได้ เนื่องจากมีการใช้งานข้อมูลนี้อยู่"
);
}
throw new HttpError(
HttpStatusCode.INTERNAL_SERVER_ERROR,
"เกิดข้อผิดพลาดในการลบข้อมูล"
);
}
```
---
## 🔴 **ปัญหาที่ 2: Nested forEach กับ Async Operations (OrgRootController)**
### ไฟล์และตำแหน่ง:
- **ไฟล์:** `src/controllers/OrgRootController.ts`
- **บรรทัด:** 571-1009
- **Method:** `publishEmployee`
### ประเภทปัญหา:
1. **Unhandled Exception** - Async operations ใน forEach ไม่ได้รับการจัดการ
### สาเหตุที่ทำให้เสี่ยงต่อการ Crash:
มีการใช้ `forEach` ซ้อนกัน 4-5 ระดับ:
- `forEach` ไม่รอ callback ให้ทำงานเสร็จ
- Promise rejections อาจไม่ได้รับการ handle
- หากเกิด error ใน nested operations อาจทำให้ unhandled rejection
---
## 🟠 **ปัญหาที่ 3: Promise.all ที่ไม่มี Error Handling (OrgChild Controllers)**
### ไฟล์และตำแหน่ง:
- **ไฟล์:** `src/controllers/OrgChild1Controller.ts`
- **บรรทัด:** 105-113, 122-130, 242-250, 259-268
- **Method:** `save`, `Edit`
### ประเภทปัญหา:
2. **Missing Error Handle** - Promise.all ไม่มี catch
### สาเหตุที่ทำให้เสี่ยงต่อการ Crash:
มีการใช้ `Promise.all` หลายครั้งแต่ไม่มี error handling:
- หาก database operations fail จะเกิด unhandled rejection
- ไม่มี try-catch รอบ Promise.all
---
## 🟠 **ปัญหาที่ 4-6: การลบข้อมูลหลายตารางโดยไม่ใช้ Transaction (OrgChild1-4 Controllers)**
### ไฟล์และตำแหน่ง:
- **ไฟล์:** `src/controllers/OrgChild1Controller.ts` (บรรทัด 456-463)
- **ไฟล์:** `src/controllers/OrgChild2Controller.ts` (บรรทัด 317-323)
- **ไฟล์:** `src/controllers/OrgChild3Controller.ts` (บรรทัด 272-278)
- **ไฟล์:** `src/controllers/OrgChild4Controller.ts` (บรรทัด 311-315)
- **Method:** `delete`
### ประเภทปัญหา:
1. **Unhandled Exception** - การลบข้อมูลหลายตารางไม่มี Transaction
---
## 🟠 **ปัญหาที่ 7: Map ที่มี Null Reference (OrgRootController)**
### ไฟล์และตำแหน่ง:
- **ไฟล์:** `src/controllers/OrgRootController.ts`
- **บรรทัด:** 446-465
- **Method:** `delete`
### ประเภทปัญหา:
1. **Unhandled Exception** - Null reference ใน map
---
## 🟡 **ปัญหาที่ 8: Missing Error Handling ใน MainController**
### ไฟล์และตำแหน่ง:
- **ไฟล์:** `src/controllers/MainController.ts`
- **บรรทัด:** 42-52
- **Method:** `getMainPerson`
### ประเภทปัญหา:
2. **Missing Error Handle** - ไม่มี error handling
---
## **สรุปสถิติ**
### ปัญหาตามระดับความรุนแรง:
| ระดับ | จำนวน | ไฟล์ที่พบ |
|---|---|---|
| 🔴 วิกฤติ | 2 | OrgRootController (2) |
| 🟠 สูง | 4 | OrgRoot, OrgChild1-4Controllers |
| 🟡 ปานกลาง | 2 | MainController, OrgRootController |
### ไฟล์ที่มีปัญหามากที่สุด:
1. **OrgRootController.ts** - 4 ปัญหา (รุนแรงที่สุด)
2. **OrgChild1Controller.ts** - 2 ปัญหา
3. **OrgChild2Controller.ts** - 1 ปัญหา
4. **OrgChild3Controller.ts** - 1 ปัญหา
5. **OrgChild4Controller.ts** - 1 ปัญหา
6. **MainController.ts** - 1 ปัญหา
### ปัญหาที่พบบ่อยที่สุด:
1. **การลบข้อมูลหลายตารางโดยไม่ใช้ Transaction** (พบ 5 ครั้ง)
2. **Promise.all/Async operations ไม่มี Error Handling** (พบ 3 ครั้ง)
---
## **คำแนะนำเพื่อป้องกันปัญหา**
### 1. สร้าง Transaction Wrapper Function
สร้าง utility function สำหรับ database operations หลายตาราง
### 2. ใช้ for...of แทน forEach สำหรับ Async Operations
```typescript
// ❌ ไม่ดี
array.forEach(async (item) => {
await processItem(item);
});
// ✅ ดี
for (const item of array) {
await processItem(item);
}
```
### 3. เพิ่ม Error Handling รอบ Async Operations
ใช้ try-catch ครอบ Promise.all และ async operations ทั้งหมด
### 4. Enable Strict TypeScript
ตรวจสอบ `tsconfig.json` ให้แน่ใจว่ามีการเปิดใช้ strict mode
---
## **บันทึกเพิ่มเติม**
- **วันที่สร้างรายงาน:** 8 พฤษภาคม 2568
- **จำนวน Controllers ที่ตรวจสอบ:** 10 ไฟล์ (31-40)
- **เครื่องมือที่ใช้:** การวิเคราะห์ Code และ Pattern Recognition
- **ข้อจำกัด:** OrganizationController.ts และ OrganizationDotnetController.ts มีขนาดใหญ่มาก (>300KB)
---
**รายงานนี้ครอบคลุมเฉพาะ Controllers 31-40 สำหรับชุดที่ 4**