ข้ามไปยังเนื้อหา

Bulk & Async Operations

API ของจริงบางครั้งต้องแก้ resource ทีละมาก ๆ ในคราวเดียว หรือเริ่มงานที่กินเวลานานเกินกว่า request หนึ่งตัวจะรอไหว ทั้งสองกรณียืดโมเดลหนึ่ง request ต่อหนึ่ง resource ออกไป จึงต้องออกแบบอย่างตั้งใจ

ในการกระทำต่อ item หลายตัวในการเรียกครั้งเดียว ให้ POST ไปยัง batch endpoint พร้อม list และคืน ผลลัพธ์รายตัว (per-item result) เพื่อให้ผู้เรียกรู้ได้อย่างแม่นยำว่าอะไรสำเร็จบ้าง:

POST /articles/batch HTTP/1.1
Content-Type: application/json
{ "items": [ { "title": "A" }, { "title": "" } ] }

response รายงานผลลัพธ์ของ item แต่ละตัวแทนที่จะเป็น status รวมเพียงค่าเดียว — ความสำเร็จบางส่วน (partial success) คือเรื่องปกติสำหรับ batch:

JavaScript

เมื่อ operation ทำไม่จบภายใน request เดียว (export ก้อนใหญ่ transcode วิดีโอ) อย่าค้าง connection ไว้ ให้รับงานเข้าคิวแล้วคืน 202 Accepted พร้อม link ไปยัง status resource ที่ client poll ได้:

sequenceDiagram
  participant C as Client
  participant S as API
  C->>S: POST /exports
  S-->>C: 202 Accepted + Location: /exports/job-1
  C->>S: GET /exports/job-1
  S-->>C: 200 OK { status: "running" }
  C->>S: GET /exports/job-1
  S-->>C: 200 OK { status: "done", result: "/files/x" }
202 Accepted พร้อม status resource ที่ poll ได้

ตัวงานเองกลายเป็น resource: POST /exports สร้างงานขึ้นมา GET /exports/\{id\} รายงานความคืบหน้า และ response สุดท้ายจะ link ไปยังผลลัพธ์ที่ได้

Patternดีข้อควรระวัง
Bulk operationลด round trip — 1 request แทน Nresponse ที่ partial success ซับซ้อน
Async jobไม่ block client สำหรับงานนานclient ต้องมี polling หรือ webhook logic
202 Acceptedบอก client ว่า processingต้อง track job status ด้วย

Bulk API ที่ Fail-all หรือ Succeed-all อาการ:

  • ส่ง 100 record ใน batch — record 1 error ทำให้ทั้ง batch fail
  • client ไม่รู้ว่า record ไหนสำเร็จ record ไหนไม่สำเร็จ
  • return partial result: { "succeeded": [...], "failed": [...] }

Async Job ที่ไม่มี Status Endpoint อาการ:

  • POST /reports — return 202 แต่ไม่มี endpoint ดู status
  • client ไม่รู้ว่า job เสร็จหรือยัง, fail หรือไม่
  • return { "jobId": "...", "statusUrl": "/jobs/\{id\}" } เสมอ

💡 ตัวอย่างจากของจริง

GitHub API:

  • bulk operation ใน GraphQL API — รวม mutation หลายอย่างในครั้งเดียว
  • async workflow ผ่าน Actions API — POST /repos/\{owner\}/\{repo\}/actions/workflows/\{id\}/dispatches return 204, ตาม status ผ่าน run endpoint

Stripe API:

  • bulk event ผ่าน webhook — Stripe ส่ง event batch มาที่ endpoint ของ consumer
  • async payout — 202 Accepted, status ตาม GET /payouts/{id}
bulk endpoint ควรคืนค่าอะไรกลับมาสำหรับ batch ที่ผลลัพธ์ปนกัน?
status ใดเหมาะกับการรับงานที่ใช้เวลานานเพื่อประมวลผลภายหลัง?
client ติดตามงาน async อย่างไรหลังจากได้รับ 202?