Chuyển từ request đồng bộ sang async job: nhận yêu cầu, trả ngay, xử lý nền, client theo dõi kết quả.
POST /reports
{ "type": "revenue", "from": "2026-01-01", "to": "2026-06-30" }
HTTP/1.1 202 Accepted
Location: /jobs/7c2
{ "job_id": "7c2", "status": "queued" }Sau đó client theo dõi bằng một trong hai cách:
Polling — GET /jobs/7c2 trả { "status": "running" | "succeeded" | "failed", "progress": 0.4 }. Khi xong thì trả kèm link tới kết quả (result_url là presigned URL của file trên object storage). Server nên trả Retry-After để client biết khoảng cách poll hợp lý, client dùng backoff thay vì poll mỗi 100ms.
Webhook / callback — client đăng ký URL, job xong thì server POST sang. Đỡ tốn request nhưng client phải có endpoint công khai và phải xử lý được retry, trùng lặp, xác thực chữ ký.
Thực tế nên hỗ trợ cả hai: webhook làm đường chính, polling làm đường dự phòng khi webhook rớt.
Các chi tiết đừng bỏ sót:
- POST /reports cần idempotency key, nếu không user bấm 2 lần là 2 job nặng.
- Job phải có TTL và trạng thái failed kèm lý do đọc được, không để client poll vô hạn một job đã chết.
- Nếu cùng tham số đã có job đang chạy, trả lại job đó thay vì tạo mới.
- Kết quả lớn thì trả link tải, đừng nhét file vào JSON response.