การรีเฟรช Audience อัตโนมัติ
ภาพรวม
Audience ประเภท automated คือกลุ่มเป้าหมายที่นิยามด้วยเงื่อนไข filter แทนที่จะเป็นรายชื่อตายตัว จึงต้องคำนวณสมาชิกใหม่เป็นระยะเพื่อให้ข้อมูลทันสมัยอยู่เสมอ
ตรรกะของ filter builder อยู่ที่ฝั่ง cms-api ดังนั้นการคำนวณจริงจึงเกิดขึ้นที่นั่น ส่วน worker ตัวนี้ทำหน้าที่เป็น "ตัวจ่ายงานที่ทนทาน" คือรับข้อความจากคิวแล้วยิง HTTP request ไปเรียก endpoint ภายในของ cms-api
การออกแบบเช่นนี้ให้ประโยชน์สองข้อ ข้อแรกคือได้ retry และ DLQ semantics ของ RabbitMQ มาโดยไม่ต้องเขียนเพิ่ม และข้อที่สองคืองานคำนวณที่ใช้เวลาหลายนาทีจะไม่ไปค้างอยู่ใน HTTP request ของผู้ใช้
Business Flow
- รับ payload ชนิด
AudienceRefreshPayloadซึ่งมีaudienceIdและฟิลด์อื่นตามที่ผู้ผลิตงานส่งมา - อ่าน base URL จากตัวแปรสภาพแวดล้อม
CMS_API_BASE_URLโดยมีค่าสำรองเป็นhttp://localhost:3000และอ่าน key จากINTERNAL_API_KEY - ยิงคำขอ
POSTไปที่/api/audiences-filter/internal/refreshของ cms-api- แนบ header
x-internal-keyพร้อมค่าจากINTERNAL_API_KEYและContent-Type: application/json - body คือ payload ทั้งก้อนที่ส่งต่อไปแบบไม่ดัดแปลง
- ตั้ง timeout ไว้ที่ 5 นาที ให้ตรงกับ axios timeout ของระบบเดิม เพื่อรองรับ audience ขนาดใหญ่
- แนบ header
- หากได้ HTTP status ในกลุ่ม 2xx ถือว่าสำเร็จ บันทึก log แล้วตอบ ack
- หากเกิด transport error หรือได้ status ที่ไม่ใช่ 2xx จะบันทึก log แล้วคืนค่า error ให้ชั้น mq เป็นผู้ตัดสินใจ โดยกรณี transient เช่น 5xx หรือ timeout จะถูก retry ตามลำดับ 1 วินาที 4 วินาที และ 9 วินาที ก่อนส่งเข้า DLQ
ไฟล์และฟังก์ชันหลัก
internal/audience/refresh_consumer.goRefreshConsumer.OnAudienceRefresh(ctx, body)— handler หลักของงานนี้NewRefreshConsumer(cfg, log)และRegister(reg, cfg)- ค่าคงที่
refreshPathมีค่าเป็น/api/audiences-filter/internal/refreshและrefreshTimeoutมีค่าเป็น 5 นาที logRefreshFailed()
internal/audience/payloads.go— นิยามชนิดAudienceRefreshPayloadcmd/worker/main.go— ลงทะเบียน consumer ในrunMain()ด้วยaudience.NewRefreshConsumer(cfg, log).Register(reg, cfg)- คิวที่เกี่ยวข้อง:
audience_refresh(runtime profilemain)
จุดเชื่อมต่อกับ Service อื่น
- ต้นทางของงาน — cms-api-go หรือ cron ฝั่ง CMS ที่ต้องการให้คำนวณสมาชิก audience ใหม่
- ปลายทางที่เรียกออกไป — endpoint ภายในของ cms-api-go คือ
POST /api/audiences-filter/internal/refreshซึ่งป้องกันด้วย headerx-internal-key - ตัวแปรสภาพแวดล้อม —
CMS_API_BASE_URLและINTERNAL_API_KEY - ไม่แตะฐานข้อมูลและไม่เรียก LINE API โดยตรง เพราะเป็น consumer แบบ forward ล้วน
- ผลลัพธ์ปลายทาง —
line_user.audience_idsและaudience.infoจะถูกอัปเดตโดย cms-api เป็นผู้เขียนเอง