Skip to main content

การเรียก API ภายนอกจาก Workflow

ภาพรวม

Action ประเภท web_request เปิดให้ลูกค้าเชื่อม workflow เข้ากับระบบภายนอกได้ ตัวอย่างการใช้งาน ที่พบบ่อยคือ เช็คแต้มสะสมจาก CRM ของลูกค้าเอง แล้วนำค่าที่ได้กลับมาเก็บเป็น attribute ของผู้ใช้ จากนั้นจึงส่งข้อความที่มีค่านั้นออกไป

งานนี้ถูกแยกออกมาเป็น profile ของตัวเอง (SVC=web-request-worker) เพราะปลายทางเป็น API ของลูกค้าที่อาจตอบช้าหรือล่มได้ จึงไม่ควรปล่อยให้มาถ่วง action queue หลัก

Business Flow

  1. รับ ActionExecutePayload แบบเดียวกับ action_execute แต่มี actionType = web_request
  2. อ่าน WebRequestActionConfig จาก actionConfig ซึ่งประกอบด้วย method, url, headers, body, responseMappings, postAction และ config ของ retry กับ timeout
  3. Resolve merge tag ใน url, headers และ body โดยรองรับรูปแบบ {{...}} จาก 3 แหล่ง
    • system attribute ผ่าน systemattribute.Service ซึ่ง cache ไว้ใน Redis
    • ฟิลด์ของ line_user และ custom_attribute
    • ค่า userId โดยตรง
  4. ยิง HTTP request พร้อม retry
    • timeout ค่า default 30,000 มิลลิวินาที (defaultTimeoutMs)
    • retry ได้สูงสุด 3 ครั้ง (defaultRetryMaxAttempts) โดยเริ่ม backoff ที่ 1,000 มิลลิวินาที
    • แยกชนิดของ error ชัดเจน — clientError (กลุ่ม 4xx ไม่ retry) และ serverError (กลุ่ม 5xx retry ได้ และ expose StatusCode() ให้ชั้น mq จำแนกเป็น transient error)
  5. Map ผลลัพธ์กลับ ผ่าน processResponseMappings โดยแต่ละ mapping ใช้ JSONPath ดึงค่าออกจาก response แล้วเขียนลงปลายทาง
    • ปลายทางเป็นได้ทั้ง system attribute และ user attribute (line_user.custom_attribute)
    • รองรับ template {{value}} สำหรับประกอบค่าใหม่
    • หาก mapping ตัวใดตัวหนึ่งล้มเหลว จะไม่ทำให้ทั้งงานพัง
  6. postAction — หากมีการกำหนดไว้ ระบบจะประกอบ ActionExecutePayload ตัวใหม่แล้ว publish เข้า action_execute เพื่อทำ action ต่อ เช่น ส่งข้อความที่มีแต้มที่เพิ่งดึงมา ถือเป็นการต่อ workflow ให้เป็นสาย
  7. onError — หากใน config มี branch สำหรับ error ระบบจะเดินเส้นทาง error แทน

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

  • internal/webrequest/service.go
    • Service.Execute(ctx, payload) — entry point และ execute() ที่เป็น flow จริง
    • executeWithRetry(), doRequest(), onError()
    • processResponseMappings(), processOneMapping()
    • resolveMergeTags(), resolveHeaderMergeTags(), getLineUser()
    • error type ได้แก่ clientError, serverError (มีเมธอด StatusCode()) และ statusError
    • ค่าคงที่ defaultTimeoutMs = 30000, defaultRetryMaxAttempts = 3, defaultRetryBackoffMs = 1000
  • internal/webrequest/consumer.goConsumer.HandleWebRequest
  • internal/webrequest/config.go — struct WebRequestActionConfig และ ResponseMapping
  • internal/webrequest/jsonpath.go — implementation ของ JSONPath ซึ่งเทียบเคียงกับ jsonpath-plus ที่ระบบเดิมใช้
  • internal/systemattribute/systemattribute.go — อ่านและเขียน system attribute พร้อม cache ใน Redis
  • cmd/worker/main.gorunWebRequestWorker()
  • Queue: consume web_request_execute และ publish action_execute (profile web-request-worker)

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

  • รับ job จาก: เครื่องยนต์ Trigger / Workflow Automation โดย executeAction จะเลือก queue นี้เมื่อ rule.actionType เท่ากับ web_request
  • ตารางที่เกี่ยวข้อง: line_user (ใช้ทั้ง merge tag และเขียนค่ากลับลง custom_attribute) รวมถึง system_attribute และ attribute_master
  • Redis: cache ของ system attribute
  • HTTP ภายนอก: API ของลูกค้า ตาม method, url และ headers ที่กำหนดใน config
  • RabbitMQ: publish เข้า action_execute สำหรับ postAction
  • งานนี้ไม่เรียก LINE API โดยตรง การส่งข้อความจะเกิดขึ้นที่ postAction ผ่าน action executor