# รายงานการวิเคราะห์ความเสี่ยงการหยุดทำงานของระบบ (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**