Skip to main content

การส่ง Campaign แบบ Broadcast (ส่งถึงเพื่อนทุกคนของ OA)

ภาพรวม​

Broadcast คือการส่ง rich message ของ campaign ไปยัง เพื่อนทุกคนของ LINE OA ด้วยการเรียก LINE Broadcast API เพียงครั้งเดียว โดยไม่ต้องระบุรายชื่อผู้รับ จึงเป็นเส้นทางที่ประหยัดและเร็วที่สุด ต่างจาก multicast ที่ต้องไล่ส่งทีละกลุ่ม

งานนี้รับ job จาก queue line_broadcast_rich_message แล้วทำหน้าที่ตรวจสอบความถูกต้องของ campaign และ OA, สร้าง tracking link ให้ทุก URL และรูปภาพในข้อความ, แปลง message object, ยิง LINE Broadcast API แล้วเขียนผลลัพธ์กลับลงตาราง campaign

Business Flow​

  1. รับ payload ที่ประกอบด้วย campaignId, audienceId, organizationId และ lineOaId
  2. เปิด claim heartbeat — background ticker อัปเดต campaign.claimed_at เป็นเวลาปัจจุบันทุก 5 นาทีระหว่างการส่ง โดย guard ด้วยเงื่อนไข status='sending' เพื่อไม่ให้ reaper ยึด campaign คืนกลางคัน
  3. Validate campaign — GetCampaignAndValidate โหลด campaign พร้อม rich_message.content ด้วย LEFT JOIN โดยเคารพ soft delete
    • สถานะ draft หรือ cancel จะถูกเปลี่ยนเป็น failed แล้วโยน error ออกไป
    • สถานะที่ไม่ใช่ sending ถือเป็น duplicate หรือ late redelivery จึงทิ้งเงียบ ๆ ด้วย permanent error ไม่มีการ republish
  4. สำเนาเนื้อหาต้นฉบับ — clone เนื้อหา rich message ต้นฉบับเก็บไว้ เพื่อใช้ rollback หากการส่งล้มเหลว
  5. Validate OA — GetLineOAAndValidate resolve OA และคืน channelAccessToken ที่ผ่านการ verify หรือ refresh แล้ว หาก OA ไม่อยู่ในสถานะ active จะเปลี่ยน campaign เป็น failed
  6. สร้าง redirect mapping — ดึงทุก URL และ image URL ในเนื้อหาแล้วแทนที่ด้วย tracked URL
    • broadcast ใช้ token และลิงก์แบบ shared ไม่ผูกกับ userId เพราะระบบไม่ทราบล่วงหน้าว่าใครจะเห็นข้อความ
    • เลือกเส้นทางตามค่า CAMPAIGN_REDIRECT_MODE ระหว่าง legacy universal-redirect กับ builtin encrypted token (ดูลิงก์ติดตามผลของ Campaign)
  7. แปลงข้อความ — TransformMessageObjects แทนที่ URL เดิมด้วย tracked URL ในโครงสร้าง message และแนบ quick reply หาก campaign ผูกกับ quick_reply_id ไว้
  8. ยิง LINE Broadcast API พร้อมแนบ retry key
  9. เขียนผลกลับ — อัปเดตตาราง campaign ด้วย line_message_object, template_tracking, rich_message_content, end_tracking_date (เท่ากับ start_date บวก 90 วัน), total_recipient และตั้งสถานะเป็น sent
  10. กรณีล้มเหลว — broadcastFailed จะคืนเนื้อหาต้นฉบับกลับ ตั้งสถานะเป็น failed พร้อมบันทึก reason ส่วน error ระดับ validation หรือ setup จะถูก log แล้ว swallow (return nil เพื่อ ack) ตามพฤติกรรมของระบบเดิม

ไฟล์และฟังก์ชันหลัก​

  • internal/linemessageapi/broadcast.go
    • BroadcastService.HandleLineBroadcastRichMessage(ctx, payload)
    • broadcastFailed() และ endTrackingDateFrom() ซึ่งกำหนดช่วง tracking 90 วัน
    • struct LineBroadcastRichMessagePayload
  • internal/linemessageapi/consumer.go — Consumer.HandleLineBroadcastRichMessage และ withClaimHeartbeat() ที่ใช้ค่า claimHeartbeatInterval เท่ากับ 5 นาที
  • internal/linemessageapi/extend.go — extendService.createRedirectMappings(), buildBuiltinMappings(), getGaSettings(), getLineLiffId()
  • internal/linemessageapi/util.go — TransformMessageObjects(), ExtractUrls(), ExtractImageUrls()
  • internal/quickreply/attach.go — LoadItems() สำหรับแนบ quick reply
  • internal/line/messaging.go — Client.Broadcast(messages, retryKey)
  • Queue: line_broadcast_rich_message บน profile main

จุดเชื่อมต่อกับ Service อื่น​

  • แหล่งที่มาของงาน — scanner ของ queue process_campaign (ดูการจ่ายงาน Campaign ตามกำหนดเวลา) หรือจาก cms-api-go กรณีผู้ใช้สั่งส่งทันที
  • ตารางที่เกี่ยวข้อง — campaign (อ่านและอัปเดต), rich_message (อ่าน content และ quick_reply_id), line_oa (token), quick_reply และ quick_reply_item
  • LINE API — POST /v2/bot/message/broadcast สำหรับส่งข้อความ และ GET /v2/bot/insight/followers สำหรับนับจำนวน follower เพื่อใช้เป็น total recipient
  • Redirect service และ campaignlink — ใช้สร้าง tracked URL
  • ผลที่ตามมา — เมื่อผู้ใช้คลิกลิงก์ ระบบจะ INSERT ลง tracking_log ทำให้ Postgres trigger ยิงเข้า campaign_click_trigger และสถิติจะถูกคำนวณโดยการคำนวณสถิติ Campaign