mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 13:35:42 +09:00
272 lines
12 KiB
Plaintext
272 lines
12 KiB
Plaintext
---
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
title: Jobs
|
|
description: Background job status, progress, task types, and cancellation.
|
|
---
|
|
|
|
import RouteHeader from '@/components/RouteHeader.astro';
|
|
|
|
These routes list recorded background jobs and request cancellation. Create jobs through [Queue bulk job](/admin-api/bulk-jobs/#queue-bulk-job), [Create system DM broadcast](/admin-api/system-dms/#create-system-dm-broadcast), [Refresh search index](/admin-api/search-indexes/#refresh-search-index), or an [archive](/admin-api/archives/) request.
|
|
|
|
Reads require `jobs:view` and cancellation requires `jobs:cancel`. Every operation on this page shares the `admin:jobs:view` bucket. The three reads record no [Admin audit entry](/admin-api/#admin-audit-entry-object), and cancellation records one.
|
|
|
|
:::note[Job updates vary by task]
|
|
Mention processing, link previews, announcement delivery and copy updates, message delete audit log batching, payment reconciliation when a user connects, and every scheduled task except `syncUrlBlocklists` and `syncFileShaBlocklists` run with no job record and never appear here. Fluxer deletes a job record about 90 days after the job was queued. A job also runs with no record when Fluxer fails to write that record. When a later write of status, progress or attempts fails, Fluxer logs the failure and the job continues, so the stored values can be behind the real run. Use the [archive routes](/admin-api/archives/) to track archive progress and failures.
|
|
:::
|
|
|
|
## Admin job object
|
|
|
|
One object describes one recorded job. These routes can only change `cancel_requested`.
|
|
|
|
### Structure
|
|
|
|
| Field | Type | Description |
|
|
| --- | --- | --- |
|
|
| job_id | snowflake | The ID of the job |
|
|
| task_type | string | The [background job task type](#background-job-task-types) the job runs |
|
|
| status | string | The latest recorded [job status](#job-statuses) |
|
|
| progress_current | ?integer | The units of work reported as complete, or null |
|
|
| progress_total | ?integer | The reported total units of work, or null |
|
|
| progress_message | ?string | The latest reported progress message, or null |
|
|
| error_message | ?string | The recorded failure reason, or null |
|
|
| created_at | ISO8601 timestamp | The time the job was recorded |
|
|
| started_at | ?ISO8601 timestamp | The latest recorded start time, or null when no start was recorded |
|
|
| completed_at | ?ISO8601 timestamp | The recorded completion, cancellation or failure time, or null |
|
|
| requested_by_user_id | ?snowflake | The recorded requester, or null |
|
|
| audit_log_reason | ?string | The recorded audit log reason, or null |
|
|
| jet_stream_lane | ?string | The assigned [processing lane](#processing-lanes), or null |
|
|
| jet_stream_seq | ?string | The recorded queue sequence as a decimal string, or null |
|
|
| attempts | integer | The recorded retry count, not a total of all executions |
|
|
| max_attempts | integer | Attempt limit recorded at queue time. Retries stop at the lane's delivery limit, which can differ from this value |
|
|
| run_at | ?ISO8601 timestamp | The earliest permitted run time, or null for an immediate job |
|
|
| cancel_requested | boolean | Whether cancellation has been requested |
|
|
| context_link | ?string | An Admin console path related to the job, or null |
|
|
| payload | ?string | The JSON-encoded job input, or null |
|
|
| result | ?string | The JSON-encoded result, or null |
|
|
|
|
Progress fields stay null until the task reports progress. A task can report progress with no total or no message, which sets `progress_total` or `progress_message` to null. The payload can contain identifiers and message content, including in list responses.
|
|
|
|
### Example
|
|
|
|
```json
|
|
{
|
|
"job_id": "1501314428688998182",
|
|
"task_type": "bulkUpdateUserFlags",
|
|
"status": "running",
|
|
"progress_current": 25,
|
|
"progress_total": 400,
|
|
"progress_message": "Updating flags",
|
|
"error_message": null,
|
|
"created_at": "2026-08-31T09:00:00.000Z",
|
|
"started_at": "2026-08-31T09:00:01.000Z",
|
|
"completed_at": null,
|
|
"requested_by_user_id": "1478812292088791040",
|
|
"audit_log_reason": null,
|
|
"jet_stream_lane": "lifecycle",
|
|
"jet_stream_seq": "4812",
|
|
"attempts": 0,
|
|
"max_attempts": 5,
|
|
"run_at": null,
|
|
"cancel_requested": false,
|
|
"context_link": null,
|
|
"payload": "{\"user_ids\":[\"1478812292088791040\"]}",
|
|
"result": null
|
|
}
|
|
```
|
|
|
|
## Job cursor object
|
|
|
|
Pass all three fields from `next_cursor` back to [List jobs](#list-jobs) using the corresponding cursor query parameters.
|
|
|
|
### Structure
|
|
|
|
| Field | Type | Description |
|
|
| --- | --- | --- |
|
|
| bucket_day | string | The cursor's UTC date as `YYYY-MM-DD` |
|
|
| created_at | ISO8601 timestamp | The cursor's creation time |
|
|
| job_id | snowflake | The cursor's job identifier |
|
|
|
|
### Example
|
|
|
|
```json
|
|
{
|
|
"bucket_day": "2026-08-30",
|
|
"created_at": "2026-08-30T22:41:07.512Z",
|
|
"job_id": "1500901337221828608"
|
|
}
|
|
```
|
|
|
|
## Job statuses
|
|
|
|
| Value | Description |
|
|
| --- | --- |
|
|
| queued | The job was recorded and no later status has been recorded |
|
|
| running | The job was recorded as started |
|
|
| succeeded | The job was recorded as completed successfully |
|
|
| cancelled | The task read the cancellation request and stopped |
|
|
| deadletter | The job was recorded as failed, including a failure to queue it |
|
|
|
|
`queued` and `running` accept cancellation requests. The other statuses are terminal. A cancellation request does not guarantee that the task will stop.
|
|
|
|
The queue drops a job 7 days after it was queued. A job still recorded as `queued` or `running` after 8 days is set to `deadletter` with the error `Expired from the job queue`.
|
|
|
|
## Processing lanes
|
|
|
|
`jet_stream_lane` identifies the job's processing group.
|
|
|
|
| Value | Description |
|
|
| --- | --- |
|
|
| realtime | Mention processing |
|
|
| unfurl | Link previews |
|
|
| lifecycle | Account, guild, moderation, archive and bulk work |
|
|
| batch | Scheduled maintenance and index work |
|
|
| crosspost | [Announcement channel](/topics/announcement-channels/) delivery, copy updates, and follower cleanup |
|
|
|
|
## Background job task types
|
|
|
|
Use the returned `task_type` value to filter [List jobs](#list-jobs).
|
|
|
|
The tasks queued by [Bulk jobs](/admin-api/bulk-jobs/) are `bulkUpdateUserFlags`, `bulkUpdateGuildFeatures`, `bulkAddGuildMembers`, and `bulkScheduleUserDeletion`. `harvestUserData` and `harvestGuildData` build [archives](/admin-api/archives/), `sendSystemDm` delivers a [system DM broadcast](/admin-api/system-dms/), and `refreshSearchIndex` rebuilds a [search index](/admin-api/search-indexes/). `removeChannelFollowers` runs on the `crosspost` lane after an announcement channel is deleted or converted into a text channel, and removes the channel follower webhooks that follow it.
|
|
|
|
## List jobs
|
|
|
|
<RouteHeader method="GET" path="/v1/admin/jobs" />
|
|
|
|
Returns a page of [Admin job](#admin-job-object) objects, newest first, within the requested lookback window. Requires `jobs:view`.
|
|
|
|
### Query parameters
|
|
|
|
| Field | Type | Description |
|
|
| --- | --- | --- |
|
|
| limit? | integer | The maximum number of jobs to return (1-200, default 50) |
|
|
| cursor_bucket_day? | string | `next_cursor.bucket_day` as a `YYYY-MM-DD` UTC date |
|
|
| cursor_created_at? | string | `next_cursor.created_at` as an ISO 8601 timestamp (1-64 characters) |
|
|
| cursor_job_id? | snowflake | The job identifier from `next_cursor.job_id` |
|
|
| max_lookback_days? | integer | The number of days before today to include (1-60, default 14) |
|
|
| status? | string | Filter by recorded [job status](#job-statuses) |
|
|
| task_type? | string | Filter by [task type](#background-job-task-types) (1-128 characters) |
|
|
| requested_by_user_id? | snowflake | Filter by recorded requester |
|
|
|
|
Supply all three cursor parameters together or omit all three. An incomplete or malformed cursor returns 400 `INVALID_FORM_BODY`. An unknown task type returns an empty page. A full page always returns `next_cursor`, so the next request can return an empty page.
|
|
|
|
### Response body
|
|
|
|
| Field | Type | Description |
|
|
| --- | --- | --- |
|
|
| jobs | array[[Admin job](#admin-job-object) object] | The jobs in this page |
|
|
| next_cursor | ?[job cursor](#job-cursor-object) object | The cursor for the next request, or null |
|
|
|
|
### Response
|
|
|
|
| Status | Body | Condition |
|
|
| --- | --- | --- |
|
|
| 200 | response body | The job page was returned |
|
|
| 400 | [error response](/admin-api/#error-response) | `INVALID_FORM_BODY` because a query parameter is invalid |
|
|
|
|
### Side effects
|
|
|
|
The operation records no [Admin audit entry](/admin-api/#admin-audit-entry-object).
|
|
|
|
### Rate limit
|
|
|
|
600 requests per minute for each authenticated user, on the `admin:jobs:view` bucket.
|
|
|
|
## List active jobs
|
|
|
|
<RouteHeader method="GET" path="/v1/admin/jobs/active" />
|
|
|
|
Returns recorded active jobs as [Admin job](#admin-job-object) objects. Requires `jobs:view`.
|
|
|
|
This operation has no filters or pagination. The stored status and progress can be behind the work the task has already done.
|
|
|
|
### Response body
|
|
|
|
| Field | Type | Description |
|
|
| --- | --- | --- |
|
|
| jobs | array[[Admin job](#admin-job-object) object] | The recorded active jobs |
|
|
|
|
### Response
|
|
|
|
| Status | Body | Condition |
|
|
| --- | --- | --- |
|
|
| 200 | response body | The active jobs were returned |
|
|
|
|
### Side effects
|
|
|
|
The operation records no [Admin audit entry](/admin-api/#admin-audit-entry-object).
|
|
|
|
### Rate limit
|
|
|
|
600 requests per minute for each authenticated user, on the `admin:jobs:view` bucket.
|
|
|
|
## Get job
|
|
|
|
<RouteHeader method="GET" path="/v1/admin/jobs/{job_id}" />
|
|
|
|
Returns one [Admin job](#admin-job-object) object. Requires `jobs:view`.
|
|
|
|
### Path parameters
|
|
|
|
| Field | Type | Description |
|
|
| --- | --- | --- |
|
|
| job_id | snowflake | The ID of the job |
|
|
|
|
### Response body
|
|
|
|
| Field | Type | Description |
|
|
| --- | --- | --- |
|
|
| job | [Admin job](#admin-job-object) object | The job |
|
|
|
|
### Response
|
|
|
|
| Status | Body | Condition |
|
|
| --- | --- | --- |
|
|
| 200 | response body | The job was returned |
|
|
| 404 | `{"error": "job_not_found"}` | No job record has this identifier |
|
|
|
|
A 404 response uses this single-field body rather than the standard error response. A missing or expired record does not mean the work never ran.
|
|
|
|
### Side effects
|
|
|
|
The operation records no [Admin audit entry](/admin-api/#admin-audit-entry-object).
|
|
|
|
### Rate limit
|
|
|
|
600 requests per minute for each authenticated user, on the `admin:jobs:view` bucket.
|
|
|
|
## Cancel job
|
|
|
|
<RouteHeader method="PUT" path="/v1/admin/jobs/{job_id}/cancellation" auditReason />
|
|
|
|
Requests cooperative cancellation of a job and reports whether the request was recorded. Requires `jobs:cancel`.
|
|
|
|
### Path parameters
|
|
|
|
| Field | Type | Description |
|
|
| --- | --- | --- |
|
|
| job_id | snowflake | The ID of the job |
|
|
|
|
### Response body
|
|
|
|
| Field | Type | Description |
|
|
| --- | --- | --- |
|
|
| cancelled | boolean | Whether a cancellation request was recorded |
|
|
|
|
Returns false for a missing or terminal job. Repeating a request for a queued or running job returns true.
|
|
|
|
### Response
|
|
|
|
| Status | Body | Condition |
|
|
| --- | --- | --- |
|
|
| 200 | response body | The request was evaluated, whether or not the flag changed |
|
|
|
|
### Side effects
|
|
|
|
Sets `cancel_requested` to true for a queued or running job. `sendSystemDm`, `bulkBanFileShas`, `bulkDeleteMessagesForUsers`, and the tasks queued by [Bulk jobs](/admin-api/bulk-jobs/) check for the request while they run and stop at the next check. Other tasks run to the end. Completed work is not undone. A status of `cancelled` means the task stopped because of the request.
|
|
|
|
The operation records one [Admin audit entry](/admin-api/#admin-audit-entry-object) with action `cancel_job`, target type `bulk_job`, target ID equal to `job_id`, and metadata key `cancelled`. The entry uses target type `bulk_job` for every task type, and Fluxer records it when `cancelled` is false too.
|
|
|
|
### Rate limit
|
|
|
|
600 requests per minute for each authenticated user, on the `admin:jobs:view` bucket.
|