การคำนวณสถิติ Rich Menu
ภาพรวม
รายงานที่ตอบคำถามว่า "ปุ่มไหนบนเมนูถูกกดมากที่สุด" เกิดจากการ aggregate ข้อมูลใน tracking_log
เทียบกับผังปุ่มของแต่ละเมนูที่เก็บไว้ในตาราง rich_menu_action
งานนี้แยกออกเป็น 2 ระดับเพื่อให้ scale ได้:
calculate_rich_menu_stat— งานระดับ fan-out ทำหน้าที่หาว่ามี rich menu ตัวไหนที่ต้องคำนวณบ้าง แล้วแตกออกเป็นงานย่อยcalculate_rich_menu_stat_item— งาน คำนวณจริง ของ rich menu หนึ่งตัว
การแยกในลักษณะนี้ทำให้ rich menu ที่มี log จำนวนมากไม่ block ตัวอื่น และสามารถ retry ได้เป็นรายเมนู
Business Flow
Trigger จาก cron (profile cron-scheduler)
- ทุกชั่วโมงตรง (
0 * * * *)RichMenuStatScannerServiceจะสแกน Redis เพื่อหา keyRICH_MENU_STAT_DIRTY:ตามด้วย rich menu id ซึ่งถูกตั้งไว้โดยเส้นทาง tracking เมื่อมีผู้ใช้คลิกเมนู - แกะ id ออกจาก key แล้ว publish หนึ่ง job ต่อหนึ่ง rich menu เข้า queue
calculate_rich_menu_stat_item - หากไม่พบ key dirty เลย จะข้ามรอบนั้นไป
calculate_rich_menu_stat (profile main)
processCalculateRichMenuStat จะค้นหา rich menu ที่ยังมีสถานะ active ทั้งหมด
แล้ว publish calculate_rich_menu_stat_item ทีละตัว ถือเป็นการ fan-out แบบเต็มรอบ
calculate_rich_menu_stat_item (profile main)
- โหลด rich menu พร้อม
rich_menu_actionของทุกปุ่มด้วยการ join โดยเก็บค่าtype,label,link(ปลายทางต้นฉบับก่อนถูกห่อด้วย tracking redirect) และindex transformRichMenuจัดโครงข้อมูลให้เป็นเมนูหนึ่งตัวพร้อมรายการ action- ดึง
tracking_logของเมนูนั้นมาสรุปด้วยsummarizeRichMenuStatstotalClick— จำนวนคลิกทั้งหมดของแต่ละปุ่มuniqueClick— จำนวนline_uidที่ไม่ซ้ำกัน
- ผลลัพธ์ที่ได้อยู่ในรูป
statDataซึ่งเป็น array ของรายการที่มีฟิลด์type,label,link,totalClickและuniqueClick - เขียนผลกลับลงตาราง
rich_menuและrich_menu_archiveสำหรับเมนูประเภท member/guest ที่มีการเก็บ archive ไว้
ไฟล์และฟังก์ชันหลัก
internal/richmenu/consumer.go—OnProcessCalculateRichMenuStat,OnProcessCalculateRichMenuStatItem, structRichMenuStatPayloadinternal/richmenu/service_stats.goService.calculateRichMenuStats(ctx, richMenuInfo)transformRichMenu(),summarizeRichMenuStats()- struct
statDataและstatItem(ฟิลด์Type,Label,Link,TotalClick,UniqueClick)
internal/richmenu/service_methods.go—processCalculateRichMenuStat(),processCalculateRichMenuStatItem()internal/cronscheduler/rich_menu_stat_scanner.go—RichMenuStatScannerService.Run(ctx)และค่าคงที่richMenuDirtyKeyPrefix = "RICH_MENU_STAT_DIRTY:"- Queue:
calculate_rich_menu_statและcalculate_rich_menu_stat_item(profilemain) โดยมี cron ที่ profilecron-schedulerเป็นผู้ publish
จุดเชื่อมต่อกับ Service อื่น
- ตารางที่เกี่ยวข้อง:
tracking_log(ข้อมูลดิบ),rich_menuและrich_menu_action(ผังปุ่ม),rich_menu_archive(เก็บ snapshot สถิติของเมนูที่ถูกเปลี่ยน) - Redis: key ที่ขึ้นต้นด้วย
RICH_MENU_STAT_DIRTY:ใช้เป็นตัวชี้ว่าเมนูใดมีข้อมูลใหม่รอคำนวณ - ผู้บริโภคผลลัพธ์: cms-api-go และ cms-web ในหน้ารายงาน rich menu
- งานนี้ไม่มีการเรียก LINE API