วิธีที่ React Bundle ที่ถูกแคชไว้ ส่งข้อมูลไปยังฐานข้อมูลที่ผิดพลาด

เราต้องทำงานให้ทันกำหนดส่ง ทีม backend ได้ทำการย้ายไปยัง API ใหม่และฐานข้อมูลใหม่ ส่วนทีม frontend ได้อัปเดต environment variables ใน AWS Amplify และ push code ขึ้นไป

การ deployment ประสบความสำเร็จ เราปิดแล็ปท็อป และคิดว่างานเสร็จสิ้นแล้ว

แต่เราคิดผิด

วิศวกรคนหนึ่งตรวจสอบ logs บน API server ตัวเก่า ซึ่งเซิร์ฟเวอร์นี้ควรจะถูกปิดไปแล้ว แต่มันยังทำงานอยู่ มันกำลังรับ request จริงจาก client และเขียนข้อมูลลงในฐานข้อมูลตัวเก่า

เป็นเวลาสองชั่วโมงที่ข้อมูลจริงของลูกค้าถูกส่งไปยังที่ที่ผิด

นี่คือสาเหตุที่มันเกิดขึ้นและวิธีที่เราแก้ไขมัน

ปัญหาที่เกิดขึ้น

React apps บน CDN อย่าง AWS Amplify จะทำการแทนที่ environment variables ในช่วง build time เมื่อคุณรัน build ตัว bundler จะค้นหาทุกตัวแปรและแทนที่ด้วย hardcoded string

API URL ถูกฝังลงไปในไฟล์ JavaScript โดยตรง

เมื่อเรา deploy ผู้ใช้ใหม่จะได้รับ bundle ตัวใหม่ แต่ผู้ใช้เดิมที่เปิดแอปค้างไว้ไม่ได้ทำการ refresh หน้าเว็บ พวกเขายังคงรัน bundle ตัวเก่าที่มี URL เก่าฝังอยู่ข้างใน

เนื่องจากเซิร์ฟเวอร์ตัวเก่ายังทำงานอยู่ client เหล่านี้จึงได้รับสถานะ 200 OK ทุกอย่างดูเหมือนจะปกติดี ความล้มเหลวนี้เกิดขึ้นอย่างเงียบเชียบ ซึ่งความเงียบคือบั๊กที่อันตรายที่สุด

การแก้ไขแบบ 3 ชั้น

เราสร้างการแก้ไขขึ้นมา 3 ชั้น เพื่อให้แน่ใจว่าเหตุการณ์นี้จะไม่เกิดขึ้นอีก

1. Runtime Configuration เราเลิกใช้วิธีฝัง URL ลงใน JavaScript bundle แต่เปลี่ยนมาใช้ไฟล์ config.json ใน public folder แทน ซึ่งตัว bundler จะไม่แตะต้องไฟล์นี้ แอปจะทำการ fetch ไฟล์นี้ที่ runtime ก่อนที่จะทำการ render เพื่อให้แน่ใจว่า session ใหม่จะได้รับ URL ที่ถูกต้องเสมอ

2. WebSocket Notifications การตั้งค่าแบบ runtime ไม่สามารถช่วยผู้ใช้ที่เปิดแท็บค้างไว้ได้ เราจึงเชื่อมโยงกระบวนการ deployment เข้ากับ WebSocket server ของเรา เมื่อ Amplify ทำการ build เสร็จสิ้น มันจะเรียก webhook บน API ของเรา จากนั้นเซิร์ฟเวอร์จะ push ข้อความไปยัง client ทั้งหมดที่เชื่อมต่ออยู่ หากผู้ใช้กำลังใช้งานเวอร์ชันเก่า จะมีแบนเนอร์ปรากฏขึ้นเพื่อขอให้พวกเขาทำการ refresh

3. Cache Management เราได้อัปเดตการตั้งค่า CloudFront โดยกำหนดให้ entry points อย่าง index.html และ config.json เป็นแบบ no-cache เพื่อให้แน่ใจว่าผู้ใช้จะได้รับไฟล์ล่าสุดเสมอ แทนที่จะเป็นเวอร์ชันเก่าที่ค้างอยู่ใน CDN edge node

บทเรียนที่ได้รับ

• การตั้งค่าในช่วง Build (Build-time config) คือกับดักสำหรับค่าที่ต้องเปลี่ยนแปลงระหว่างการ Deploy • ความเงียบนั้นอันตรายกว่าเสียงรบกวน จงทำให้ระบบเก่าแจ้งข้อผิดพลาดออกมาอย่างชัดเจนด้วยสถานะ 410 Gone • แรงกดดันจากเส้นตายทำให้ขั้นตอนที่ทำด้วยมือ (manual steps) เกิดความผิดพลาดได้ จงเปลี่ยนกระบวนการยกเลิกการใช้งาน (decommissioning process) ให้เป็นระบบอัตโนมัติ • จงเฝ้าติดตามสิ่งที่กำลังจะปิดการใช้งาน ไม่ใช่แค่สิ่งที่กำลังเปิดใช้งานเท่านั้น

การ Deployment ไม่ใช่แค่เรื่องของการ Push code เท่านั้น แต่คือการทำให้มั่นใจว่า Client ทุกรายได้รันโค้ดเวอร์ชันที่ถูกต้อง

ที่มา: https://dev.to/sugan_dev/how-a-cached-react-bundle-sent-production-data-to-the-wrong-database-55n9