@@ -26,48 +26,32 @@ failure and the task is rescheduled using an exponential-backoff algorithm.
26
26
27
27
Each task function is passed two arguments:
28
28
29
- - ` payload ` &mdash ; the ( JSON) payload you passed when calling
29
+ - ` payload ` &mdash ; the JSON payload you passed when calling
30
30
` graphile_worker.add_job(...) ` in the database, or ` addJob(...) ` via the JS
31
31
API
32
- - ` helpers ` (see [ ` helpers ` ] ( #helpers ) below) &mdash ; an object containing:
33
- - ` logger ` &mdash ; a scoped [ Logger] ( /docs/library/logger ) instance, to aid
34
- tracing/debugging
35
- - ` job ` &mdash ; the whole job (including ` uuid ` , ` attempts ` , etc) &mdash ; you
36
- shouldn't need this
37
- - ` getQueueName() ` &mdash ; get the name of the queue the job is in (may or may
38
- not return a promise - recommend you always ` await ` it)
39
- - ` abortSignal ` &mdash ; could be an ` AbortSignal ` , or ` undefined ` if not
40
- supported by this release of worker; if set, use this to abort your task
41
- early on graceful shutdown (can be passed to a number of asynchronous
42
- Node.js methods)
43
- - ` abortPromise ` &mdash ; if present, a promise that will reject when
44
- ` abortSignal ` aborts; convenient for exiting your task when the abortSignal
45
- fires: ` Promise.race([abortPromise, doYourThing()]) `
46
- - ` withPgClient ` &mdash ; a helper to use to get a database client
47
- - ` query(sql, values) ` &mdash ; a convenience wrapper for
48
- ` withPgClient(pgClient => pgClient.query(sql, values)) `
49
- - ` addJob ` &mdash ; a helper to schedule a job
32
+ - ` helpers ` see [ ` helpers ` ] ( #helpers ) below
50
33
51
34
:::warning Important
52
35
53
- Your jobs must wait for all asynchronous work to be completed before returning,
54
- otherwise we might think they were successful prematurely. Every promise that a
55
- task executor triggers must be ` await ` -ed; task executors _ should not_ create
56
- &ldquo ; untethered&rdquo ; promises.
36
+ Your task executors must wait for all asynchronous work for a job to be
37
+ completed before returning, otherwise Graphile Worker might think they were
38
+ successful prematurely. Every promise that a task executor triggers must be
39
+ ` await ` -ed; task executors _ should not_ create &ldquo ; untethered&rdquo ;
40
+ promises.
57
41
58
42
:::
59
43
60
44
::: tip
61
45
62
- We automatically retry the job if it fails, so it&apos ; s often sensible to split
63
- a large job into multiple smaller jobs, this also allows them to run in parallel
64
- resulting in faster execution. This is particularly important for tasks that are
65
- not idempotent (i.e. running them a second time will have extra side effects)
66
- &mdash ; for example sending emails.
46
+ Graphile Worker automatically retries the job if it fails, so it&apos ; s often
47
+ sensible to split a large job into multiple smaller jobs, this also allows them
48
+ to run in parallel resulting in faster execution. This is particularly important
49
+ for tasks that are not idempotent (i.e. running them a second time will have
50
+ extra side effects) &mdash ; for example sending emails.
67
51
68
52
:::
69
53
70
- ## Example task executors
54
+ ## Example JS task executors
71
55
72
56
``` js title="tasks/task_1.js"
73
57
module .exports = async (payload ) => {
@@ -82,46 +66,41 @@ module.exports = async (payload, helpers) => {
82
66
};
83
67
```
84
68
85
- ## The ` tasks/ ` folder
69
+ ## The task directory
86
70
87
- When you run ` graphile-worker ` , it will look in the current directory for a
88
- folder called ` tasks ` , and it will recursively look for files suitable to run as
89
- tasks. File names excluding the extension and folder names must only use
90
- alphanumeric characters, underscores and dashes (` /^[A-Za-z0-9_-]+$/ ` ) to be
91
- recognized. Graphile Worker will then attempt to load the file as a task
92
- executor; the task identifier for this will be all the folders and the file name
93
- (excluding the extension) joined with ` / ` characters; e.g.
94
- ` tasks/send_notification.js ` would get the identifier ` send_notification ` and
95
- ` tasks/users/emails/verify.js ` would get the identifier ` users/emails/verify ` .
96
- How the file is loaded as a task executor will depend on the file in question
97
- and the plugins you have loaded.
71
+ When you run Graphile Worker, it will look in the configured
72
+ [ ` taskDirectory ` ] ( ./config#workertaskdirectory ) for files suitable to run as
73
+ tasks.
98
74
99
- ```
100
- current directory
101
- ├── package.json
102
- ├── node_modules
103
- └── tasks
104
- ├── send_notification.js
105
- ├── generate_pdf.js
106
- └── users
107
- ├── congratulate.js
108
- └── emails
109
- ├── verify.js
110
- └── send_otp.js
111
- ```
75
+ File names excluding the extension and folder names must only use alphanumeric
76
+ characters, underscores, and dashes (` /^[A-Za-z0-9_-]+$/ ` ) to be recognized.
77
+
78
+ Graphile Worker will then attempt to load the file as a task executor; the task
79
+ identifier for this task will be all the folders and the file name (excluding
80
+ the extension) joined with ` / ` characters:
81
+
82
+ - ` ${taskDirectory}/send_notification.js ` would get the task identifier
83
+ ` send_notification ` .
84
+ - ` ${taskDirectory}/users/emails/verify.js ` would get the task identifier
85
+ ` users/emails/verify ` .
86
+
87
+ How the file is loaded as a task executor will depend on the specific file and
88
+ the plugins you have loaded.
112
89
113
- ## Loading JavaScript files
90
+ ## Loading JavaScript task executors
114
91
115
- Out of the box , Graphile Worker will load ` .js ` , ` .cjs ` and ` .mjs ` files using
116
- the ` import() ` function. If the file is a CommonJS module then Worker will
117
- expect ` module.exports ` to be the task executor function; if the file is an
118
- ECMAScript module (ESM) then Worker will expect the default export to be the
119
- task executor function.
92
+ With the default preset , Graphile Worker will load ` .js ` , ` .cjs ` and ` .mjs `
93
+ files as task executors using the ` import() ` function. If the file is a CommonJS
94
+ module, then Worker will expect ` module.exports ` to be the task executor
95
+ function; if the file is an ECMAScript module (ESM) then Worker will expect the
96
+ default export to be the task executor function.
120
97
121
- Via plugins, support for other ways of loading task files can be added; look at
122
- the source code of ` LoadTaskFromJsPlugin.ts ` for inspiration.
98
+ You can add support for other ways of loading task executors via plugins; look
99
+ at the source code of
100
+ [ ` LoadTaskFromJsPlugin.ts ` ] ( https://github.com/graphile/worker/blob/main/src/plugins/LoadTaskFromJsPlugin.ts )
101
+ for inspiration.
123
102
124
- ### Loading TypeScript files
103
+ ### Loading TypeScript task executors
125
104
126
105
::: tip
127
106
@@ -130,16 +109,15 @@ TypeScript files to JS and then have Graphile Worker load the JS files.
130
109
131
110
:::
132
111
133
- To load TypeScript files directly as tasks (without precompilation), one way is
134
- to :
112
+ To load TypeScript files directly as task executors (without precompilation),
113
+ one way is to do the following :
135
114
136
- 1 . install ` ts-node ` ,
137
- 2 . add ` ".ts" ` to the ` worker.fileExtensions ` list in your ` graphile.config.ts ` ,
138
- 3 . run Graphile Worker with the environmental variable
115
+ 1 . Install ` ts-node ` .
116
+ 2 . Add ` ".ts" ` to the ` worker.fileExtensions ` list in your preset.
117
+ 3 . Run Graphile Worker with the environment variable
139
118
` NODE_OPTIONS="--loader ts-node/esm" ` set.
140
119
141
120
``` ts title="Example graphile.config.ts"
142
- import type { GraphileConfig } from " graphile-config" ;
143
121
import type {} from " graphile-worker" ;
144
122
145
123
const preset: GraphileConfig .Preset = {
@@ -167,18 +145,18 @@ This feature is currently experimental.
167
145
:::
168
146
169
147
If you're running on Linux or Unix (including macOS) then if Graphile Worker
170
- finds an executable file inside of ` tasks/ ` it will create a task executor for
171
- it. When a task of this kind is found, Graphile Worker will execute the file
172
- setting the relevant environmental variables and passing in the payload
148
+ finds an executable file inside of the ` taskDirectory ` it will create a task
149
+ executor for it. When a task of this kind is found, Graphile Worker will execute
150
+ the file with the relevant environment variables and pass in the payload
173
151
according to the encoding. If the executable exits with code ` 0 ` then Graphile
174
- Worker will see this as success, all other exit codes are seen as failure.
152
+ Worker will see this as success. All other exit codes are seen as failure.
175
153
176
- ### Environmental variables
154
+ ### Environment variables
177
155
178
156
- ` GRAPHILE_WORKER_PAYLOAD_FORMAT ` &mdash ; the encoding that Graphile Worker
179
- uses to pass the payload to the binary. Currently this will be the string
180
- ` json ` , but you should check this before processing the payload in case the
181
- format changes.
157
+ used to pass the payload to the binary. Currently this will always be the
158
+ string ` json ` , but you should check this before processing the payload in case
159
+ the format changes.
182
160
- ` GRAPHILE_WORKER_TASK_IDENTIFIER ` &mdash ; the identifier for the task this
183
161
file represents (useful if you want multiple task identifiers to be served by
184
162
the same binary file, e.g. via symlinks)
@@ -198,34 +176,59 @@ Worker will see this as success, all other exit codes are seen as failure.
198
176
199
177
In the JSON payload format, your binary will be fed via stdin
200
178
` JSON.stringify({payload}) ` ; for example, if you did
201
- ` addJob('myScript ', {mol: 42}) ` then your ` myScript ` task would be sent
179
+ ` addJob('my_script ', {mol: 42}) ` then your ` my_script ` task would be sent
202
180
` {"payload":{"mol":42}} ` via stdin.
203
181
204
182
## Handling batch jobs
205
183
206
- If the payload is an array, then _ optionally_ your task may choose to return an
207
- array of the same length, the entries in which are promises. Should any of these
208
- promises reject, then the job will be re-enqueued, but the payload will be
209
- overwritten to only contain the entries associated with the rejected promises
210
- &mdash ; i.e. the successful entries will be removed.
184
+ If the payload is an array, then _ optionally_ your task executor may choose to
185
+ return an array of the same length, the entries in which are promises. Should
186
+ any of these promises reject, then the job will be re-enqueued, but the payload
187
+ will be overwritten to only contain the entries associated with the rejected
188
+ promises &mdash ; i.e. the successful entries will be removed.
211
189
212
190
## ` helpers `
213
191
192
+ ### ` helpers.abortPromise `
193
+
194
+ This is a promise that will reject when [ ` abortSignal ` ] ( #helpersabortsignal )
195
+ aborts. This makes it convenient for exiting your task when the abortSignal
196
+ fires: ` Promise.race([abortPromise, doYourAsyncThing()]) ` .
197
+
198
+ ### ` helpers.abortSignal `
199
+
200
+ This is a Node ` AbortSignal ` . Use this to be notified that you should abort your
201
+ task early due to a graceful shutdown request. ` AbortSignal ` s can be passed to a
202
+ number of asynchronous Node.js methods like
203
+ [ ` http.request() ` ] ( https://nodejs.org/api/http.html#httprequesturl-options-callback ) .
204
+
205
+ ### ` helpers.addJob() `
206
+
207
+ See [ ` addJob ` ] ( /library/add-job.md ) .
208
+
209
+ ### ` helpers.addJobs() `
210
+
211
+ See [ ` addJobs ` ] ( /library/add-job.md#add-jobs ) .
212
+
213
+ ### ` helpers.getQueueName() `
214
+
215
+ Get the name of the queue the job is in, or the queue name of the provided queue
216
+ ID. This function may or may not return a promise. We recommend that you always
217
+ ` await ` it.
218
+
219
+ ### ` helpers.job `
220
+
221
+ The whole job, including ` uuid ` , ` attempts ` , etc.
222
+
214
223
### ` helpers.logger `
215
224
216
- So that you may redirect logs to your preferred logging provider, we have
217
- enabled you to supply your own logging provider. Overriding this is currently
218
- only available in library mode (see [ Logger] ( /library/logger.md ) ). We then wrap
219
- this logging provider with a helper class to ease debugging; the helper class
220
- has the following methods:
225
+ See [ Logger] ( ./library/logger )
226
+
227
+ ### ` helpers.query() `
221
228
222
- - ` error(message, meta?) ` : for logging errors, similar to ` console.error `
223
- - ` warn(message, meta?) ` : for logging warnings, similar to ` console.warn `
224
- - ` info(message, meta?) ` : for logging informational messages, similar to
225
- ` console.info `
226
- - ` debug(message, meta?) ` : to aid with debugging, similar to ` console.log `
227
- - ` scope(additionalScope) ` : returns a new ` Logger ` instance with additional
228
- scope information
229
+ This is a convenience wrapper for
230
+ ` withPgClient(pgClient => pgClient.query(sql, values)) ` . See
231
+ [ ` withPgClient() ` ] ( #helperswithpgclient )
229
232
230
233
### ` helpers.withPgClient() `
231
234
@@ -249,19 +252,3 @@ keeping transactions open may decrease Graphile Worker's performance due to
249
252
increasing contention over the pool of database clients.
250
253
251
254
:::
252
-
253
- ### ` helpers.addJob() `
254
-
255
- ``` ts
256
- await helpers .addJob (identifier , payload , options );
257
- ```
258
-
259
- See [ ` addJob ` ] ( /library/add-job.md ) .
260
-
261
- ### ` helpers.addJobs() `
262
-
263
- ``` ts
264
- await helpers .addJobs (specs , preserveRunAt );
265
- ```
266
-
267
- See [ ` addJobs ` ] ( /library/add-job.md#add-jobs ) .
0 commit comments