-
Notifications
You must be signed in to change notification settings - Fork 237
/
task.nu
434 lines (387 loc) · 12.6 KB
/
task.nu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
# Spawn a task to run in the background, even when the shell is closed.
#
# Note that a fresh Nushell interpreter is spawned to execute the
# given task, so it won't inherit the current scope's variables,
# custom commands and alias definitions.
#
# It will only inherit environment variables which can be converted to a string.
#
# Note that the closure can't take arguments.
#
# Example usage: task spawn { echo "Hello, World!" }
export def spawn [
command: closure # The closure to run.
--working-directory (-w): directory # Specify the working directory the task will be run in.
--immediate (-i) # Immediately start the task.
--stashed (-s) # Create the task in Stashed state. Useful to avoid immediate execution if the queue is empty
--delay (-d): duration # Queue the task for execution only after the duration.
--group (-g): string # The group to spawn the task under.
--after (-a): int # Start the task once all specified tasks have successfully finished. As soon as one of the dependencies fails, this task will fail as well.
--priority (-o): string # Start this task with a higher priority. The higher the number, the faster it will be processed.
--label (-l): string # Label the task. This string will be shown in the `status` column of `task status`.
] -> int {
mut args = []
if $working_directory != null {
$args = ($args | prepend ["--working-directory", $working_directory])
}
if $immediate {
$args = ($args | prepend "--immediate")
}
if $stashed {
$args = ($args | prepend "--stashed")
}
if $delay != null {
$args = ($args | prepend ["--delay" ($delay | format duration sec | parse "{secs} {_}" | get 0.secs)])
}
if $group != null {
$args = ($args | prepend ["--group" $group])
}
if $after != null {
$args = ($args | prepend ["--after" $after])
}
if $priority != null {
$args = ($args | prepend ["--priority" $priority])
}
if $label != null {
$args = ($args | prepend ["--label" $label])
}
let source_path = mktemp --tmpdir --suffix "-nu-task"
(
view source $command
| str trim --left --char "{"
| str trim --right --char "}"
)
| save --force $source_path
(pueue add --print-task-id ...$args $"nu --config '($nu.config-path)' --env-config '($nu.env-path)' ($source_path)")
}
# Remove tasks from the queue.
# Running or paused tasks need to be killed first.
export def remove [
...ids: int # IDs of the tasks to remove from the status list.
] {
pueue remove ...$ids
}
# Switches the queue position of two tasks.
# Only works for queued or stashed tasks.
export def switch [
task_id_1: int # The first task ID.
task_id_2: int # The second task ID.
] {
pueue switch $task_id_1 $task_id_2
}
# Stash a task that is not currently running.
#
# Stashed tasks won't be automatically started.
# You will have to queue them or start them by hand.
export def stash [
...ids: int # IDs of the tasks to stash.
] {
pueue stash ...$ids
}
# Queue stashed tasks for execution.
export def queue [
...ids: int # IDs of the tasks to queue.
--delay (-d): duration # Queue only after the specified delay.
] {
let args = if $delay != null {
["--delay" ($delay | format duration sec | parse '{secs} {_}' | get 0.secs)]
} else {
[]
}
pueue enqueue ...$args ...$ids
}
# Resume operation of specific tasks or groups of tasks.
#
# By default, this resumes the default group and all its tasks.
# It can also be used force-start specific tasks or start whole groups.
export def start [
...ids: int # IDs of the tasks to start. By default all the tasks in the default group will be started.
--group (-g): string # Resume a specific group and all paused tasks in it. The group will be set to running and its paused tasks will be resumed.
--all (-a) # Resume all groups. All groups will be set to running and paused tasks will be resumed.
] {
mut args = []
if $group != null {
$args = ($args | prepend ["--group" $group])
}
if $all {
$args = ($args | prepend "--all")
}
pueue start ...$args
}
# Restart failed or successful task(s).
#
# By default, identical tasks will be created and
# enqueued, but it's possible to restart in-place.
#
# You can also edit a few properties, such as
# the path and the command of the task, before restarting.
export def restart [
...ids: int # IDs of the tasks to restart.
--all-failed (-a) # Restart all failed tasks across all groups. Nice to use in combination with `--in-place/i`.
--failed-in-group (-g): string # Like `--all-failed`, but only restart tasks failed tasks of a specific group. The group will be set to running and its paused tasks will be resumed.
--start-immediately (-k) # Immediately start the tasks, no matter how many open slots there are. This will ignore any dependencies tasks may have.
--stashed (-s) # Set the restarted task to a "Stashed" state. Useful to avoid immediate execution.
--in-place (-i) # Restart the tasks by reusing the already existing tasks.
--not-in-place (-n) # Opposite of `--in-place`. This is already the default unless you have `restart_in_place` set to true.
--edit (-e) # Edit the tasks' commands before restarting
--edit-path (-p) # Edit the tasks' paths before restarting
--edit-label (-l) # Edit the tasks' labels before restarting
] {
mut args = []
if $all_failed {
$args = ($args | prepend "--all-failed")
}
if $failed_in_group != null {
$args = ($args | prepend "--failed-in-group")
}
if $start_immediately {
$args = ($args | prepend "--start-immediately")
}
if $stashed {
$args = ($args | prepend "--stashed")
}
if $in_place {
$args = ($args | prepend "--in-place")
}
if $not_in_place {
$args = ($args | prepend "--not-in-place")
}
if $edit {
$args = ($args | prepend "--edit")
}
if $edit_path {
$args = ($args | prepend "--edit-path")
}
if $edit_label {
$args = ($args | prepend "--edit-label")
}
pueue restart ...$args ...$ids
}
# Either pause a running tasks or a specific groups of tasks.
#
# By default, pauses the default group and all its tasks.
#
# A paused group won't start any new tasks automatically.
export def pause [
...ids: int # IDs of the tasks to pause.
--group (-g) # Pause a specific group
--all (-a) # Pause all groups.
--wait (-w) # Only pause the specified group and let already running tasks finish by themselves
] {
mut args = []
if $group != null {
$args = ($args | prepend "--group")
}
if $all != null {
$args = ($args | prepend "--all")
}
if $wait != null {
$args = ($args | prepend "--wait")
}
pueue pause ...$args ...$ids
}
# Kill specific running tasks or whole task groups.
#
# Kills all tasks of the default group when no ids or a specific group are provided.
export def kill [
...ids: int # IDs of the tasks to kill.
--group (-g): string # Kill all running tasks in a group. This also pauses the group.
--all (-a) # Kill all running tasks across ALL groups. This also pauses all groups.
--signal (-s): string # Send a UNIX signal instead of simply killing the process. DISCLAIMER: This bypasses Pueue's process handling logic! You might enter weird invalid states, use at your own descretion.
] {
mut args = []
if $group != null {
$args = ($args | prepend ["--group" $group])
}
if $all {
$args = ($args | prepend "--all")
}
if $signal != null {
$args = ($args | prepend ["--signal" $signal])
}
pueue kill ...$args ...$ids
}
# Send something to a task. Useful for sending confirmations such as "y\n".
export def send [
id: int # ID of the task to send something to.
input: string # The input that should be sent to the process.
] {
pueue send $id $input
}
# Edit the command, path or label of a stashed or queued task.
#
# By default only the command is edited.
#
# Multiple properties can be added in one go.
export def edit [
id: int # ID of the task to edit.
--command (-c) # Edit the task's command
--path (-p) # Edit the task's path
--label (-l) # Edit the task's label
] {
mut args = []
if $command {
$args = ($args | prepend "--command")
}
if $path {
$args = ($args | prepend "--path")
}
if $label {
$args = ($args | prepend "--label")
}
pueue edit ...$args $id
}
# Use this to add or remove groups.
#
# By default, this will simply display all known groups.
export def group [] {
pueue group --json | from json
}
# Create a new group with a name.
export def "group add" [
name: string # The name of the new group.
--parallel (-p): int # The amount of parallel tasks the group can run at one time.
] {
let args = if $parallel != null {
["--parallel" $parallel]
} else {
[]
}
pueue group add ...$args $name
}
# Remove a group with a name.
export def "group remove" [
name: string # The name of the group to be removed.
] {
pueue group remove $name
}
# Display the current status of all tasks.
export def status [
--detailed (-d) # Return a table with more detailed information.
] {
let output = (
pueue status --json
| from json
| get tasks
| transpose --ignore-titles status
| flatten
)
# TODO: Rename the Done column to done.
if not $detailed {
$output | select id label group Done? status? start? end?
} else {
$output
}
}
# Display the output of tasks.
#
# Only the last few lines will be shown by default for multiple tasks.
# If you want to follow the output, use `--tail/-t`.
export def log [
...ids: int # The tasks to check the outputs of.
--last (-l): int # Only print the last N lines of each task's output. This is done by default if you're looking at multiple tasks.
--tail (-t) # Follow the output as it is printing. Only works with 1 task. When used in conjunction with `--last`, the last N lines will be printed before starting to wait for output.
--detailed (-d) # Include all fields, don't simplify output.
] {
def process_raw [raw: string] {
let full = (
$raw
| from json
| transpose -i info
| flatten --all
| flatten --all
)
if $detailed {
$full
} else {
$full | select id label group Done? status? start? end?
}
}
if (($ids | length) == 1) {
if $tail {
let args = if $last != null {
["--lines" $last]
} else {
[]
}
pueue follow ...$ids
} else {
let args = if $last != null {
["--lines" $last]
} else {
[]
}
process_raw (pueue log --full --json ...$args ...$ids)
| first
}
} else {
if $tail {
echo $"(ansi red)--tail can only be used with one task.(ansi reset)"
return
}
let args = if $last != null {
["--lines" $last]
} else {
[]
}
process_raw (pueue log --full --json ...$args ...$ids)
}
}
# Wait until the provided tasks are finished.
#
# This is like join() or await in many languages.
export def wait [
...ids: int # IDs of the tasks to wait for.
--group (-g): string # Wait for all tasks in a specific group.
--all (-a) # Wait for all tasks across all groups and the default group.
--quiet (-q) # Don't show any log output while waiting.
--status (-s): string # Wait for tasks to reach a specific task status.
] {
mut args = []
if $group != null {
$args = ($args | prepend ["--group" $group])
}
if $all {
$args = ($args | prepend $all)
}
if $quiet {
$args = ($args | prepend $quiet)
}
if $status != null {
$args = ($args | prepend ["--status" $status])
}
pueue wait ...$args ...$ids
}
# Remove tasks from the status list.
export def clean [
--successful-only (-s) # Only clean tasks that finished successfully
--group (-g): string # Only clean tasks of a specific group
] {
mut args = []
if $successful_only {
$args = ($args | prepend "--successful-only")
}
if $group != null {
$args = ($args | prepend ["--group" $group])
}
pueue clean ...$args
}
# Shutdown pueue and thus this module.
export def shutdown [] {
pueue shutdown
}
# Set the maximum parallel tasks for a group.
#
# Note that no tasks will be stopped if the number is lowered.
# The limit only applies when schelduing.
export def set-parallel-limit [
max: int # The maximum parallel tasks allowed for a group when schelduing.
--group (-g): string # The group to set the limit for. By default this is `default`.
] {
let args = if $group != null {
["--group" $group]
} else {
[]
}
pueue parallel ...$args $max
}