Skip to content

Commit 88e2315

Browse files
committed
feat: add task documentation
1 parent b77660b commit 88e2315

File tree

3 files changed

+304
-7
lines changed

3 files changed

+304
-7
lines changed

src/app/web/tasks/page.mdx

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
export const metadata = {
2+
title: 'Tasks',
3+
description:
4+
"On this page, we'll dive into tasks, and how to connect to them and listen for updates through the Web API.",
5+
}
6+
7+
# Tasks
8+
9+
Tasks are long-running operations that some users may want to come back to, or leave running in the background. {{ className: 'lead' }}
10+
11+
## Authentication
12+
13+
Connecting to the task endpoint doesn't require any special permissions. However, each task has a list of ACLs that you must have at least one of to connect to the task.
14+
15+
For example, even though you can connect, if you don't have the `system:maintenance:read` ACL, you won't be able to access any of the session/object cleanup tasks.
16+
17+
---
18+
19+
## Connect {{ tag: 'WS', label: '/api/v1/task' }}
20+
21+
Connecting and listening to task is a multi-stage process. You can listen to more than one task on the same websocket connection.
22+
23+
### Setting up
24+
25+
This is a GET endpoint that upgrades to a Websocket connection upon connection.
26+
27+
When you connect, you'll get a single message:
28+
29+
- `unauthenticated`: There was an error fetching the internal states of your websocket connection, and you won't be able to connect to any tasks.
30+
- `connect`: You've connect successfully to the endpoint, and you can continue.
31+
32+
### Connecting to a task
33+
34+
Once connected, you can send a message in the following format:
35+
36+
```
37+
connect/{task id}
38+
```
39+
40+
Where "task id" is the ID of the task you want to connect to. These task IDs are returned by several other endpoints, like import endpoints and task CRUD endpoints.
41+
42+
After you send that message, you'll be connected to the task.
43+
44+
At any point, Drop will send one of the following messages:
45+
46+
### Error event: `error/{task id}/{error title}/{error body}`
47+
48+
This means something has gone wrong with the task, and you should show or handle the error.
49+
50+
If "error title" is "Unknown task", your task ID was invalid, or you do not have the necessary ACLs to access the task.
51+
52+
This is different from an error generated from a task. This error is from Drop itself, not the task.
53+
54+
### Disconnect event: `disconnect/{task id}`
55+
56+
The task has ended, and you'll no longer recieve updates
57+
58+
### Task message: `{ ... JSON object ... }`
59+
60+
If the message isn't one of the two above ones, it'll be a stringified JSON object that represents a task message:
61+
62+
```json
63+
{
64+
"id": "...",
65+
"name": "My Task",
66+
"success": false,
67+
"progress": 34,
68+
"error": null,
69+
"log": [
70+
"... JSON object ...",
71+
"... JSON object ...",
72+
"... more JSON objects ...",
73+
"... yet another JSON object ..."
74+
],
75+
"reset": false
76+
};
77+
```
78+
79+
### Task message properties
80+
81+
Here's what they do:
82+
83+
<Properties>
84+
<Property name="id" type="string">
85+
Task ID of this message
86+
</Property>
87+
<Property name="name" type="string">
88+
User-friendly name of this task.
89+
</Property>
90+
<Property name="success" type="string">
91+
If `true`, this task has completed without error.
92+
</Property>
93+
<Property name="error" type="object">
94+
If not `null` or `undefined`, it will be an object:
95+
```json
96+
{
97+
"title": "My Error",
98+
"description": "Something has gone terribly wrong."
99+
}
100+
```
101+
102+
This means the task has errored out with the above error.
103+
104+
</Property>
105+
<Property name="progress" type="number">
106+
A number between 0-100 that represents the progress. Not guaranteed to be between 0-100, but we spit out warnings if it is.
107+
</Property>
108+
<Property name="log" type="string[]">
109+
An array of log messages. If `reset` is not set (see below), it is a **partial** log message, which means you should append these messages to a local cache of them for display.
110+
111+
Each log message is a JSON stringified object:
112+
```json
113+
{
114+
"message": "my log line",
115+
"level": "info",
116+
"timestamp": "2025-09-23T06:37:19.047Z"
117+
}
118+
```
119+
120+
The values are fairly self-explanatory. Do note that, on older versions of Drop, `level` is a number rather than a string, so you may need to map it to the string value:
121+
122+
| Number | String |
123+
| ------ | ------ |
124+
| 100 | silent |
125+
| 60 | fatal |
126+
| 50 | error |
127+
| 40 | warn |
128+
| 30 | info |
129+
| 20 | debug |
130+
| 10 | trace |
131+
| 0 | off |
132+
133+
This also serves as a list of all possible `level` values*.*
134+
135+
</Property>
136+
<Property name="reset" type="boolean">
137+
This message is a reset message, meaning it contains a full log history, rather than a partial one. You should overwrite your local log history, rather than appending to it.
138+
</Property>
139+
</Properties>
140+
141+
---
142+
143+
## Fetch all tasks {{ tag: 'GET', label: '/api/v1/admin/task', apilevel: "system", acl: "task:read" }}
144+
145+
<Row>
146+
<Col>
147+
148+
Fetches all tasks running, recently run, and scheduled for this instance.
149+
150+
<Note>
151+
The scheduled tasks refer to *task groups*, not individual tasks. These are string IDs for a type of task, like `cleanup:invitations`, rather than a *specific* task, like `cleanup:invitations:{timestamp}`.
152+
</Note>
153+
154+
</Col>
155+
<Col sticky>
156+
157+
<CodeGroup title="Request" tag="GET" label="/api/v1/admin/task">
158+
159+
```bash {{ title: 'cURL' }}
160+
curl -G http://localhost:3000/api/v1/admin/task \
161+
-H "Authorization: Bearer {token}"
162+
```
163+
164+
```js
165+
const response = await fetch("http://localhost:3000/api/v1/admin/task", {
166+
headers: {
167+
Authorization: "Bearer {token}"
168+
},
169+
});
170+
171+
const { runningTasks, historicalTasks, dailyTasks, weeklyTasks } = await response.blob();
172+
173+
```
174+
175+
</CodeGroup>
176+
177+
```json {{ title: 'Response' }}
178+
{
179+
"runningTasks": [],
180+
"historicalTasks": [
181+
{
182+
"id": "cleanup:invitations:2025-08-23T08:27:15.156Z",
183+
"taskGroup": "cleanup:invitations",
184+
"name": "Cleanup Invitations",
185+
"started": "2025-08-23T08:27:15.156Z",
186+
"ended": "2025-08-23T08:27:15.258Z",
187+
"success": true,
188+
"error": null,
189+
"progress": 100,
190+
"log": [
191+
"{\"level\":\"info\",\"time\":\"2025-08-23T08:27:15.257Z\",\"msg\":\"Cleaning invitations\"}",
192+
"{\"level\":\"info\",\"time\":\"2025-08-23T08:27:15.258Z\",\"msg\":\"Done\"}"
193+
],
194+
"acls": [
195+
"system:maintenance:read"
196+
]
197+
},
198+
{
199+
"id": "cleanup:sessions:2025-08-23T01:02:47.015Z",
200+
"taskGroup": "cleanup:sessions",
201+
"name": "Cleanup Sessions",
202+
"started": "2025-08-23T01:02:47.016Z",
203+
"ended": "2025-08-23T01:02:47.132Z",
204+
"success": true,
205+
"error": null,
206+
"progress": 100,
207+
"log": [
208+
"{\"level\":\"info\",\"time\":\"2025-08-23T01:02:47.116Z\",\"msg\":\"Cleaning up sessions\"}",
209+
"{\"level\":\"info\",\"time\":\"2025-08-23T01:02:47.132Z\",\"msg\":\"Done\"}"
210+
],
211+
"acls": [
212+
"system:maintenance:read"
213+
]
214+
},
215+
],
216+
"dailyTasks": [
217+
"cleanup:invitations",
218+
"cleanup:sessions",
219+
"check:update"
220+
],
221+
"weeklyTasks": [
222+
"cleanup:objects"
223+
]
224+
}
225+
```
226+
227+
</Col>
228+
</Row>
229+
230+
---
231+
232+
## Execute scheduled task {{ tag: 'POST', label: '/api/v1/admin/task', apilevel: "system", acl: "task:start" }}
233+
234+
<Row>
235+
<Col>
236+
237+
This endpoint invokes a scheduled task by the task group name (see above, `dailyTasks` & `weeklyTasks`), and returns the task ID.
238+
239+
Despite not needing the task's ACL to start it, you will need the task's ACL to read it.
240+
241+
### Request body
242+
<Properties>
243+
<Property name="taskGroup" type="string">
244+
Name of the task group to start.
245+
</Property>
246+
</Properties>
247+
248+
</Col>
249+
<Col sticky>
250+
251+
<CodeGroup title="Request" tag="POST" label="/api/v1/admin/task">
252+
253+
```bash {{ title: 'cURL' }}
254+
curl -X POST http://localhost:3000/api/v1/admin/task \
255+
-H "Authorization: Bearer {token}" \
256+
-H "Content-Type: application/json" \
257+
-d "{ ... }"
258+
```
259+
260+
```js
261+
const response = await fetch("http://localhost:3000/api/v1/admin/task", {
262+
headers: {
263+
Authorization: "Bearer {token}"
264+
},
265+
method: "POST",
266+
body: {
267+
taskGroup: "..."
268+
}
269+
});
270+
271+
272+
```
273+
274+
</CodeGroup>
275+
276+
```json {{ title: 'Response' }}
277+
{
278+
"id": "..."
279+
}
280+
```
281+
282+
</Col>
283+
</Row>
284+
285+
---
286+
287+
## Scheduled tasks
288+
289+
This is an exhaustive list of all scheduled tasks, their descriptions, and their tasks groups on Drop instances. It may be out-of-date for new versions. Please file a [report](https://github.com/Drop-OSS/drop-api-docs/issues) if you believe it is out-of-date.
290+
291+
| Task Group | Task Name | Description |
292+
| --------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
293+
| `debug` | Debug Task | May not be implemented; usually removed for release and only added when needing to debug tasks. |
294+
| `cleanup:invitations` | Cleanup Invitations | Deletes expired invitations from database to save space. Invitations check themselves regardless, this just cleans out old invitations. |
295+
| `cleanup:objects` | Cleanup Objects | Deletes unreferenced objects from the object backend to save space. |
296+
| `cleanup:sessions` | Cleanup Sessions | Cleans up expired sessions from the session handler. |
297+
| `check:update` | Check for Update | Checks if there is an update for Drop available, and if so, send a notification to admins. |

src/components/Navigation.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ function NavLink({
6767
? 'text-yellow-600/90 dark:text-yellow-400/70'
6868
: 'text-zinc-400 dark:text-zinc-500'
6969

70-
7170
return (
7271
<CloseButton
7372
as={Link}
@@ -270,6 +269,7 @@ export const navigation: Array<NavGroup> = [
270269
links: [
271270
{ title: 'Users', href: '/web/users' },
272271
{ title: 'Objects', href: '/web/objects' },
272+
{ title: 'Tasks', href: '/web/tasks' },
273273
],
274274
},
275275
]

src/components/Resources.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import Link from 'next/link'
1010

1111
import { GridPattern } from '@/components/GridPattern'
1212
import { Heading } from '@/components/Heading'
13-
import { EnvelopeIcon } from '@/components/icons/EnvelopeIcon'
1413
import { UserIcon } from '@/components/icons/UserIcon'
1514
import { UsersIcon } from '@/components/icons/UsersIcon'
1615
import { DocumentIcon } from '@/components/icons/DocumentIcon'
16+
import { ShapesIcon } from '@/components/icons/ShapesIcon'
1717

1818
interface Resource {
1919
href: string
@@ -56,11 +56,11 @@ const resources: Array<Resource> = [
5656
},
5757
},
5858
{
59-
href: '/messages',
60-
name: 'Messages',
59+
href: '/web/tasks',
60+
name: 'Tasks',
6161
description:
62-
'Learn about the message model and how to create, retrieve, update, delete, and list messages.',
63-
icon: EnvelopeIcon,
62+
'Learn about Drop\' tasks system, and how to connect to and listen to them.',
63+
icon: ShapesIcon,
6464
pattern: {
6565
y: 32,
6666
squares: [
@@ -113,7 +113,7 @@ function ResourcePattern({
113113
/>
114114
</div>
115115
<motion.div
116-
className="absolute inset-0 rounded-2xl bg-linear-to-r from-blue-600/10 to-blue-400/10 opacity-0 transition duration-300 group-hover:opacity-100 dark:from-[#202D2E] dark:to-[#303428]"
116+
className="absolute inset-0 rounded-2xl bg-linear-to-r from-blue-600/10 to-blue-400/10 opacity-0 transition duration-300 group-hover:opacity-100 dark:from-blue-400/20 dark:to-blue-600/20"
117117
style={style}
118118
/>
119119
<motion.div

0 commit comments

Comments
 (0)