Skip to main content

การส่ง Campaign แบบ Multicast / เจาะกลุ่มเป้าหมาย

ภาพรวม​

Multicast คือการส่ง campaign ไปยัง กลุ่มผู้รับที่ระบุไว้ (audience) หรือถึงสมาชิกทั้งหมดของ OA เท่าที่มีอยู่ในฐานข้อมูล ต่างจาก broadcast ตรงที่ต้องรู้ lineUserId ของผู้รับทุกคน แต่แลกมาด้วยความสามารถในการใช้ merge tag เพื่อใส่ชื่อผู้รับลงในข้อความ และสร้าง tracking link รายบุคคล ได้

นี่คือเส้นทางที่หนักที่สุดในระบบ เพราะจำนวนผู้รับอาจมีตั้งแต่หลักแสนถึงหลายล้านคน จึงต้องมีกลไก concurrency, resume, dry-run และรองรับการเลือกใช้ LINE API ได้ 2 รูปแบบ

Business Flow​

  1. รับ payload ที่ประกอบด้วย campaignId, audienceId, organizationId และ lineOaId พร้อมเปิด claim heartbeat ที่อัปเดตทุก 5 นาที

  2. Resolve OA และ validate campaign ด้วยเงื่อนไขเดียวกับ broadcast จากนั้นโหลด quick reply ล่วงหน้าเพียงครั้งเดียว หากโหลดไม่สำเร็จระบบจะส่งข้อความต่อไปโดยไม่มี quick reply แทนที่จะล้มทั้ง campaign

  3. หารายชื่อผู้รับ แยกออกเป็น 3 กรณี

    • มี audienceId และ audience มีไฟล์ CSV ระบุไว้ที่ info.lineUserIdsPathFilename — อ่านไฟล์ CSV จาก S3 แบบแบ่งหน้า ครั้งละ 10,000 รายชื่อจนครบ
    • มี audienceId แต่ไม่มี CSV ซึ่งหมายถึง automated audience — query จากตาราง line_user โดยกรองด้วยเงื่อนไข audience_ids @> to_jsonb($1::int) และ line_oa_id
    • ไม่มี audienceId — เรียก FindAllMemberUID เพื่อดึงสมาชิกทั้งหมดของคู่ lineOaId และ organizationId
  4. ตรวจว่าเนื้อหามี merge tag หรือไม่ โดยดูจาก campaign.has_merge_tags หรือสแกนเนื้อหาโดยตรง แล้วเลือกเส้นทางส่ง

    เส้นทาง A — LINE Multicast API ใช้เมื่อ ไม่มี merge tag และเปิด MULTICAST_USE_BATCH_API

    • สร้าง redirect mapping แบบ shared เพียงครั้งเดียว และ transform message เพียงครั้งเดียว
    • ยิงทีละ batch ขนาด 500 คน โดยใช้ retry key รูปแบบ campaign:<id>:multicast:<batchNo>
    • เป็นเส้นทางที่เร็วและประหยัดจำนวน API call มากที่สุด

    เส้นทาง B — Push Message รายคน เป็นค่าเริ่มต้น และถูกบังคับใช้เมื่อมี merge tag

    • แบ่งผู้รับเป็น batch แล้วในแต่ละ batch จะ bulk-fetch ข้อมูลผู้ใช้ เช่น display_name, firstname, email, custom_attribute เฉพาะกรณีที่มี merge tag เท่านั้น
    • กระจายงานให้ worker ทำงานพร้อมกันตามค่า MULTICAST_CONCURRENCY (ค่าเริ่มต้น 200)
    • สำหรับผู้ใช้แต่ละคน ระบบจะ resolve merge tag → สร้าง tracking link ที่ผูกกับ lineUserId → transform message → แนบ quick reply → เรียก push message
    • ผู้ใช้ที่หาข้อมูลสำหรับ merge tag ไม่เจอจะถูก skip โดยนับไว้ใน skippedCount และเก็บ 100 รายแรกไว้ใน log ตามค่าตั้งใน campaign.skip_merge_tag_missing
  5. รองรับการ resume — บันทึกผู้รับที่ส่งสำเร็จลง Redis set แยกตาม campaign หาก message ถูก redeliver ระหว่างการส่ง คนที่ส่งไปแล้วจะถูกข้ามไปโดยอัตโนมัติ หาก Redis ล่มก็ไม่ block การส่ง

  6. Dry-run — เมื่อเปิด MULTICAST_DRY_RUN ระบบจะทำทุกขั้นตอนตามปกติยกเว้นการยิง LINE API จริง

  7. จบงาน — อัปเดตตาราง campaign ด้วย line_message_object, template_tracking, rich_message_content, end_tracking_date, total_recipient และตั้งสถานะเป็น sent หรือหากล้มเหลวจะเข้า multicastFailed ซึ่งคืนเนื้อหาต้นฉบับ ตั้งสถานะเป็น failed พร้อมบันทึก reason

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

  • internal/linemessageapi/multicast.go
    • MulticastService.HandleLineMulticastRichMessage(ctx, payload) — flow ทั้งหมดของ feature นี้
    • struct MulticastToggles ซึ่งเก็บค่า DryRun, UseBatchAPI และ Concurrency
    • sentSetKey(), isAlreadySent(), markSent() — กลไก resume ผ่าน Redis
    • multicastFailed()
  • internal/linemessageapi/consumer.go — Consumer.HandleLineMulticastRichMessage และ withClaimHeartbeat
  • internal/linemessageapi/mergetag.go — ResolveMergeTags(), extractMergeTagKeys(), hasMergeTags()
  • internal/linemessageapi/extend.go — createRedirectMappings() ในโหมดรายผู้ใช้
  • internal/csvaudience/csvaudience.go — อ่านไฟล์ CSV ของ audience จาก S3 ผ่าน Count และ Page
  • cmd/worker/integration.go — adapter audienceForLineMessageApi และ lineUserRepoForLineMessageApi
  • Queue: line_multicast_rich_message บน profile main

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

  • แหล่งที่มาของงาน — scanner ของ queue process_campaign หรือ cms-api-go กรณีสั่งส่งทันที
  • ตารางที่เกี่ยวข้อง — campaign, rich_message, audience (อ่าน info.lineUserIdsPathFilename), line_user (รายชื่อผู้รับและข้อมูลสำหรับ merge tag), line_oa และกลุ่มตาราง quick reply
  • S3 — เก็บไฟล์ CSV รายชื่อ audience
  • Redis — เก็บ sent-set สำหรับกลไก resume
  • LINE API — POST /v2/bot/message/multicast สำหรับเส้นทาง A และ POST /v2/bot/message/push สำหรับเส้นทาง B
  • Environment variable ที่ปรับพฤติกรรมได้ — MULTICAST_DRY_RUN, MULTICAST_USE_BATCH_API, MULTICAST_CONCURRENCY
  • มีเอกสารออกแบบ chunked delivery สำหรับอนาคต ซึ่งจะเพิ่ม queue line_campaign_delivery_batch และตาราง campaign_delivery_batch อยู่ที่ docs/campaign-delivery-tracking-redesign.md ใน repository ของ worker