Bulk & Async Operations
API ของจริงบางครั้งต้องแก้ resource ทีละมาก ๆ ในคราวเดียว หรือเริ่มงานที่กินเวลานานเกินกว่า request หนึ่งตัวจะรอไหว ทั้งสองกรณียืดโมเดลหนึ่ง request ต่อหนึ่ง resource ออกไป จึงต้องออกแบบอย่างตั้งใจ
การทำงานแบบ Bulk
หัวข้อที่มีชื่อว่า “การทำงานแบบ Bulk”ในการกระทำต่อ item หลายตัวในการเรียกครั้งเดียว ให้ POST ไปยัง batch endpoint พร้อม list และคืน ผลลัพธ์รายตัว (per-item result) เพื่อให้ผู้เรียกรู้ได้อย่างแม่นยำว่าอะไรสำเร็จบ้าง:
POST /articles/batch HTTP/1.1Content-Type: application/json
{ "items": [ { "title": "A" }, { "title": "" } ] }response รายงานผลลัพธ์ของ item แต่ละตัวแทนที่จะเป็น status รวมเพียงค่าเดียว — ความสำเร็จบางส่วน (partial success) คือเรื่องปกติสำหรับ batch:
งานที่ใช้เวลานาน (async)
หัวข้อที่มีชื่อว่า “งานที่ใช้เวลานาน (async)”เมื่อ 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" } ตัวงานเองกลายเป็น resource: POST /exports สร้างงานขึ้นมา GET /exports/\{id\} รายงานความคืบหน้า และ response สุดท้ายจะ link ไปยังผลลัพธ์ที่ได้
| Pattern | ดี | ข้อควรระวัง |
|---|---|---|
| Bulk operation | ลด round trip — 1 request แทน N | response ที่ 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\}/dispatchesreturn 204, ตาม status ผ่าน run endpointStripe API:
- bulk event ผ่าน webhook — Stripe ส่ง event batch มาที่ endpoint ของ consumer
- async payout — 202 Accepted, status ตาม GET /payouts/{id}