[ADP-357] 長時間運行的任務
概述
本文件概述了在 RESTful API 中處理長時間運行任務的指導方針和最佳實踐。長時間運行的任務是指可能需要大量時間才能完成,無法在典型的請求-回應週期內處理的操作。
指導方針
- 必須(MUST)為成功創建的任務返回 HTTP 狀態碼 202 Accepted。
- 必須(MUST)在回應標頭中返回 Location,以向客戶端提供有關已創建任務的資訊。
- 作業創建後,有兩個作法可提供額外的結果。
- 可(MAY)在作業完成時返回
Location
,生成一個與作業不同的URI的新資源。
httpHTTP/1.1 200 OK Location: https://my.dev/v1/jobs/job-id/results Content-Location: https://my.dev/v1/jobs/job-id { "jobId": "123e4567-e89b-12d3-a456-426614174000", "status": "COMPLETED", "createdAt": "2023-04-01T12:00:00Z", "updatedAt": "2023-04-01T12:10:00Z" }
- 可(MAY)在作業資源中包含一個
response
欄位。
TIP
這個方法受到opensearch和elasticsearch的啟發,它們都直接在搜索作業中嵌入了回應。 設計理念是啟用搜索作業的輪詢,並為API用戶提供部分搜索結果的更新。根據你的用例決定。如果你的目標是提供類似於elasticsearch/opensearch的API,你可以(MAY)採用這個設計。然而,它們的設計並不完全符合目前的ADP。記住最佳實踐原則:如果你(作為API設計師)認為這是行業標準,則採用它。如果你對設計不滿意,試著發想一個更好的設計,並貢獻回ADP。
- 可(MAY)在作業完成時返回
- 必須(MUST)在任務資源中包含狀態屬性(property)。
- 應該(SHOULD)為每個任務使用唯一標識符(例如 UUID)。
- 可以(MAY)附加 Sunset 標頭,以指示任務完成後資源將被移除的時間。
- 如果任務失敗,應(SHOULD)提供問題詳細資訊對象(與 RFC 9457 兼容)或錯誤 JSON。
- 可(MAY)考慮允許客戶端在需要時取消正在運行的任務
- DRAFT 可以(MAY)設計使用
DELETE
動詞對應取消任務。
httpDELETE /jobs/{job-id}
- DRAFT 可以(MAY)設計使用
- 可(MAY)考慮實現通知系統(例如 webhooks)以在任務完成時通知客戶端
- 應(SHOULD)實施適當的安全措施,確保客戶端只能訪問自己的任務資源
- DRAFT 可(MAY)附加
Retry-After
用以指出應該在多久後重新查詢作業狀態。
實現細節
任務創建
當客戶端啟動長時間運行的任務時,服務器應:
- 接受請求並創建任務資源
- 返回 202 Accepted 狀態碼
- 在 Location 標頭中包含已創建任務資源的 URI
回應示例:
http
HTTP/1.1 202 Accepted
Location: https://api.my.dev/v1/jobs/123e4567-e89b-12d3-a456-426614174000
任務資源
任務資源應至少包含以下資訊:
- 唯一標識符
- 任務的當前狀態
- 創建和最後更新的時間戳
任務資源示例:
json
{
"jobId": "123e4567-e89b-12d3-a456-426614174000",
"status": "RUNNING",
"createdAt": "2023-04-01T12:00:00Z",
"updatedAt": "2023-04-01T12:05:00Z"
}
任務狀態
任務狀態應為以下之一:
- PENDING: 任務已排隊但尚未開始
- RUNNING: 任務當前正在處理中
- COMPLETED: 任務已成功完成
- FAILED: 任務遇到錯誤無法完成
錯誤處理
如果任務失敗,請使用問題詳細資訊對象提供詳細的錯誤資訊:
http
GET /jobs/123e4567-e89b-12d3-a456-426614174000 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{
"jobId": "123e4567-e89b-12d3-a456-426614174000",
"status": "FAILED",
"createdAt": "2023-04-01T12:00:00Z",
"updatedAt": "2023-04-01T12:10:00Z",
"problem": {
"type": "https://example.com/problems/job-execution-error",
"title": "任務執行錯誤",
"status": 500,
"detail": "任務執行期間發生意外錯誤"
}
}
OpenAPI 3.1.0 示例
以下是使用 OpenAPI 3.1.0 記錄長時間運行任務 API 的示例:
yaml
openapi: 3.1.0
info:
title: 長時間運行任務 API
version: 1.0.0
paths:
/jobs:
post:
summary: 創建新任務
operationId: createJob
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/JobRequest'
responses:
'202':
description: 已接受
headers:
Location:
schema:
type: string
description: 已創建任務資源的 URI
/jobs/{jobId}:
get:
summary: 獲取任務狀態
operationId: getJobStatus
parameters:
- name: jobId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: 成功回應
content:
application/json:
schema:
$ref: '#/components/schemas/Job'
components:
schemas:
JobRequest:
type: object
properties:
# 定義任務請求屬性
Job:
type: object
properties:
jobId:
type: string
format: uuid
status:
type: string
enum: [PENDING, RUNNING, COMPLETED, FAILED]
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
problem:
$ref: '#/components/schemas/Problem'
Problem:
type: object
properties:
type:
type: string
format: uri
title:
type: string
status:
type: integer
detail:
type: string
參考資料
Changelog
2024.10.30
Add more reference; add result design for long running task