ซิงก์ข้อมูลไป BigQuery
ภาพรวม
หน้านี้คือหน้าตั้งค่าการเชื่อมต่อกับ Google BigQuery เพื่อ ดึงข้อมูลจาก BigQuery เข้ามาเป็นคุณสมบัติเพิ่มเติมของผู้ใช้ (custom attribute) ในระบบ
แม้ชื่อฟีเจอร์จะอ่านว่า "ซิงก์ไป BigQuery" แต่ทิศทางการไหลของข้อมูลจริงคือจาก BigQuery เข้าสู่ระบบ สังเกตได้จากผลลัพธ์ของการซิงก์ที่รายงานเป็นจำนวนผู้ใช้ที่ถูกอัปเดต และจากการแม็ปฟิลด์ที่จับคู่คอลัมน์ใน BigQuery เข้ากับคีย์คุณสมบัติของผู้ใช้
ลักษณะเด่นคือ เป็นหน้าตั้งค่าชุดเดียว ไม่มีหน้ารายการ หนึ่ง LINE OA มีการตั้งค่าได้หนึ่งชุด หน้าจอเดียวจึงทำหน้าที่ทั้งสร้างและแก้ไข โดยตัดสินจากว่ามีการตั้งค่าเดิมอยู่แล้วหรือไม่ ตัวหน้าจออยู่ใต้เมนูการตั้งค่าระบบ
ประโยชน์คือทีมที่มีคลังข้อมูลลูกค้าอยู่บน BigQuery อยู่แล้ว สามารถดึงค่าสรุป เช่น ยอดใช้จ่ายสะสม ระดับสมาชิก หรือพฤติกรรมการซื้อ เข้ามาเป็นคุณสมบัติของผู้ใช้ LINE เพื่อนำไปทำกลุ่มเป้าหมายและแคมเปญต่อได้
Business Flow
การโหลดการตั้งค่า
- เปิดหน้า ระบบจะดึงการตั้งค่าปัจจุบันมาแสดง โดยกรณีที่ยังไม่เคยตั้งค่าถือเป็นเรื่องปกติ ระบบจึงไม่พยายามเรียกซ้ำและแสดงฟอร์มเปล่าแทน
- ระหว่างโหลดหน้าจอจะแสดงสถานะกำลังโหลดแทนที่ฟอร์ม
- ค่าเริ่มต้นสำหรับการตั้งค่าใหม่คือคอลัมน์ระบุตัวผู้ใช้ชื่อ
user_id, ตารางเวลาทำงานทุกวันเวลา 06:00 น., สถานะปิดใช้งาน และยังไม่มีการแม็ปฟิลด์ใด - เมื่อโหลดการตั้งค่าเดิมได้ ระบบจะเติมค่าลงฟอร์มพร้อม ถอดคำนำหน้า
custom.ออกจากคีย์คุณสมบัติ เพราะหน้าจอแสดงคำนำหน้านี้เป็นส่วนประกอบตายตัวของช่องกรอกอยู่แล้ว
การกรอกฟอร์ม
ฟอร์มแบ่งเป็น 4 การ์ด
- การเชื่อมต่อ — ระบุรหัสโปรเจกต์ GCP (บังคับ), ชื่อตารางสรุปที่จะอ่าน (บังคับ), คอลัมน์ที่เป็น LINE user ID (ถ้าเว้นว่างระบบจะใช้ค่าเริ่มต้น) และข้อมูลรับรอง service account แบบ JSON โดยมีปุ่ม ทดสอบการเชื่อมต่อ ที่ส่งเฉพาะข้อมูลการเชื่อมต่อไปตรวจ และแยกผลลัพธ์เป็น 3 ทาง คือเชื่อมต่อสำเร็จ, เซิร์ฟเวอร์ตอบกลับแต่เชื่อมต่อไม่ได้ (แสดงเหตุผลจากเซิร์ฟเวอร์) และคำขอล้มเหลว
- ตารางเวลา — กำหนดเวลาทำงานอัตโนมัติเป็น cron expression และเปิด/ปิดการทำงานตามตารางด้วยสวิตช์ โดยหน้าเว็บไม่ได้ตรวจรูปแบบ cron ให้
- การแม็ปฟิลด์ — เป็นรายการที่เพิ่มลบแถวได้ แต่ละแถวมี 4 ช่องที่บังคับกรอกทั้งหมด ได้แก่ ชื่อคอลัมน์ใน BigQuery, คีย์คุณสมบัติปลายทาง (ช่องกรอกมีคำนำหน้า
custom.ติดอยู่ ผู้ใช้กรอกเฉพาะส่วนหลัง), ชนิดข้อมูล (ข้อความ / ตัวเลข / วันที่ / ค่าตรรกะ) และชื่อที่ใช้แสดงผล - สถานะรอบล่าสุด — ปรากฏเฉพาะเมื่อบันทึกการตั้งค่าไว้แล้ว แสดงเวลาที่ซิงก์ล่าสุดและผลลัพธ์เป็นป้ายกำกับ ได้แก่ จำนวนผู้ใช้ที่ถูกอัปเดต, จำนวนข้อผิดพลาด (แสดงเมื่อมากกว่าศูนย์) และระยะเวลาที่ใช้ หากยังไม่เคยซิงก์จะแสดงข้อความแจ้งแทน พร้อมปุ่ม ซิงก์ทันที
การบันทึก
- ปุ่มบันทึกเปลี่ยนข้อความตามสถานการณ์ระหว่าง "สร้าง" กับ "อัปเดต" เมื่อกดจะตรวจความถูกต้องของฟอร์มก่อน
- ก่อนส่ง ระบบจะประกอบข้อมูลใหม่ โดยใส่ค่าเริ่มต้นให้คอลัมน์ระบุตัวผู้ใช้หากเว้นว่าง และ เติมคำนำหน้า
custom.กลับเข้าไปในคีย์คุณสมบัติทุกแถว โดยเขียนให้ปลอดภัยต่อกรณีที่ผู้ใช้พิมพ์คำนำหน้ามาเองแล้ว - หากยังไม่มีการตั้งค่าเดิมจะเป็นการสร้างใหม่ ถ้ามีแล้วจะเป็นการแก้ไข ทั้งสองทางเมื่อสำเร็จจะแจ้งผลและโหลดข้อมูลใหม่ ส่วนกรณีผิดพลาดจะแสดงข้อความจากเซิร์ฟเวอร์
- เมื่อออกจากหน้า ระบบจะล้างสถานะกำลังโหลดเสมอเพื่อไม่ให้ค้างข้ามหน้า
การสั่งซิงก์ทันที
- ระบบตรวจก่อนว่ามีการตั้งค่าที่บันทึกแล้วหรือไม่ ถ้ายังไม่มีจะแจ้งเตือนให้บันทึกก่อน
- เมื่อสั่งสำเร็จ หน้าจอจะแจ้งว่าเริ่มงานแล้วและโหลดข้อมูลใหม่เพื่อดูเวลาและผลลัพธ์รอบล่าสุด
- การซิงก์จริงทำงานเบื้องหลังแบบไม่พร้อมกัน การโหลดข้อมูลใหม่ทันทีอาจยังเห็นค่าเดิม เพราะหน้าจอไม่ได้ติดตามความคืบหน้าต่อเนื่อง ผู้ใช้จึงต้องรีเฟรชหน้าอีกครั้งเพื่อดูผลลัพธ์
หน้าจอและองค์ประกอบหลัก
หน้าเพจ (src/app/bigquery-sync/page.tsx) — ตั้ง breadcrumb สองชั้นใต้เมนูการตั้งค่า และเรนเดอร์ตัวควบคุมของฟอร์ม
ตัวควบคุม (src/components/bigquery-sync/bigquery-sync-form.container.tsx) — รวมตรรกะทั้งหมด ทั้งการโหลดการตั้งค่า การสร้างและแก้ไข การทดสอบการเชื่อมต่อ การสั่งซิงก์ และการแปลงคำนำหน้าคีย์คุณสมบัติทั้งขาเข้าและขาออก
ตัวฟอร์ม (src/components/bigquery-sync/bigquery-sync-form.tsx) — จัดวางการ์ดทั้ง 4 ใบ รายการแม็ปฟิลด์แบบเพิ่มลบแถวได้ และการแสดงสถานะรอบล่าสุด
เซอร์วิสกลาง (src/services/bigquery-sync.service.ts) — ครอบคลุมการอ่านการตั้งค่า, สร้าง, แก้ไข, ทดสอบการเชื่อมต่อ, สั่งซิงก์ และอ่านสถานะการซิงก์ โดยฟังก์ชันอ่านสถานะยังไม่ถูกใช้ในหน้าจอ เพราะหน้าจออ่านสถานะรอบล่าสุดจากข้อมูลการตั้งค่าโดยตรง
โครงสร้างข้อมูล — การตั้งค่าหนึ่งชุดประกอบด้วย 4 ส่วน คือข้อมูลการเชื่อมต่อ, ตารางเวลา, รายการแม็ปฟิลด์ และผลลัพธ์รอบล่าสุด โดยการแม็ปฟิลด์หนึ่งแถวเก็บชื่อคอลัมน์ต้นทาง, คีย์ปลายทาง, ชนิดข้อมูล และชื่อที่ใช้แสดง
จุดเชื่อมต่อกับฟีเจอร์อื่น
- สิทธิ์การเข้าถึง — มี subject
bigquery-syncประกาศไว้และปลดล็อกด้วยโมดูลระบบฝั่งหลังบ้าน แต่ในทางปฏิบัติหน้านี้ไม่ได้ตรวจสิทธิ์ ทั้งที่ตัวหน้าเพจและที่การแสดงเมนูย่อย - ระบบภายนอก Google BigQuery — ต้องมีโปรเจกต์ GCP, ตารางสรุป, คอลัมน์ที่เป็น LINE user ID และข้อมูลรับรอง service account การเชื่อมต่อจริงและการทำงานตามตารางเวลาทำที่ฝั่งเซิร์ฟเวอร์และ worker ทั้งหมด หน้าเว็บเพียงเก็บค่าและสั่งงาน
- ตั้งค่าคุณสมบัติผู้ใช้ (Attribute Setup) — คีย์ที่แม็ปมาอยู่ใน namespace
custom.เดียวกับคุณสมบัติเพิ่มเติมของผู้ใช้ในระบบ ทำให้ข้อมูลจาก BigQuery ถูกนำไปใช้ทำกลุ่มเป้าหมายและ segment ต่อได้ทันที - การจัดการสถานะและ UI — หน้านี้ต่างจากหน้าอื่นของ CMS ตรงที่ใช้ข้อความแจ้งเตือนแบบสั้นทั้งหมด ไม่ใช้หน้าต่างยืนยันหรือหน้าต่างผลลัพธ์ ไม่มีส่วนหัวหน้ามาตรฐาน และไม่มีการตรวจรูปแบบ cron หรือ JSON ที่ฝั่งหน้าเว็บ
รายละเอียดฝั่ง Backend (CMS API)
โมดูลนี้อยู่ที่ internal/modules/bigquerysync/ ลงทะเบียนใต้กลุ่ม /api/bigquery-sync-config โดยตัวเชื่อมต่อ BigQuery จริงอยู่ที่แพ็กเกจ internal/bigqueryx
ข้อสังเกตด้านความปลอดภัยที่สำคัญที่สุดของหน้านี้
- ทุก endpoint ของโมดูลนี้อยู่บนกลุ่มสาธารณะและตรวจด้วย token ระดับ "ล็อกอินแล้ว" เท่านั้น ไม่มีการตรวจ policy ใด ๆ และไม่มี
ModuleGateยกโครงมาจากระบบเดิมที่ไม่ได้ใส่การตรวจสิทธิ์ไว้ - ผลในทางปฏิบัติคือ ใครก็ตามที่ล็อกอินเข้าระบบได้ ก็เรียก endpoint เหล่านี้ได้ ไม่ว่าจะมีสิทธิ์อะไรอยู่ ซึ่งสอดคล้องกับที่หน้าเว็บเองก็ไม่ได้ตรวจสิทธิ์ทั้งที่ตัวหน้าและที่เมนูย่อย
- เรื่องนี้มีน้ำหนักเป็นพิเศษเพราะโมดูลนี้เก็บ ข้อมูลรับรอง service account ของ Google Cloud และมีปุ่มสั่งซิงก์ข้อมูลผู้ใช้ออกไปยังปลายทางที่ผู้เรียกกำหนดเองได้ จึงควรถือเป็นรายการที่ต้องจัดการก่อนเมื่อจะเปิดบังคับใช้สิทธิ์จริง
- ขอบเขตข้อมูลยังคงอ่านจาก context ของ request (
lineOaId,organizationId) ดังนั้นผู้ใช้ยังเห็นเฉพาะการตั้งค่าของ OA ที่ตนกำลังทำงานอยู่
สิ่งที่แต่ละ endpoint ทำจริง
GET /api/bigquery-sync-config— อ่านการตั้งค่าปัจจุบันของ OAPOST /api/bigquery-sync-config/test-connection— ลองเชื่อมต่อ BigQuery ด้วยข้อมูลรับรองที่กรอกมา โดยยังไม่บันทึกลงฐานข้อมูล แล้วคืนผลว่าสำเร็จหรือไม่พร้อมข้อความอธิบาย จุดประสงค์คือให้รู้ก่อนกดบันทึกว่าตั้งค่าถูกหรือเปล่าPOST /api/bigquery-sync-config— บันทึกการตั้งค่า ประกอบด้วยรหัสโปรเจกต์, dataset, ข้อมูลรับรอง, ตารางที่จะซิงก์ และตารางเวลาPUT /api/bigquery-sync-config/:id— แก้ไขการตั้งค่าเดิมPOST /api/bigquery-sync-config/:id/sync-now— สั่งซิงก์ทันที คืนผลว่าสำเร็จหรือไม่พร้อมข้อความGET /api/bigquery-sync-config/:id/sync-status— อ่านผลรอบล่าสุด คืนเวลาที่ซิงก์ครั้งสุดท้าย (อาจเป็นค่าว่างถ้ายังไม่เคยซิงก์) และผลลัพธ์รอบล่าสุดในรูป JSON ดิบตามที่บันทึกไว้ ไม่ได้แปลงเป็นโครงสร้างมาตรฐาน ฝั่งหน้าจอจึงต้องเผื่อรูปข้อมูลที่หลากหลาย
ข้อควรรู้เกี่ยวกับการเชื่อมต่อ
- ระบบไม่ได้เชื่อมต่อ BigQuery ตอนเริ่มบริการ แต่สร้างตัวเชื่อมต่อเปล่าไว้แล้วจึงเชื่อมจริงเมื่อมีการเรียกใช้ ผลคือการตั้งค่าที่ผิดจะไม่ทำให้บริการเริ่มไม่ขึ้น แต่จะไปแสดงตัวตอนกดทดสอบการเชื่อมต่อหรือตอนถึงรอบซิงก์แทน
- การซิงก์ตามตารางเวลาไม่ได้ทำงานในบริการนี้ แต่ทำที่ฝั่ง worker CMS API มีหน้าที่เก็บการตั้งค่าและสั่งงานเท่านั้น สถานะที่หน้าจออ่านจึงเป็นสิ่งที่ worker เขียนกลับมา
- ไม่มีการตรวจรูปแบบ cron หรือรูปแบบ JSON ของข้อมูลรับรองที่ฝั่งหน้าเว็บ และฝั่งนี้ก็ไม่ได้ประกาศ policy ตรวจอะไรเพิ่ม ค่าที่ผิดรูปจึงจะไปพังตอนรันจริง ไม่ใช่ตอนบันทึก
ตารางที่เกี่ยวข้อง
bigquery_sync_config และ line_oa