Files
G-Launcher/Doc/game-selection-persistence.md
T

38 lines
3.6 KiB
Markdown
Raw Normal View History

# 🛡️ สัญญาทางเทคนิค: การบันทึกพาธเกมแบบทนทานต่อ Crash (Game Selection Persistence)
เอกสารนี้ระบุสถาปัตยกรรมการบันทึกและอ่านพาธที่ตั้งของไฟล์ตัวเกม (`StarRail.exe`) ใน [`internal/fs-service/game-selection.go`](../internal/fs-service/game-selection.go)
---
## 1. ที่มาและปัญหาความเสียหายของไฟล์คอนฟิก (The Corruption Problem)
ในโปรเจกต์ต้นแบบเดิม การบันทึกพาธของเกมใช้ฟังก์ชันมาตรฐาน `os.WriteFile` ซึ่งมีจุดอ่อนร้ายแรงบนระบบปฏิบัติการ Windows:
* หากเครื่องคอมพิวเตอร์ดับกะทันหัน ไฟตก หรือ Launcher เกิด Crash ในเสี้ยววินาทีที่กำลังเขียนไฟล์
* ไฟล์ `game-selection.json` จะกลายเป็น **ไฟล์ว่างเปล่าขนาด 0 ไบต์ (Zero-Byte Corrupted File)**
* เมื่อเปิด Launcher ขึ้นมาใหม่ โปรแกรมจะไม่สามารถอ่าน JSON ได้ ส่งผลให้ผู้ใช้ต้องค้นหาและเลือกพาธเกมใหม่ซ้ำซาก
---
## 2. โซลูชัน: Atomic Write ผ่าน Windows API `MoveFileEx`
เพื่อแก้ไขปัญหานี้ G-Launcher จึงนำรูปแบบ **Atomic Write** ที่ผสานมาจาก Sunbringer มาใช้งานอย่างเคร่งครัด:
```
[ผู้ใช้เลือกพาธเกม: C:\Games\StarRail.exe]
│
▼
1. เขียนข้อมูล JSON ลงในไฟล์ชั่วคราว (.tmp)
└── %APPDATA%\g-launcher\game-selection.json.tmp
│
▼
2. Flush ข้อมูลลงดิสก์จริง (Sync to Storage)
└── file.Sync() เพื่อให้แน่ใจว่าข้อมูลถูกเขียนลงฮาร์ดดิสก์/SSD จริง ไม่ค้างใน OS Cache
│
▼
3. สลับไฟล์ด้วย Windows Native API MoveFileEx
└── MoveFileExW(tempPath, targetPath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)
```
### คุณสมบัติของ `MoveFileEx`:
* **Atomic Operation:** บนระบบไฟล์ NTFS การสลับไฟล์ด้วย `MoveFileEx` ถือเป็น Atomic Operation กล่าวคือ ไฟล์จะเปลี่ยนเป็นเวอร์ชันใหม่ทันที หรือหากเกิดเหตุขัดข้อง ไฟล์เดิมก็จะยังคงอยู่สมบูรณ์ 100% ไม่มีทางเกิดไฟล์ 0 ไบต์
* **No Hardcoding:** ตำแหน่งไฟล์คอนฟิกถูกสร้างขึ้นโดยใช้ `os.UserConfigDir()` ร่วมกับ `filepath.Join(...)` ซึ่งจะได้พาธมาตรฐาน `%APPDATA%\g-launcher\game-selection.json` โดยไม่ฝังชื่อไดรฟ์ `C:\` ในโค้ด