Files
G-Launcher/Doc/updater-temp-lifecycle.md
T

8.0 KiB

🔄 สัญญาทางเทคนิค: วงจรชีวิตของระบบอัปเดต (Updater Temp Lifecycle Contract)

เอกสารนี้ระบุข้อตกลงและสัญญาทางเทคนิค (Contract) สำหรับระบบอัปเดตและบิลด์ในเครื่องของ G-Launcher ซึ่งครอบคลุมทั้งสคริปต์ PowerShell (scripts/bootstrap.ps1) และบริการ Go Backend (internal/git-service/launcher.go)


1. วัตถุประสงค์และข้อจำกัดของระบบปฏิบัติการ (Operating System Constraints)

ปัญหาข้อจำกัดของ Windows:

  1. Windows Executable Locking: เมื่อโปรเซส .exe กำลังทำงานอยู่ ระบบปฏิบัติการจะเปิดแฮนเดิลไฟล์ด้วยการล็อกแบบแชร์การอ่าน (FILE_SHARE_READ) แต่ไม่อนุญาตให้เขียน (GENERIC_WRITE) หรือลบทิ้ง (DELETE) โดยตรง
  2. ข้อยกเว้นการเปลี่ยนชื่อ (Rename Privilege): บน Windows อนุญาตให้ เปลี่ยนชื่อ (Rename/Move) ไฟล์ executable ที่กำลังทำงานอยู่ได้ ตราบใดที่ยังอยู่บนโวลุม (Volume/Drive) เดียวกัน
  3. การหลีกเลี่ยง Build In-Place: การรัน git pull หรือ go build ทับโฟลเดอร์หลักของ Launcher ขณะที่ตัว Launcher รันอยู่ จะทำให้เกิด Exception Access is denied ทันที และอาจทำให้โฟลเดอร์ซอร์สโค้ดค้างอยู่ในสถานะไม่สมบูรณ์

2. ขั้นตอนทั้ง 4 ของวงจรชีวิต (The 4 Lifecycle Phases)

Phase 1: การจัดเตรียมพื้นที่ชั่วคราวและการดาวน์โหลด (Download to Temp)

  • PowerShell:
    • โฟลเดอร์เป้าหมาย: $tempBuildDir = Join-Path $rootDir "temp\build_workspace"
    • หากมีโฟลเดอร์ตกค้างจากรอบก่อน ให้สั่งลบทิ้งก่อนสร้างใหม่เสมอ
    • สั่ง git clone --depth 1 --branch Dev https://gaytea.cod-algieba.ts.net/GaCy/G-Launcher.git $tempBuildDir
    • หากการ Clone ผ่านเน็ตเวิร์กล้มเหลว (เช่น ทำงานแบบออฟไลน์) สคริปต์จะสลับไป Clone จากโฟลเดอร์ท้องถิ่น ($rootDir) เข้าสู่ $tempBuildDir แทน
  • Go Backend:
    • ใช้ tempDir, err := os.MkdirTemp("", "g-launcher-build-*")
    • สั่งงาน Git ผ่านฟังก์ชัน ensureGit() เพื่อรับประกันว่ามี Portable MinGit ทำงานได้โดยไม่ต้องพึ่งสิทธิ์ Administrator

Phase 2: การคอมไพล์แบบแยกส่วนในโฟลเดอร์ชั่วคราว (Isolated Build)

  • สวิตช์ Working Directory เข้าสู่โฟลเดอร์ชั่วคราว (Push-Location $tempBuildDir หรือ cmd.Dir = tempDir)
  • ลำดับการคอมไพล์:
    1. npm --prefix frontend install --no-audit --no-fund (ติดตั้ง dependencies ของ React 19)
    2. npm --prefix frontend run build (คอมไพล์ assets ผ่าน Vite 8 ได้ผลลัพธ์ลง frontend/dist/)
    3. go mod tidy (จัดระเบียบ Go modules)
    4. wails3 generate syso (สร้าง Windows PE Resource, Manifest, DPI awareness, และ Icon)
    5. go build -tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui" -o bin/G-Launcher.exe .
  • ตรวจสอบว่าไฟล์ไบนารีผลลัพธ์ถูกสร้างขึ้นจริง และมีขนาดมากกว่า 0 ไบต์
  • สลับกลับสู่ Working Directory เดิม (Pop-Location) ก่อนเริ่มขั้นตอนถัดไป

Phase 3: การสลับไฟล์ไบนารีอย่างปลอดภัยและการ Rollback (Atomic Swap & Safe Rollback)

  • หากไฟล์เป้าหมาย bin/G-Launcher.exe มีอยู่เดิม:
    1. เปลี่ยนชื่อไฟล์เดิมเป็น bin/G-Launcher.exe.old
    2. ย้ายไฟล์ใหม่จากโฟลเดอร์ Temp มาวางที่ bin/G-Launcher.exe
    3. หากการย้ายไฟล์ล้มเหลว (เกิด Exception):
      • Rollback ทันที: ย้าย bin/G-Launcher.exe.old กลับมาเป็น bin/G-Launcher.exe เพื่อให้ผู้ใช้ยังสามารถเปิดโปรแกรมเดิมได้
      • แจ้งข้อผิดพลาดและยุติการทำงาน
    4. หากการย้ายไฟล์สำเร็จ:
      • ลบไฟล์ bin/G-Launcher.exe.old (หากโปรแกรมเดิมกำลังรันอยู่และยังลบไม่ได้ ไฟล์นี้จะถูกเพิกเฉยและรอการลบในรอบถัดไป)
  • ในฝั่ง Go Backend ใช้ไลบรารี github.com/minio/selfupdate:
    • ฟังก์ชัน selfupdate.Apply(newBinaryReader, selfupdate.Options{}) ดำเนินการ Rename & Swap แบบ Atomic ในระดับ Native Windows API

Phase 4: การทำลายโฟลเดอร์ชั่วคราว (Guaranteed Temp Purge)

  • PowerShell:
    • ครอบกระบวนการทั้งหมดด้วยบล็อก try { ... } finally { ... }
    • ในบล็อก finally:
      Set-Location $rootDir
      if (Test-Path $tempBuildDir) {
          Remove-Item -LiteralPath $tempBuildDir -Recurse -Force -ErrorAction SilentlyContinue
      }
      
    • การันตีว่าโฟลเดอร์ Temp จะถูกลบออก 100% เสมอ ไม่ว่าการบิลด์จะสำเร็จหรือเกิดข้อผิดพลาด
  • Go Backend:
    • ใช้คำสั่ง defer os.RemoveAll(tempDir) ทันทีหลังสร้าง os.MkdirTemp สำเร็จ

3. หลักฐานการตรวจสอบจริง (Empirical Verification Log)

ผลการทดสอบสคริปต์จริงในสภาพแวดล้อม Windows 64-bit (Task ID: task-607):

  • โฟลเดอร์ชั่วคราว: C:\Users\Phitchayut\Desktop\G Launcher\temp\build_workspace
  • เวลาในการดาวน์โหลดและแตกแพ็กเกจ Frontend: 21 วินาที
  • เวลาในการคอมไพล์ Vite Frontend: 751 มิลลิวินาที
  • ขนาดไฟล์ Executable ผลลัพธ์: 28,677,632 ไบต์ (27.35 MB)
  • ผลการตรวจสอบการล้างขยะ: คำสั่ง Test-Path .\temp\build_workspace คืนค่า False (โฟลเดอร์ชั่วคราวถูกลบทิ้งหมดจด ไร้ขยะตกค้าง)