async-lube 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/README.md +1 -1
- package/docs/http.md +1 -1
- package/docs/reference.md +4 -2
- package/docs/tasks.md +19 -2
- package/package.json +4 -5
- package/public.d.ts +112 -0
- package/src/attempt.js +17 -7
- package/src/durable/context.js +107 -64
- package/src/durable/error.js +39 -15
- package/src/durable/index.js +18 -10
- package/src/durable/journal.js +29 -14
- package/src/durable/json.js +26 -9
- package/src/durable/lease.js +15 -5
- package/src/durable/persist.js +60 -22
- package/src/durable/run.js +103 -41
- package/src/durable/send.js +30 -13
- package/src/durable/serve.js +30 -24
- package/src/durable/state.js +28 -13
- package/src/durable/store.js +19 -10
- package/src/durable/watch.js +31 -11
- package/src/errors.js +9 -3
- package/src/flow/attempts.js +49 -29
- package/src/flow/builder.js +260 -161
- package/src/flow/compile.js +86 -66
- package/src/flow/graph.js +108 -42
- package/src/flow/index.js +13 -7
- package/src/flow/items.js +79 -46
- package/src/flow/nodes.js +267 -117
- package/src/flow/refs.js +27 -13
- package/src/flow/resources.js +9 -3
- package/src/flow/run.js +287 -114
- package/src/flow/streams.js +44 -19
- package/src/flow/subflows.js +93 -53
- package/src/http/config.js +11 -5
- package/src/http/index.js +25 -14
- package/src/http/refresh.js +29 -12
- package/src/http/request.js +246 -151
- package/src/http/response.js +105 -50
- package/src/http/retry.js +52 -27
- package/src/http/socket.js +220 -172
- package/src/http/sse.js +113 -74
- package/src/http/throttle.js +9 -4
- package/src/http/url.js +58 -35
- package/src/http/xhr.js +29 -24
- package/src/index.js +1 -0
- package/src/key.js +3 -5
- package/src/limiter.js +146 -65
- package/src/offload.js +116 -85
- package/src/offload_module.js +594 -0
- package/src/options.js +8 -4
- package/src/redial.js +129 -0
- package/src/signal.js +14 -4
- package/src/stream.js +353 -198
- package/types/attempt.d.ts.map +1 -1
- package/types/durable/index.d.ts.map +1 -1
- package/types/durable/state.d.ts.map +1 -1
- package/types/durable/store.d.ts.map +1 -1
- package/types/errors.d.ts.map +1 -1
- package/types/http/index.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/limiter.d.ts +5 -1
- package/types/limiter.d.ts.map +1 -1
- package/types/offload.d.ts +2 -16
- package/types/offload.d.ts.map +1 -1
- package/types/redial.d.ts +28 -0
- package/types/redial.d.ts.map +1 -0
- package/types/stream.d.ts +2 -0
- package/types/stream.d.ts.map +1 -1
package/src/flow/nodes.js
CHANGED
|
@@ -73,22 +73,27 @@ function apply_value(c, name, value) {
|
|
|
73
73
|
set_status(c, record, "skipped")
|
|
74
74
|
delete c.results[name]
|
|
75
75
|
enter(c, targets, name)
|
|
76
|
-
if (c.run_status != "running")
|
|
76
|
+
if (c.run_status != "running") {
|
|
77
|
+
return
|
|
78
|
+
}
|
|
77
79
|
if (record.status == "skipped") {
|
|
78
80
|
kill_transitions(c, name)
|
|
79
|
-
for (const dependent of record.node.dependents)
|
|
80
|
-
|
|
81
|
+
for (const dependent of record.node.dependents) {
|
|
82
|
+
try_start(c, dependent)
|
|
83
|
+
}
|
|
84
|
+
if (record.backlog.length > record.backlog_head || record.retrigger) {
|
|
85
|
+
defer(c, () => run_next(c, name))
|
|
86
|
+
}
|
|
81
87
|
}
|
|
82
88
|
drain(c)
|
|
83
89
|
schedule(c)
|
|
84
90
|
}
|
|
85
91
|
/**
|
|
86
|
-
* @param {RunContext} c
|
|
87
92
|
* @param {NodeRecord} record
|
|
88
93
|
* @returns {unknown[]}
|
|
89
94
|
*/
|
|
90
|
-
export function args_of(
|
|
91
|
-
return
|
|
95
|
+
export function args_of(record) {
|
|
96
|
+
return /** @type {unknown[]} */(record.args)/**/
|
|
92
97
|
}
|
|
93
98
|
/**
|
|
94
99
|
* @param {RunContext} c
|
|
@@ -97,12 +102,14 @@ export function args_of(c, record) {
|
|
|
97
102
|
*/
|
|
98
103
|
export function clear_record(c, record) {
|
|
99
104
|
const { name, options } = record.node
|
|
100
|
-
if (options.release && record.status == "done" && !record.released)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
105
|
+
if (options.release && record.status == "done" && !record.released) {
|
|
106
|
+
release_quietly(
|
|
107
|
+
record,
|
|
108
|
+
new CancelError(
|
|
109
|
+
`Flow node "${name}" was reset`
|
|
110
|
+
)
|
|
104
111
|
)
|
|
105
|
-
|
|
112
|
+
}
|
|
106
113
|
stop_record(
|
|
107
114
|
c,
|
|
108
115
|
record,
|
|
@@ -112,12 +119,16 @@ export function clear_record(c, record) {
|
|
|
112
119
|
)
|
|
113
120
|
: void 0
|
|
114
121
|
)
|
|
115
|
-
if (record.status == "done")
|
|
122
|
+
if (record.status == "done") {
|
|
123
|
+
record.previous = record.result
|
|
124
|
+
}
|
|
116
125
|
delete c.errors[name]
|
|
117
126
|
if (record.node.each) {
|
|
118
127
|
const prefix = name + "."
|
|
119
128
|
for (const key of Object.keys(c.errors)) {
|
|
120
|
-
if (key.startsWith(prefix))
|
|
129
|
+
if (key.startsWith(prefix)) {
|
|
130
|
+
delete c.errors[key]
|
|
131
|
+
}
|
|
121
132
|
}
|
|
122
133
|
}
|
|
123
134
|
record.abandoned = false
|
|
@@ -150,7 +161,9 @@ export function clear_record(c, record) {
|
|
|
150
161
|
function drop(c, name, error) {
|
|
151
162
|
c.errors[name] = error
|
|
152
163
|
settle(c, name, "skipped", void 0)
|
|
153
|
-
for (const dep of get_record(c, name).node.deps)
|
|
164
|
+
for (const dep of get_record(c, name).node.deps) {
|
|
165
|
+
release_unused(c, dep, error)
|
|
166
|
+
}
|
|
154
167
|
}
|
|
155
168
|
/**
|
|
156
169
|
* @param {RunContext} c
|
|
@@ -185,7 +198,9 @@ export function fail(c, name, error) {
|
|
|
185
198
|
new CancelError("The flow failed"),
|
|
186
199
|
true
|
|
187
200
|
)
|
|
188
|
-
if (!c.cycle.settled)
|
|
201
|
+
if (!c.cycle.settled) {
|
|
202
|
+
close_cycle(c, failure, void 0)
|
|
203
|
+
}
|
|
189
204
|
}
|
|
190
205
|
/**
|
|
191
206
|
* @param {RunContext} c
|
|
@@ -220,9 +235,7 @@ export function forget_runs(record) {
|
|
|
220
235
|
* @returns {NodeRecord}
|
|
221
236
|
*/
|
|
222
237
|
export function get_record(c, name) {
|
|
223
|
-
|
|
224
|
-
if (!record) throw Error(`Unknown flow node "${name}"`)
|
|
225
|
-
return record
|
|
238
|
+
return /** @type {NodeRecord} */(c.records.get(name))/**/
|
|
226
239
|
}
|
|
227
240
|
/**
|
|
228
241
|
* @param {RunContext} c
|
|
@@ -236,12 +249,14 @@ async function handle_error(c, name, error, from_items, index) {
|
|
|
236
249
|
const record = get_record(c, name)
|
|
237
250
|
const token = record.token
|
|
238
251
|
const { fallback, options } = record.node
|
|
239
|
-
if (index != null)
|
|
252
|
+
if (index != null) {
|
|
253
|
+
c.errors[name + "." + index] = error
|
|
254
|
+
}
|
|
240
255
|
if (options.catch && !from_items) {
|
|
241
256
|
try {
|
|
242
257
|
const value = await options.catch(
|
|
243
258
|
error,
|
|
244
|
-
...args_of(
|
|
259
|
+
...args_of(record),
|
|
245
260
|
make_context(
|
|
246
261
|
c,
|
|
247
262
|
record,
|
|
@@ -251,22 +266,32 @@ async function handle_error(c, name, error, from_items, index) {
|
|
|
251
266
|
record.runs.get("")
|
|
252
267
|
)
|
|
253
268
|
)
|
|
254
|
-
if (token != record.token)
|
|
269
|
+
if (token != record.token) {
|
|
270
|
+
return
|
|
271
|
+
}
|
|
255
272
|
c.errors[name] = error
|
|
256
273
|
apply_value(c, name, value)
|
|
257
274
|
} catch (catch_error) {
|
|
258
|
-
if (token != record.token)
|
|
259
|
-
|
|
260
|
-
|
|
275
|
+
if (token != record.token) {
|
|
276
|
+
return
|
|
277
|
+
}
|
|
278
|
+
if (record.abandoned) {
|
|
279
|
+
drop(c, name, catch_error)
|
|
280
|
+
} else {
|
|
281
|
+
fail(c, name, catch_error)
|
|
282
|
+
}
|
|
261
283
|
}
|
|
262
|
-
} else if (record.abandoned)
|
|
263
|
-
|
|
284
|
+
} else if (record.abandoned) {
|
|
285
|
+
drop(c, name, error)
|
|
286
|
+
} else if (fallback.length) {
|
|
264
287
|
c.errors[name] = error
|
|
265
288
|
apply_value(c, name, { [GOTO]: fallback })
|
|
266
289
|
} else if (options.optional && !from_items) {
|
|
267
290
|
c.errors[name] = error
|
|
268
291
|
settle(c, name, "failed", void 0)
|
|
269
|
-
} else
|
|
292
|
+
} else {
|
|
293
|
+
fail(c, name, error)
|
|
294
|
+
}
|
|
270
295
|
}
|
|
271
296
|
/**
|
|
272
297
|
* @param {NodeRecord} record
|
|
@@ -311,7 +336,9 @@ function launch(c, record, args) {
|
|
|
311
336
|
return false
|
|
312
337
|
}
|
|
313
338
|
} catch (error) {
|
|
314
|
-
if (c.run_status != "running" || record.status != "idle")
|
|
339
|
+
if (c.run_status != "running" || record.status != "idle") {
|
|
340
|
+
return false
|
|
341
|
+
}
|
|
315
342
|
record.args = args
|
|
316
343
|
if (kind == "input" || each) {
|
|
317
344
|
fail_input(c, record, error)
|
|
@@ -319,7 +346,9 @@ function launch(c, record, args) {
|
|
|
319
346
|
}
|
|
320
347
|
record.gate = { error }
|
|
321
348
|
}
|
|
322
|
-
if (c.run_status != "running" || record.status != "idle")
|
|
349
|
+
if (c.run_status != "running" || record.status != "idle") {
|
|
350
|
+
return false
|
|
351
|
+
}
|
|
323
352
|
record.args = args
|
|
324
353
|
if (kind == "input" && record.buffer) {
|
|
325
354
|
const { value } = record.buffer
|
|
@@ -337,22 +366,21 @@ function launch(c, record, args) {
|
|
|
337
366
|
set_status(c, record, "waiting")
|
|
338
367
|
if (options.timeout) {
|
|
339
368
|
const timeout = options.timeout
|
|
340
|
-
const token = record.token
|
|
341
369
|
const deadline = record.resume_deadline ?? Date.now() + timeout
|
|
342
370
|
record.deadline = deadline
|
|
343
371
|
record.resume_deadline = void 0
|
|
344
|
-
/**
|
|
345
|
-
* @returns {void}
|
|
346
|
-
*/
|
|
372
|
+
/** @returns {void} */
|
|
347
373
|
function expire() {
|
|
348
|
-
if (record.status != "waiting" || token != record.token) return
|
|
349
374
|
const left = deadline - Date.now()
|
|
350
|
-
if (left > 0)
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
375
|
+
if (left > 0) {
|
|
376
|
+
record.timer = setTimeout(expire, clamp_delay(left))
|
|
377
|
+
} else {
|
|
378
|
+
fail_input(
|
|
379
|
+
c,
|
|
380
|
+
record,
|
|
381
|
+
new TimeoutError(timeout)
|
|
382
|
+
)
|
|
383
|
+
}
|
|
356
384
|
}
|
|
357
385
|
record.timer = setTimeout(
|
|
358
386
|
expire,
|
|
@@ -362,7 +390,9 @@ function launch(c, record, args) {
|
|
|
362
390
|
} else if (c.running >= c.concurrency) {
|
|
363
391
|
set_status(c, record, "pending")
|
|
364
392
|
c.queue.push(name)
|
|
365
|
-
} else
|
|
393
|
+
} else {
|
|
394
|
+
start(c, name)
|
|
395
|
+
}
|
|
366
396
|
return true
|
|
367
397
|
}
|
|
368
398
|
/**
|
|
@@ -372,9 +402,11 @@ function launch(c, record, args) {
|
|
|
372
402
|
*/
|
|
373
403
|
export function name_or_throw(c, target) {
|
|
374
404
|
const name = c.program.name_of(target)
|
|
375
|
-
if (name == null)
|
|
376
|
-
|
|
377
|
-
|
|
405
|
+
if (name == null) {
|
|
406
|
+
throw Error(
|
|
407
|
+
`${describe(target)} is not added to the flow`
|
|
408
|
+
)
|
|
409
|
+
}
|
|
378
410
|
return name
|
|
379
411
|
}
|
|
380
412
|
/**
|
|
@@ -384,18 +416,30 @@ export function name_or_throw(c, target) {
|
|
|
384
416
|
*/
|
|
385
417
|
function needs(c, name) {
|
|
386
418
|
const record = get_record(c, name)
|
|
387
|
-
if (!record.activated || record.status != "idle" && !(record.retrigger && active_statuses.has(record.status)))
|
|
419
|
+
if (!record.activated || record.status != "idle" && !(record.retrigger && active_statuses.has(record.status))) {
|
|
420
|
+
return false
|
|
421
|
+
}
|
|
388
422
|
const { arrive, deps, options } = record.node
|
|
389
423
|
for (const dep of deps) {
|
|
390
424
|
const dep_record = get_record(c, dep)
|
|
391
|
-
if (dep_record.fatal)
|
|
392
|
-
|
|
425
|
+
if (dep_record.fatal) {
|
|
426
|
+
return false
|
|
427
|
+
}
|
|
428
|
+
if (dep_record.node.options.release && !settled_statuses.has(dep_record.status)) {
|
|
429
|
+
continue
|
|
430
|
+
}
|
|
393
431
|
if (arrive?.[dep] == "queue") {
|
|
394
|
-
if (!record.queued?.get(dep)?.length)
|
|
432
|
+
if (!record.queued?.get(dep)?.length) {
|
|
433
|
+
return false
|
|
434
|
+
}
|
|
395
435
|
continue
|
|
396
436
|
}
|
|
397
|
-
if (!settled_statuses.has(dep_record.status))
|
|
398
|
-
|
|
437
|
+
if (!settled_statuses.has(dep_record.status)) {
|
|
438
|
+
return false
|
|
439
|
+
}
|
|
440
|
+
if (dep_record.status == "skipped" && (options.join ?? "all") == "all") {
|
|
441
|
+
return false
|
|
442
|
+
}
|
|
399
443
|
}
|
|
400
444
|
return !options.release || !record.node.dependents.length || record.node.dependents.some(
|
|
401
445
|
dependent => needs(c, dependent)
|
|
@@ -449,10 +493,13 @@ export function plan_retry(record) {
|
|
|
449
493
|
*/
|
|
450
494
|
export function prepare_restart(c, record) {
|
|
451
495
|
record.fatal = false
|
|
452
|
-
if (record.args && !same_args(c, record))
|
|
453
|
-
|
|
496
|
+
if (record.args && !same_args(c, record)) {
|
|
497
|
+
forget_runs(record)
|
|
498
|
+
} else {
|
|
454
499
|
record.resume_items = record.items ?? record.resume_items
|
|
455
|
-
if (record.sub_runs.size)
|
|
500
|
+
if (record.sub_runs.size) {
|
|
501
|
+
record.resume_subs = snapshot_subs(record)
|
|
502
|
+
}
|
|
456
503
|
}
|
|
457
504
|
set_status(c, record, "idle")
|
|
458
505
|
record.sub_runs.clear()
|
|
@@ -463,7 +510,9 @@ export function prepare_restart(c, record) {
|
|
|
463
510
|
* @returns {void}
|
|
464
511
|
*/
|
|
465
512
|
function release(c, record) {
|
|
466
|
-
if (!record.slot)
|
|
513
|
+
if (!record.slot) {
|
|
514
|
+
return
|
|
515
|
+
}
|
|
467
516
|
record.slot = false
|
|
468
517
|
c.running--
|
|
469
518
|
}
|
|
@@ -473,9 +522,13 @@ function release(c, record) {
|
|
|
473
522
|
* @returns {void}
|
|
474
523
|
*/
|
|
475
524
|
function run_next(c, name) {
|
|
476
|
-
if (c.room_waiters.length)
|
|
525
|
+
if (c.room_waiters.length) {
|
|
526
|
+
wake_room(c)
|
|
527
|
+
}
|
|
477
528
|
const record = get_record(c, name)
|
|
478
|
-
if (c.run_status != "running" || active_statuses.has(record.status))
|
|
529
|
+
if (c.run_status != "running" || active_statuses.has(record.status)) {
|
|
530
|
+
return
|
|
531
|
+
}
|
|
479
532
|
const { backlog, backlog_head } = record
|
|
480
533
|
const entry = backlog[backlog_head]
|
|
481
534
|
const retrigger = record.retrigger
|
|
@@ -486,21 +539,32 @@ function run_next(c, name) {
|
|
|
486
539
|
: void 0
|
|
487
540
|
/** @type {Iterable<string>} */
|
|
488
541
|
let touched = [ name ]
|
|
489
|
-
if (entry?.resume)
|
|
490
|
-
|
|
491
|
-
|
|
542
|
+
if (entry?.resume) {
|
|
543
|
+
clear_record(c, record)
|
|
544
|
+
} else {
|
|
545
|
+
touched = reset(c, name, true, true)
|
|
546
|
+
}
|
|
547
|
+
if (plan) {
|
|
548
|
+
plan_resume(record, plan)
|
|
549
|
+
}
|
|
492
550
|
if (entry) {
|
|
493
551
|
const head = backlog_head + 1
|
|
494
|
-
if (head > 1024 && head * 2 > backlog.length)
|
|
495
|
-
|
|
552
|
+
if (head > 1024 && head * 2 > backlog.length) {
|
|
553
|
+
record.backlog = backlog.slice(head)
|
|
554
|
+
} else if (head < backlog.length) {
|
|
496
555
|
record.backlog = backlog
|
|
497
556
|
record.backlog_head = head
|
|
498
557
|
}
|
|
499
558
|
record.retrigger = retrigger
|
|
500
|
-
if (entry.skipped)
|
|
501
|
-
|
|
559
|
+
if (entry.skipped) {
|
|
560
|
+
settle(c, name, "skipped", void 0)
|
|
561
|
+
} else {
|
|
562
|
+
launch(c, record, entry.args)
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
for (const touched_name of touched) {
|
|
566
|
+
try_start(c, touched_name)
|
|
502
567
|
}
|
|
503
|
-
for (const touched_name of touched) try_start(c, touched_name)
|
|
504
568
|
}
|
|
505
569
|
/**
|
|
506
570
|
* @param {RunContext} c
|
|
@@ -509,14 +573,22 @@ function run_next(c, name) {
|
|
|
509
573
|
*/
|
|
510
574
|
export function same_args(c, record) {
|
|
511
575
|
const { args, backlog, backlog_head } = record
|
|
512
|
-
if (!args)
|
|
576
|
+
if (!args) {
|
|
577
|
+
return false
|
|
578
|
+
}
|
|
513
579
|
const { arrive, deps, options } = record.node
|
|
514
580
|
const head = backlog[backlog_head]
|
|
515
|
-
if (options.overlap == "queue" && head?.resume)
|
|
581
|
+
if (options.overlap == "queue" && head?.resume) {
|
|
582
|
+
return head.args === args
|
|
583
|
+
}
|
|
516
584
|
for (const [ index, dep ] of deps.entries()) {
|
|
517
585
|
if (arrive?.[dep] == "queue") {
|
|
518
|
-
if (record.queued?.get(dep)?.[0] !== args[index])
|
|
519
|
-
|
|
586
|
+
if (record.queued?.get(dep)?.[0] !== args[index]) {
|
|
587
|
+
return false
|
|
588
|
+
}
|
|
589
|
+
} else if (!settled_statuses.has(get_record(c, dep).status) || c.results[dep] !== args[index]) {
|
|
590
|
+
return false
|
|
591
|
+
}
|
|
520
592
|
}
|
|
521
593
|
return true
|
|
522
594
|
}
|
|
@@ -531,7 +603,9 @@ export function save_run(run_state) {
|
|
|
531
603
|
serial: run_state.serial,
|
|
532
604
|
waits: [ ...run_state.waits ]
|
|
533
605
|
}
|
|
534
|
-
if (run_state.delay != null)
|
|
606
|
+
if (run_state.delay != null) {
|
|
607
|
+
saved.delay = run_state.delay
|
|
608
|
+
}
|
|
535
609
|
return saved
|
|
536
610
|
}
|
|
537
611
|
/**
|
|
@@ -541,8 +615,12 @@ export function save_run(run_state) {
|
|
|
541
615
|
* @returns {void}
|
|
542
616
|
*/
|
|
543
617
|
export function set_status(c, record, status) {
|
|
544
|
-
if (active_statuses.has(record.status))
|
|
545
|
-
|
|
618
|
+
if (active_statuses.has(record.status)) {
|
|
619
|
+
c.active_count--
|
|
620
|
+
}
|
|
621
|
+
if (active_statuses.has(status)) {
|
|
622
|
+
c.active_count++
|
|
623
|
+
}
|
|
546
624
|
record.status = status
|
|
547
625
|
c.version++
|
|
548
626
|
}
|
|
@@ -555,22 +633,28 @@ export function set_status(c, record, status) {
|
|
|
555
633
|
* @returns {void}
|
|
556
634
|
*/
|
|
557
635
|
export function settle(c, name, status, value, cancelled) {
|
|
558
|
-
if (c.room_waiters.length)
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
636
|
+
if (c.room_waiters.length) {
|
|
637
|
+
defer(c, wake_room.bind(void 0, c))
|
|
638
|
+
}
|
|
639
|
+
if (c.trace && status == "skipped" && !cancelled) {
|
|
640
|
+
emit(
|
|
641
|
+
c,
|
|
642
|
+
{
|
|
643
|
+
attempt: 0,
|
|
644
|
+
index: c.item_index,
|
|
645
|
+
node: name,
|
|
646
|
+
time: Date.now(),
|
|
647
|
+
type: "skip"
|
|
648
|
+
}
|
|
649
|
+
)
|
|
650
|
+
}
|
|
569
651
|
const record = get_record(c, name)
|
|
570
652
|
clearTimeout(record.timer)
|
|
571
653
|
record.controller = void 0
|
|
572
654
|
set_status(c, record, status)
|
|
573
|
-
if (record.node.kind == "input")
|
|
655
|
+
if (record.node.kind == "input") {
|
|
656
|
+
record.buffer = void 0
|
|
657
|
+
}
|
|
574
658
|
if (status == "done") {
|
|
575
659
|
record.result = value
|
|
576
660
|
c.results[name] = value
|
|
@@ -589,35 +673,56 @@ export function settle(c, name, status, value, cancelled) {
|
|
|
589
673
|
let more = false
|
|
590
674
|
if (record.queued) {
|
|
591
675
|
for (const waiting of record.queued.values()) {
|
|
592
|
-
if (waiting.length > 1)
|
|
676
|
+
if (waiting.length > 1) {
|
|
677
|
+
more = true
|
|
678
|
+
}
|
|
593
679
|
}
|
|
594
680
|
record.holding = status == "failed" && !more && !!record.args
|
|
595
681
|
if (!record.holding) {
|
|
596
|
-
for (const waiting of record.queued.values())
|
|
682
|
+
for (const waiting of record.queued.values()) {
|
|
683
|
+
waiting.shift()
|
|
684
|
+
}
|
|
597
685
|
}
|
|
598
686
|
}
|
|
599
|
-
if (status == "done")
|
|
687
|
+
if (status == "done") {
|
|
688
|
+
c.streams.get(name)?.send(value)
|
|
689
|
+
}
|
|
600
690
|
if (status == "done" && !record.abandoned) {
|
|
601
691
|
for (const dependent of record.node.queuers) {
|
|
602
692
|
const target = get_record(c, dependent)
|
|
603
693
|
target.queued ??= new Map()
|
|
604
694
|
if (target.holding) {
|
|
605
695
|
target.holding = false
|
|
606
|
-
for (const waiting of target.queued.values())
|
|
696
|
+
for (const waiting of target.queued.values()) {
|
|
697
|
+
waiting.shift()
|
|
698
|
+
}
|
|
607
699
|
}
|
|
608
700
|
const waiting = target.queued.get(name) ?? []
|
|
609
701
|
waiting.push(value)
|
|
610
702
|
const in_use = active_statuses.has(target.status) || target.fatal ? 1 : 0
|
|
611
|
-
if (waiting.length - in_use > (target.node.options.limit ?? Infinity))
|
|
703
|
+
if (waiting.length - in_use > (target.node.options.limit ?? Infinity)) {
|
|
704
|
+
waiting.splice(in_use, 1)
|
|
705
|
+
}
|
|
612
706
|
target.queued.set(name, waiting)
|
|
613
|
-
if (settled_statuses.has(target.status) && c.run_status == "running")
|
|
707
|
+
if (settled_statuses.has(target.status) && c.run_status == "running") {
|
|
708
|
+
defer(c, () => run_next(c, dependent))
|
|
709
|
+
}
|
|
614
710
|
}
|
|
615
711
|
}
|
|
616
|
-
for (const dependent of record.node.dependents)
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
if (
|
|
620
|
-
|
|
712
|
+
for (const dependent of record.node.dependents) {
|
|
713
|
+
try_start(c, dependent)
|
|
714
|
+
}
|
|
715
|
+
if (status == "done" && !record.abandoned) {
|
|
716
|
+
follow_edge(c, name, value)
|
|
717
|
+
} else {
|
|
718
|
+
kill_transitions(c, name)
|
|
719
|
+
}
|
|
720
|
+
if (c.run_status != "running") {
|
|
721
|
+
return
|
|
722
|
+
}
|
|
723
|
+
if (has_next || more) {
|
|
724
|
+
defer(c, () => run_next(c, name))
|
|
725
|
+
}
|
|
621
726
|
drain(c)
|
|
622
727
|
schedule(c)
|
|
623
728
|
}
|
|
@@ -647,8 +752,12 @@ export async function start(c, name) {
|
|
|
647
752
|
const outcome = record.node.each
|
|
648
753
|
? await run_each(c, record, token)
|
|
649
754
|
: await run_single(c, record, token)
|
|
650
|
-
if (token != record.token && outcome.kind == "done" && !is_sentinel(outcome.value))
|
|
651
|
-
|
|
755
|
+
if (token != record.token && outcome.kind == "done" && !is_sentinel(outcome.value)) {
|
|
756
|
+
discard(record, outcome.value)
|
|
757
|
+
}
|
|
758
|
+
if (token != record.token || outcome.kind == "stale") {
|
|
759
|
+
return
|
|
760
|
+
}
|
|
652
761
|
release(c, record)
|
|
653
762
|
if (outcome.kind == "error") {
|
|
654
763
|
drain(c)
|
|
@@ -659,9 +768,13 @@ export async function start(c, name) {
|
|
|
659
768
|
!!outcome.items,
|
|
660
769
|
outcome.index
|
|
661
770
|
)
|
|
662
|
-
} else
|
|
771
|
+
} else {
|
|
772
|
+
apply_value(c, name, outcome.value)
|
|
773
|
+
}
|
|
663
774
|
} catch (error) {
|
|
664
|
-
if (token != record.token || c.run_status != "running")
|
|
775
|
+
if (token != record.token || c.run_status != "running") {
|
|
776
|
+
return
|
|
777
|
+
}
|
|
665
778
|
release(c, record)
|
|
666
779
|
fail(c, name, error)
|
|
667
780
|
}
|
|
@@ -687,7 +800,9 @@ export function stop_all(c, status, reason, keep) {
|
|
|
687
800
|
]
|
|
688
801
|
record.backlog_head = 0
|
|
689
802
|
} else if (!holds) {
|
|
690
|
-
if (record.backlog[record.backlog_head]?.resume)
|
|
803
|
+
if (record.backlog[record.backlog_head]?.resume) {
|
|
804
|
+
forget_runs(record)
|
|
805
|
+
}
|
|
691
806
|
record.backlog = []
|
|
692
807
|
record.backlog_head = 0
|
|
693
808
|
}
|
|
@@ -719,7 +834,9 @@ export function stop_record(c, record, reason) {
|
|
|
719
834
|
record.controller = void 0
|
|
720
835
|
} else if (record.status == "pending") {
|
|
721
836
|
const index = c.queue.indexOf(record.node.name)
|
|
722
|
-
if (index >= 0)
|
|
837
|
+
if (index >= 0) {
|
|
838
|
+
c.queue.splice(index, 1)
|
|
839
|
+
}
|
|
723
840
|
}
|
|
724
841
|
}
|
|
725
842
|
/**
|
|
@@ -732,13 +849,19 @@ export function try_start(c, name) {
|
|
|
732
849
|
c,
|
|
733
850
|
() => {
|
|
734
851
|
const record = get_record(c, name)
|
|
735
|
-
if (!record.activated || c.run_status != "running")
|
|
852
|
+
if (!record.activated || c.run_status != "running") {
|
|
853
|
+
return
|
|
854
|
+
}
|
|
736
855
|
const overlapping = record.retrigger && (active_statuses.has(record.status) || holds_backlog(record))
|
|
737
|
-
if (record.status != "idle" && !overlapping)
|
|
856
|
+
if (record.status != "idle" && !overlapping) {
|
|
857
|
+
return
|
|
858
|
+
}
|
|
738
859
|
const { dependents, deps, options } = record.node
|
|
739
860
|
if (options.release && dependents.length && !dependents.some(
|
|
740
861
|
dependent => needs(c, dependent)
|
|
741
|
-
))
|
|
862
|
+
)) {
|
|
863
|
+
return
|
|
864
|
+
}
|
|
742
865
|
const join = options.join ?? "all"
|
|
743
866
|
let done = 0
|
|
744
867
|
let resources = 0
|
|
@@ -747,7 +870,9 @@ export function try_start(c, name) {
|
|
|
747
870
|
const { arrive } = record.node
|
|
748
871
|
for (const dep of deps) {
|
|
749
872
|
const dep_record = get_record(c, dep)
|
|
750
|
-
if (dep_record.fatal)
|
|
873
|
+
if (dep_record.fatal) {
|
|
874
|
+
return
|
|
875
|
+
}
|
|
751
876
|
if (dep_record.status == "idle" && dep_record.node.options.release) {
|
|
752
877
|
resources++
|
|
753
878
|
continue
|
|
@@ -759,20 +884,32 @@ export function try_start(c, name) {
|
|
|
759
884
|
}
|
|
760
885
|
continue
|
|
761
886
|
}
|
|
762
|
-
if (dep_record.status == "done")
|
|
763
|
-
|
|
764
|
-
|
|
887
|
+
if (dep_record.status == "done") {
|
|
888
|
+
done++
|
|
889
|
+
}
|
|
890
|
+
if (dep_record.status == "skipped") {
|
|
891
|
+
skipped++
|
|
892
|
+
}
|
|
893
|
+
if (settled_statuses.has(dep_record.status)) {
|
|
894
|
+
settled++
|
|
895
|
+
}
|
|
765
896
|
}
|
|
766
897
|
if (resources && !(join == "race" && done)) {
|
|
767
|
-
if (settled + resources < deps.length)
|
|
898
|
+
if (settled + resources < deps.length) {
|
|
899
|
+
return
|
|
900
|
+
}
|
|
768
901
|
if (join != "all" || !skipped) {
|
|
769
902
|
for (const dep of deps) {
|
|
770
903
|
const dep_record = get_record(c, dep)
|
|
771
|
-
if (dep_record.status == "idle" && dep_record.node.options.release)
|
|
904
|
+
if (dep_record.status == "idle" && dep_record.node.options.release) {
|
|
905
|
+
try_start(c, dep)
|
|
906
|
+
}
|
|
772
907
|
}
|
|
773
908
|
return
|
|
774
909
|
}
|
|
775
|
-
} else if (join == "race" ? !done && settled < deps.length : settled < deps.length)
|
|
910
|
+
} else if (join == "race" ? !done && settled < deps.length : settled < deps.length) {
|
|
911
|
+
return
|
|
912
|
+
}
|
|
776
913
|
const is_skipped = !!deps.length && (join == "all" ? skipped > 0 : !done)
|
|
777
914
|
if (overlapping) {
|
|
778
915
|
record.retrigger = false
|
|
@@ -780,10 +917,15 @@ export function try_start(c, name) {
|
|
|
780
917
|
const overlap = options.overlap ?? "restart"
|
|
781
918
|
if (overlap == "restart") {
|
|
782
919
|
const touched = reset(c, name, true, true)
|
|
783
|
-
if (is_skipped)
|
|
784
|
-
|
|
920
|
+
if (is_skipped) {
|
|
921
|
+
settle(c, name, "skipped", void 0)
|
|
922
|
+
} else {
|
|
923
|
+
launch(c, record, args)
|
|
924
|
+
}
|
|
785
925
|
for (const touched_name of touched) {
|
|
786
|
-
if (touched_name != name)
|
|
926
|
+
if (touched_name != name) {
|
|
927
|
+
try_start(c, touched_name)
|
|
928
|
+
}
|
|
787
929
|
}
|
|
788
930
|
return
|
|
789
931
|
}
|
|
@@ -797,7 +939,9 @@ export function try_start(c, name) {
|
|
|
797
939
|
const held = record.backlog[record.backlog_head]?.resume ? 1 : 0
|
|
798
940
|
if (record.backlog.length - record.backlog_head - held > limit) {
|
|
799
941
|
record.dropped++
|
|
800
|
-
if (held)
|
|
942
|
+
if (held) {
|
|
943
|
+
record.backlog[record.backlog_head + 1] = /** @type {BacklogEntry} */(record.backlog[record.backlog_head])/**/
|
|
944
|
+
}/**/
|
|
801
945
|
record.backlog_head++
|
|
802
946
|
if (record.backlog_head * 2 > record.backlog.length) {
|
|
803
947
|
record.backlog = record.backlog.slice(record.backlog_head)
|
|
@@ -805,7 +949,9 @@ export function try_start(c, name) {
|
|
|
805
949
|
}
|
|
806
950
|
}
|
|
807
951
|
}
|
|
808
|
-
if (!active_statuses.has(record.status))
|
|
952
|
+
if (!active_statuses.has(record.status)) {
|
|
953
|
+
run_next(c, name)
|
|
954
|
+
}
|
|
809
955
|
return
|
|
810
956
|
}
|
|
811
957
|
if (record.backlog.length > record.backlog_head) {
|
|
@@ -816,7 +962,9 @@ export function try_start(c, name) {
|
|
|
816
962
|
settle(c, name, "skipped", void 0)
|
|
817
963
|
return
|
|
818
964
|
}
|
|
819
|
-
if (launch(c, record, values_for(c, record)) && join == "race" && c.run_status == "running")
|
|
965
|
+
if (launch(c, record, values_for(c, record)) && join == "race" && c.run_status == "running") {
|
|
966
|
+
abandon(c, deps, name)
|
|
967
|
+
}
|
|
820
968
|
}
|
|
821
969
|
)
|
|
822
970
|
}
|
|
@@ -827,7 +975,9 @@ export function try_start(c, name) {
|
|
|
827
975
|
*/
|
|
828
976
|
function values_for(c, record) {
|
|
829
977
|
const { arrive, deps } = record.node
|
|
830
|
-
if (!arrive)
|
|
978
|
+
if (!arrive) {
|
|
979
|
+
return deps.map(dep => c.results[dep])
|
|
980
|
+
}
|
|
831
981
|
return deps.map(
|
|
832
982
|
dep => arrive[dep] == "queue"
|
|
833
983
|
? record.queued?.get(dep)?.[0]
|