/api/v1/job
Background work. Defined in crates/rest/src/job.rs.
A job is a complete unit of work; a task is a sub-unit, and many tasks compose into one job. Every job has a root task, and every task belongs to a job.
Administrators only. The four routes all check is_administrator on the
auth context before anything else. A guest, an OAuth token or an ordinary
member is refused.
Mind the status codes: only POST /jobs reports a refusal as 403. The
three reads collapse every service failure — including the permission one —
into 500{"error": "internal error"}. That is a rough edge of the REST
layer, not a statement about the permission, which is checked exactly the same
way on all four.
GET /jobs
Lists jobs, most recent first.
No query parameter is read: the handler always asks for offset = 0,
limit = 100, no status filter and no creator filter.
Example
GET /api/v1/job/jobs Cookie: sid=b8be19ef-2d61-44de-b7d2-9c34ccb8a763
{
"offset": 0,
"limit": 100,
"count": 1,
"items": [
{
"id": "1b5f36a1-8e6c-4b59-bd62-2f6a0b8f4e11",
"created_at": "2021-01-15T14:17:14.015Z",
"created_by": {
"type": "User",
"id": "9f310484-963b-446b-af69-797feec6813f",
"display_name": {"current": {"value": "Demurgos"}}
},
"task": {
"id": "c0a0d0b8-6e0e-4a4e-9b8a-51d1e9b9f0c2",
"revision": 3,
"polled_at": "2021-01-15T14:17:20.000Z",
"status": "Complete",
"starvation": 0,
"kind": "SendEmail",
"kind_version": 1
}
}
]
}
| Field | Type | Meaning |
|---|---|---|
created_by | short user or null | Who started the job. null for one the server started itself. |
task | object | The root task, without its state. |
task.revision | integer | Incremented on every update of the task. |
task.polled_at | timestamp or null | Last time a worker picked it up. |
task.status | string | "Available", "Blocked" or "Complete". |
task.starvation | integer | How long the task has been waiting for a worker. |
task.kind | string | Task kind, ^[A-Z][A-Za-z0-9]{0,31}$. |
task.kind_version | integer | Version of the state layout for that kind. |
Errors
| Status | Body | When |
|---|---|---|
| 500 | {"error": "internal error"} | The caller is not an administrator, or the store failed. |
POST /jobs
Starts a job.
Body
| Field | Type | Meaning |
|---|---|---|
kind | string | Task kind of the root task. |
state | any JSON | Initial state handed to that task. |
kind_version is not part of the body; the handler always sends 1.
POST /api/v1/job/jobs
Content-Type: application/json
Cookie: sid=b8be19ef-2d61-44de-b7d2-9c34ccb8a763
{"kind": "SendEmail", "state": {}}
No task kind is registered yet. After the administrator check, the service rejects every kind as unknown, and the REST layer reports that as 500. The route is in place for the job runtime, but there is nothing it can start today.
Errors
| Status | Body | When |
|---|---|---|
| 403 | {"error": "current actor does not have the permission to create a job"} | Not an administrator. |
| 500 | {"error": "internal error"} | Unknown task kind, which is currently every kind. |
GET /jobs/:job_id
Returns one job, in the same shape as a row of the listing above. :job_id is
a UUID.
GET /api/v1/job/jobs/1b5f36a1-8e6c-4b59-bd62-2f6a0b8f4e11 Cookie: sid=b8be19ef-2d61-44de-b7d2-9c34ccb8a763
Errors
| Status | Body | When |
|---|---|---|
| 500 | {"error": "internal error"} | Not an administrator, no such job, or the store failed. |
GET /tasks/:task_id
Returns one task with its state, which is what the listing omits.
GET /api/v1/job/tasks/c0a0d0b8-6e0e-4a4e-9b8a-51d1e9b9f0c2 Cookie: sid=b8be19ef-2d61-44de-b7d2-9c34ccb8a763
{
"id": "c0a0d0b8-6e0e-4a4e-9b8a-51d1e9b9f0c2",
"revision": 3,
"polled_at": "2021-01-15T14:17:20.000Z",
"status": "Complete",
"starvation": 0,
"kind": "SendEmail",
"kind_version": 1,
"state": {},
"output": null
}
state and output are opaque JSON: their shape belongs to the task kind,
not to this API. output is null until the task completes.
Errors
| Status | Body | When |
|---|---|---|
| 500 | {"error": "internal error"} | Not an administrator, no such task, or the store failed. |