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 campaignGetCampaignAndValidate โหลด 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 OAGetLineOAAndValidate 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.goConsumer.HandleLineBroadcastRichMessage และ withClaimHeartbeat() ที่ใช้ค่า claimHeartbeatInterval เท่ากับ 5 นาที
  • internal/linemessageapi/extend.goextendService.createRedirectMappings(), buildBuiltinMappings(), getGaSettings(), getLineLiffId()
  • internal/linemessageapi/util.goTransformMessageObjects(), ExtractUrls(), ExtractImageUrls()
  • internal/quickreply/attach.goLoadItems() สำหรับแนบ quick reply
  • internal/line/messaging.goClient.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 APIPOST /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