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.
Files changed (70) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +1 -1
  3. package/docs/http.md +1 -1
  4. package/docs/reference.md +4 -2
  5. package/docs/tasks.md +19 -2
  6. package/package.json +4 -5
  7. package/public.d.ts +112 -0
  8. package/src/attempt.js +17 -7
  9. package/src/durable/context.js +107 -64
  10. package/src/durable/error.js +39 -15
  11. package/src/durable/index.js +18 -10
  12. package/src/durable/journal.js +29 -14
  13. package/src/durable/json.js +26 -9
  14. package/src/durable/lease.js +15 -5
  15. package/src/durable/persist.js +60 -22
  16. package/src/durable/run.js +103 -41
  17. package/src/durable/send.js +30 -13
  18. package/src/durable/serve.js +30 -24
  19. package/src/durable/state.js +28 -13
  20. package/src/durable/store.js +19 -10
  21. package/src/durable/watch.js +31 -11
  22. package/src/errors.js +9 -3
  23. package/src/flow/attempts.js +49 -29
  24. package/src/flow/builder.js +260 -161
  25. package/src/flow/compile.js +86 -66
  26. package/src/flow/graph.js +108 -42
  27. package/src/flow/index.js +13 -7
  28. package/src/flow/items.js +79 -46
  29. package/src/flow/nodes.js +267 -117
  30. package/src/flow/refs.js +27 -13
  31. package/src/flow/resources.js +9 -3
  32. package/src/flow/run.js +287 -114
  33. package/src/flow/streams.js +44 -19
  34. package/src/flow/subflows.js +93 -53
  35. package/src/http/config.js +11 -5
  36. package/src/http/index.js +25 -14
  37. package/src/http/refresh.js +29 -12
  38. package/src/http/request.js +246 -151
  39. package/src/http/response.js +105 -50
  40. package/src/http/retry.js +52 -27
  41. package/src/http/socket.js +220 -172
  42. package/src/http/sse.js +113 -74
  43. package/src/http/throttle.js +9 -4
  44. package/src/http/url.js +58 -35
  45. package/src/http/xhr.js +29 -24
  46. package/src/index.js +1 -0
  47. package/src/key.js +3 -5
  48. package/src/limiter.js +146 -65
  49. package/src/offload.js +116 -85
  50. package/src/offload_module.js +594 -0
  51. package/src/options.js +8 -4
  52. package/src/redial.js +129 -0
  53. package/src/signal.js +14 -4
  54. package/src/stream.js +353 -198
  55. package/types/attempt.d.ts.map +1 -1
  56. package/types/durable/index.d.ts.map +1 -1
  57. package/types/durable/state.d.ts.map +1 -1
  58. package/types/durable/store.d.ts.map +1 -1
  59. package/types/errors.d.ts.map +1 -1
  60. package/types/http/index.d.ts.map +1 -1
  61. package/types/index.d.ts +1 -0
  62. package/types/index.d.ts.map +1 -1
  63. package/types/limiter.d.ts +5 -1
  64. package/types/limiter.d.ts.map +1 -1
  65. package/types/offload.d.ts +2 -16
  66. package/types/offload.d.ts.map +1 -1
  67. package/types/redial.d.ts +28 -0
  68. package/types/redial.d.ts.map +1 -0
  69. package/types/stream.d.ts +2 -0
  70. package/types/stream.d.ts.map +1 -1
package/src/flow/run.js CHANGED
@@ -51,14 +51,22 @@ export function begin(c) {
51
51
  clear_record(c, record)
52
52
  touched.add(record.node.name)
53
53
  } else {
54
- for (const name of reset(c, record.node.name, true)) touched.add(name)
54
+ for (const name of reset(c, record.node.name, true)) {
55
+ touched.add(name)
56
+ }
55
57
  }
56
58
  }
57
- for (const record of released) record.released = void 0
58
- for (const name of touched) get_record(c, name).released = void 0
59
+ for (const record of released) {
60
+ record.released = void 0
61
+ }
62
+ for (const name of touched) {
63
+ get_record(c, name).released = void 0
64
+ }
59
65
  if (c.cycle.settled) {
60
66
  c.cycle = create_cycle()
61
- if (c.watched || c.streaming && c.observed) c.cycle.promise.catch(noop)
67
+ if (c.watched || c.streaming && c.observed) {
68
+ c.cycle.promise.catch(noop)
69
+ }
62
70
  c.run_status = "running"
63
71
  c.steps = 0
64
72
  start_pumps(c)
@@ -67,17 +75,23 @@ export function begin(c) {
67
75
  c.run_options.signal
68
76
  )
69
77
  for (const record of c.records.values()) {
70
- if (record.status == "cancelled") prepare_restart(c, record)
78
+ if (record.status == "cancelled") {
79
+ prepare_restart(c, record)
80
+ }
71
81
  }
72
82
  }
73
- for (const name of touched) try_start(c, name)
83
+ for (const name of touched) {
84
+ try_start(c, name)
85
+ }
74
86
  }
75
87
  /**
76
88
  * @param {RunContext} c
77
89
  * @returns {void}
78
90
  */
79
91
  function check_complete(c) {
80
- if (c.active_count || c.run_status != "running" || c.cycle.settled || c.releasing) return
92
+ if (c.active_count || c.run_status != "running" || c.cycle.settled || c.releasing) {
93
+ return
94
+ }
81
95
  /** @type {NodeRecord | undefined} */
82
96
  let fatal
83
97
  for (const record of c.records.values()) {
@@ -92,7 +106,9 @@ function check_complete(c) {
92
106
  c.errors[fatal.node.name]
93
107
  )
94
108
  : void 0
95
- if (failure) release_all(c, failure)
109
+ if (failure) {
110
+ release_all(c, failure)
111
+ }
96
112
  const holding = [ ...c.records.values() ].filter(
97
113
  record => record.node.options.release && record.status == "done" && !record.released
98
114
  )
@@ -115,7 +131,9 @@ function check_complete(c) {
115
131
  c.releasing = false
116
132
  for (const [ index, outcome ] of outcomes.entries()) {
117
133
  const record = /** @type {NodeRecord} */(holding[index])/**/
118
- if (outcome.status == "fulfilled" || record.released?.error !== void 0 || record.status != "done") continue
134
+ if (outcome.status == "fulfilled" || record.released?.error !== void 0 || record.status != "done") {
135
+ continue
136
+ }
119
137
  record.released = { error: outcome.reason }
120
138
  c.errors[record.node.name] = outcome.reason
121
139
  record.fatal = true
@@ -150,9 +168,14 @@ export function close_cycle(c, error, value) {
150
168
  c.cycle.settled = true
151
169
  c.unlink_signal()
152
170
  c.unlink_signal = noop
153
- if (error instanceof CancelError) c.cycle.promise.catch(noop)
154
- if (error) c.cycle.reject(error)
155
- else c.cycle.resolve(value)
171
+ if (error instanceof CancelError) {
172
+ c.cycle.promise.catch(noop)
173
+ }
174
+ if (error) {
175
+ c.cycle.reject(error)
176
+ } else {
177
+ c.cycle.resolve(value)
178
+ }
156
179
  schedule(c)
157
180
  }
158
181
  /**
@@ -176,10 +199,14 @@ function create_cycle() {
176
199
  */
177
200
  export function defer(c, job) {
178
201
  c.jobs.push(job)
179
- if (c.flushing) return
202
+ if (c.flushing) {
203
+ return
204
+ }
180
205
  c.flushing = true
181
206
  try {
182
- for (const queued of c.jobs) queued()
207
+ for (const queued of c.jobs) {
208
+ queued()
209
+ }
183
210
  } finally {
184
211
  c.jobs.length = 0
185
212
  c.flushing = false
@@ -191,8 +218,10 @@ export function defer(c, job) {
191
218
  */
192
219
  export function drain(c) {
193
220
  while (c.running < c.concurrency && c.queue.length) {
194
- const name = /** @type {string} */(c.queue.shift())/**/
195
- if (get_record(c, name).status == "pending") start(c, name)
221
+ start(
222
+ c,
223
+ /** @type {string} */(c.queue.shift())/**/
224
+ )
196
225
  }
197
226
  }
198
227
  /**
@@ -206,7 +235,9 @@ function get_statuses(c) {
206
235
  statuses[name] = record.status == "running" && record.sub_waiting && !record.sub_running && !record.delaying
207
236
  ? "waiting"
208
237
  : record.status
209
- if (record.status == "done" || record.status == "skipped") continue
238
+ if (record.status == "done" || record.status == "skipped") {
239
+ continue
240
+ }
210
241
  for (const [ key, sub_run ] of record.sub_runs) {
211
242
  const prefix = key ? name + "." + key : name
212
243
  for (const [ sub_name, status ] of Object.entries(sub_run.nodes)) {
@@ -221,10 +252,14 @@ function get_statuses(c) {
221
252
  * @returns {void}
222
253
  */
223
254
  function notify(c) {
224
- if (!c.waiters.length && !c.run_options[ON_CHANGE] && !c.subscribers.size) return
255
+ if (!c.waiters.length && !c.run_options[ON_CHANGE] && !c.subscribers.size) {
256
+ return
257
+ }
225
258
  const status = c.run.status
226
259
  if (status != "running") {
227
- for (const resolve of c.waiters.splice(0)) resolve()
260
+ for (const resolve of c.waiters.splice(0)) {
261
+ resolve()
262
+ }
228
263
  }
229
264
  report(c, status)
230
265
  publish(c)
@@ -234,7 +269,9 @@ function notify(c) {
234
269
  * @returns {void}
235
270
  */
236
271
  export function publish(c) {
237
- if (!c.subscribers.size || c.notified_version == c.version) return
272
+ if (!c.subscribers.size || c.notified_version == c.version) {
273
+ return
274
+ }
238
275
  c.notified_version = c.version
239
276
  for (const listener of [ ...c.subscribers ]) {
240
277
  try {
@@ -249,9 +286,13 @@ export function publish(c) {
249
286
  */
250
287
  export function report(c, status) {
251
288
  const on_change = c.run_options[ON_CHANGE]
252
- if (!on_change) return
289
+ if (!on_change) {
290
+ return
291
+ }
253
292
  const current = status ?? c.run.status
254
- if (current == c.reported_status && c.reported_version == c.version) return
293
+ if (current == c.reported_status && c.reported_version == c.version) {
294
+ return
295
+ }
255
296
  c.reported_status = current
256
297
  c.reported_version = c.version
257
298
  on_change(current)
@@ -263,16 +304,24 @@ export function report(c, status) {
263
304
  */
264
305
  function retry_failed(c, only_fatal) {
265
306
  begin(c)
266
- if (c.run_status != "running") return
307
+ if (c.run_status != "running") {
308
+ return
309
+ }
267
310
  /** @type {[string, ResumePlan, BacklogEntry[]][]} */
268
311
  const plans = []
269
312
  for (const [ name, record ] of c.records) {
270
- if (only_fatal && !record.fatal) continue
313
+ if (only_fatal && !record.fatal) {
314
+ continue
315
+ }
271
316
  const has_failed_items = !!(record.items ?? record.resume_items)?.some(item => item?.failed)
272
- if (record.status != "failed" && !(record.status == "done" && (has_failed_items || failed_sub_keys(record).length))) continue
317
+ if (record.status != "failed" && !(record.status == "done" && (has_failed_items || failed_sub_keys(record).length))) {
318
+ continue
319
+ }
273
320
  const plan = plan_retry(record)
274
321
  if (record.args && !same_args(c, record)) {
275
- if (record.status == "failed") plan.items = void 0
322
+ if (record.status == "failed") {
323
+ plan.items = void 0
324
+ }
276
325
  plan.runs = void 0
277
326
  plan.subs = void 0
278
327
  }
@@ -288,16 +337,22 @@ function retry_failed(c, only_fatal) {
288
337
  const reached = new Set()
289
338
  for (const [ name ] of plans) {
290
339
  for (const reset_name of reset(c, name, true, true)) {
291
- if (reset_name != name) reached.add(reset_name)
340
+ if (reset_name != name) {
341
+ reached.add(reset_name)
342
+ }
292
343
  }
293
344
  }
294
345
  for (const [ name, plan, backlog ] of plans) {
295
- if (reached.has(name)) continue
346
+ if (reached.has(name)) {
347
+ continue
348
+ }
296
349
  const record = get_record(c, name)
297
350
  plan_resume(record, plan)
298
351
  record.backlog = backlog
299
352
  }
300
- for (const node_name of c.records.keys()) try_start(c, node_name)
353
+ for (const node_name of c.records.keys()) {
354
+ try_start(c, node_name)
355
+ }
301
356
  drain(c)
302
357
  schedule(c)
303
358
  }
@@ -307,14 +362,18 @@ function retry_failed(c, only_fatal) {
307
362
  * @returns {unknown}
308
363
  */
309
364
  function save_error(error, depth = 0) {
310
- if (!(error instanceof Error)) return error
365
+ if (!(error instanceof Error)) {
366
+ return error
367
+ }
311
368
  /** @type {Record<string, unknown>} */
312
369
  const saved = {
313
370
  ...error,
314
371
  message: error.message,
315
372
  name: error.name
316
373
  }
317
- if (error.cause !== void 0 && depth < 8) saved["cause"] = save_error(error.cause, depth + 1)
374
+ if (error.cause !== void 0 && depth < 8) {
375
+ saved["cause"] = save_error(error.cause, depth + 1)
376
+ }
318
377
  return saved
319
378
  }
320
379
  /**
@@ -322,7 +381,9 @@ function save_error(error, depth = 0) {
322
381
  * @returns {void}
323
382
  */
324
383
  export function schedule(c) {
325
- if (c.scheduled) return
384
+ if (c.scheduled) {
385
+ return
386
+ }
326
387
  c.scheduled = true
327
388
  queueMicrotask(
328
389
  () => {
@@ -353,20 +414,28 @@ export function start_run(
353
414
  const { edges, incoming } = program
354
415
  c.edges = edges
355
416
  c.incoming = incoming
356
- if (run_options.id != null && !(typeof run_options.id == "string" && run_options.id)) throw TypeError(
357
- "The id of a run must be a non-empty string"
358
- )
417
+ if (run_options.id != null && !(typeof run_options.id == "string" && run_options.id)) {
418
+ throw TypeError(
419
+ "The id of a run must be a non-empty string"
420
+ )
421
+ }
359
422
  const { snapshot } = run_options
360
423
  if (snapshot != null) {
361
- if (typeof snapshot != "object" || !snapshot.nodes || typeof snapshot.nodes != "object") throw TypeError(
362
- "Invalid flow snapshot: pass the result of run.snapshot()"
363
- )
364
- if (snapshot.version !== 1) throw TypeError(
365
- `Unknown flow snapshot version ${String(snapshot.version)}: pass the result of run.snapshot()`
366
- )
367
- if (run_options.id != null && snapshot.id != null && snapshot.id !== run_options.id) throw TypeError(
368
- `The id "${run_options.id}" of the run is not the id "${snapshot.id}" of its snapshot`
369
- )
424
+ if (typeof snapshot != "object" || !snapshot.nodes || typeof snapshot.nodes != "object") {
425
+ throw TypeError(
426
+ "Invalid flow snapshot: pass the result of run.snapshot()"
427
+ )
428
+ }
429
+ if (snapshot.version !== 1) {
430
+ throw TypeError(
431
+ `Unknown flow snapshot version ${String(snapshot.version)}: pass the result of run.snapshot()`
432
+ )
433
+ }
434
+ if (run_options.id != null && snapshot.id != null && snapshot.id !== run_options.id) {
435
+ throw TypeError(
436
+ `The id "${run_options.id}" of the run is not the id "${snapshot.id}" of its snapshot`
437
+ )
438
+ }
370
439
  }
371
440
  const run_id = snapshot?.id ?? run_options.id ?? run_options[RUN_ID] ?? random_key()
372
441
  c.run_id = run_id
@@ -498,12 +567,16 @@ export function start_run(
498
567
  if (snapshot != null) {
499
568
  for (const [ name, data ] of Object.entries(snapshot.nodes)) {
500
569
  const record = records.get(name)
501
- if (!record) throw Error(
502
- `The snapshot has unknown flow node "${name}"`
503
- )
570
+ if (!record) {
571
+ throw Error(
572
+ `The snapshot has unknown flow node "${name}"`
573
+ )
574
+ }
504
575
  record.abandoned = !!data.abandoned
505
576
  record.activated = data.activated
506
- for (const source of data.activators ?? (data.activated && incoming.has(name) ? [ "*" ] : [])) record.activators.add(source)
577
+ for (const source of data.activators ?? (data.activated && incoming.has(name) ? [ "*" ] : [])) {
578
+ record.activators.add(source)
579
+ }
507
580
  record.backlog = data.backlog ?? []
508
581
  record.backlog_head = 0
509
582
  record.buffer = data.buffer
@@ -517,45 +590,61 @@ export function start_run(
517
590
  )
518
591
  }
519
592
  record.resume_subs = data.subs
520
- if (data.sends) record.sends = new Map(Object.entries(data.sends))
593
+ if (data.sends) {
594
+ record.sends = new Map(Object.entries(data.sends))
595
+ }
521
596
  record.resume_runs = data.runs
522
597
  record.resume_deadline = data.deadline
523
598
  record.serial = data.serial ?? 0
524
599
  record.fatal = data.status == "failed" && !!data.fatal
525
600
  record.holding = data.status == "failed" && !data.fatal && !!data.queued
526
- if (record.fatal) resumes_failure = true
601
+ if (record.fatal) {
602
+ resumes_failure = true
603
+ }
527
604
  set_status(c, record, data.status)
528
605
  if (data.status == "done") {
529
606
  record.items = data.items
530
607
  record.result = data.items ? data.items.map(item => item?.value) : data.result
531
608
  results[name] = record.result
532
- } else record.resume_items = data.items
609
+ } else {
610
+ record.resume_items = data.items
611
+ }
533
612
  }
534
613
  Object.assign(errors, snapshot.errors)
535
614
  for (const record of records.values()) {
536
615
  const { arrive, deps } = record.node
537
616
  if (record.backlog.length && deps.some(
538
617
  dep => arrive?.[dep] != "queue" && !settled_statuses.has(get_record(c, dep).status)
539
- )) record.retrigger = true
618
+ )) {
619
+ record.retrigger = true
620
+ }
540
621
  }
541
622
  }
542
623
  /** @type {FlowRunner} */
543
624
  const run = {
544
625
  cancel(reason) {
545
626
  stop_pumps(c)
546
- for (const source of streams.values()) source.close()
627
+ for (const source of streams.values()) {
628
+ source.close()
629
+ }
547
630
  streams.clear()
548
- if (c.run_status != "running") return
631
+ if (c.run_status != "running") {
632
+ return
633
+ }
549
634
  const error = new CancelError(
550
635
  reason ?? "The flow was cancelled"
551
636
  )
552
637
  release_all(c, error)
553
638
  stop_all(c, "cancelled", error)
554
639
  c.run_status = "cancelled"
555
- if (!c.cycle.settled) close_cycle(c, error, void 0)
640
+ if (!c.cycle.settled) {
641
+ close_cycle(c, error, void 0)
642
+ }
556
643
  },
557
644
  get errors() {
558
- if (errors_cache && errors_version == c.version) return errors_cache
645
+ if (errors_cache && errors_version == c.version) {
646
+ return errors_cache
647
+ }
559
648
  /** @type {Record<string, unknown>} */
560
649
  const all = { ...errors }
561
650
  for (const [ name, record ] of records) {
@@ -571,7 +660,9 @@ export function start_run(
571
660
  ]
572
661
  )
573
662
  for (const [ key, sub_errors ] of subs) {
574
- for (const [ sub_key, error ] of Object.entries(sub_errors)) all[(key ? name + "." + key : name) + "." + sub_key] = error
663
+ for (const [ sub_key, error ] of Object.entries(sub_errors)) {
664
+ all[(key ? name + "." + key : name) + "." + sub_key] = error
665
+ }
575
666
  }
576
667
  }
577
668
  errors_cache = all
@@ -581,9 +672,15 @@ export function start_run(
581
672
  [STOP]: stop_pumps.bind(void 0, c),
582
673
  [FAILURES]() {
583
674
  for (const record of records.values()) {
584
- if (record.status == "failed" && !record.fatal) return true
585
- if ((record.items ?? record.resume_items)?.some(item => item?.failed)) return true
586
- if (failed_sub_keys(record).length) return true
675
+ if (record.status == "failed" && !record.fatal) {
676
+ return true
677
+ }
678
+ if ((record.items ?? record.resume_items)?.some(item => item?.failed)) {
679
+ return true
680
+ }
681
+ if (failed_sub_keys(record).length) {
682
+ return true
683
+ }
587
684
  }
588
685
  return false
589
686
  },
@@ -599,7 +696,9 @@ export function start_run(
599
696
  },
600
697
  idle() {
601
698
  watch(c)
602
- if (run.status != "running") return Promise.resolve()
699
+ if (run.status != "running") {
700
+ return Promise.resolve()
701
+ }
603
702
  return /** @type {Promise<void>} */(new Promise(
604
703
  resolve => waiters.push(() => resolve())
605
704
  ))/**/
@@ -618,7 +717,9 @@ export function start_run(
618
717
  }
619
718
  const record = get_record(c, name_or_throw(c, target))
620
719
  let queued = active_statuses.has(record.status) ? 1 : 0
621
- for (const waiting of record.queued?.values() ?? []) queued = Math.max(queued, waiting.length)
720
+ for (const waiting of record.queued?.values() ?? []) {
721
+ queued = Math.max(queued, waiting.length)
722
+ }
622
723
  return record.backlog.length - record.backlog_head + queued - (record.holding ? 1 : 0)
623
724
  },
624
725
  reload(target) {
@@ -629,15 +730,21 @@ export function start_run(
629
730
  }
630
731
  const name = target == null ? void 0 : name_or_throw(c, target)
631
732
  begin(c)
632
- if (c.run_status != "running") return
733
+ if (c.run_status != "running") {
734
+ return
735
+ }
633
736
  if (name == null) {
634
737
  for (const record of records.values()) {
635
738
  clear_record(c, record)
636
739
  record.activators.clear()
637
740
  record.activated = !incoming.has(record.node.name)
638
741
  }
639
- } else enter(c, [ name ], "*", true)
640
- for (const node_name of records.keys()) try_start(c, node_name)
742
+ } else {
743
+ enter(c, [ name ], "*", true)
744
+ }
745
+ for (const node_name of records.keys()) {
746
+ try_start(c, node_name)
747
+ }
641
748
  drain(c)
642
749
  schedule(c)
643
750
  },
@@ -658,41 +765,57 @@ export function start_run(
658
765
  }
659
766
  const name = name_or_throw(c, target)
660
767
  const record = get_record(c, name)
661
- if (record.node.kind != "input") throw Error(
662
- `Flow node "${name}" is not an input`
663
- )
768
+ if (record.node.kind != "input") {
769
+ throw Error(
770
+ `Flow node "${name}" is not an input`
771
+ )
772
+ }
664
773
  if (record.status == "waiting" && c.run_status == "running") {
665
774
  settle(c, name, "done", value)
666
775
  return
667
776
  }
668
- if (record.abandoned) return
777
+ if (record.abandoned) {
778
+ return
779
+ }
669
780
  record.buffer = { value }
670
781
  if (settled_statuses.has(record.status) || record.status == "cancelled") {
671
782
  begin(c)
672
- if (c.run_status != "running") return
783
+ if (c.run_status != "running") {
784
+ return
785
+ }
673
786
  enter(c, [ name ], "*")
674
- for (const node_name of records.keys()) try_start(c, node_name)
787
+ for (const node_name of records.keys()) {
788
+ try_start(c, node_name)
789
+ }
675
790
  drain(c)
676
791
  schedule(c)
677
792
  }
678
793
  },
679
794
  snapshot() {
680
- if (!run_options[ON_CHANGE]) check_snapshot_names(program, "")
795
+ if (!run_options[ON_CHANGE]) {
796
+ check_snapshot_names(program, "")
797
+ }
681
798
  /** @type {Record<string, SavedNode>} */
682
799
  const snapshot_nodes = {}
683
800
  /** @type {Set<string>} */
684
801
  const held = new Set()
685
802
  for (const [ name, record ] of records) {
686
- if (record.node.options.release && record.status == "done" && !record.released) held.add(name)
803
+ if (record.node.options.release && record.status == "done" && !record.released) {
804
+ held.add(name)
805
+ }
687
806
  }
688
807
  const redone = new Set(held)
689
808
  for (const name of redone) {
690
809
  for (const dependent of get_record(c, name).node.dependents) {
691
- if (get_record(c, dependent).status == "done") redone.add(dependent)
810
+ if (get_record(c, dependent).status == "done") {
811
+ redone.add(dependent)
812
+ }
692
813
  }
693
814
  }
694
815
  for (const [ name, record ] of records) {
695
- if (record.node.options.release && record.status == "done") redone.add(name)
816
+ if (record.node.options.release && record.status == "done") {
817
+ redone.add(name)
818
+ }
696
819
  }
697
820
  for (const [ name, record ] of records) {
698
821
  const { status } = record
@@ -702,22 +825,42 @@ export function start_run(
702
825
  activated: record.activated,
703
826
  status: is_kept ? /** @type {"done" | "failed" | "skipped"} */(status)/**/ : "idle"
704
827
  }
705
- if (record.abandoned) data.abandoned = true
706
- if (record.activators.size) data.activators = [ ...record.activators ]
707
- if (record.fatal && status == "failed") data.fatal = true
708
- if (status == "done") data.result = record.result
709
- if (record.previous !== void 0) data.previous = record.previous
710
- if (record.buffer) data.buffer = { value: record.buffer.value }
711
- if (record.sends?.size) data.sends = Object.fromEntries(record.sends)
712
- if (status == "waiting" && record.deadline != null) data.deadline = record.deadline
713
- if (record.serial) data.serial = record.serial
828
+ if (record.abandoned) {
829
+ data.abandoned = true
830
+ }
831
+ if (record.activators.size) {
832
+ data.activators = [ ...record.activators ]
833
+ }
834
+ if (record.fatal && status == "failed") {
835
+ data.fatal = true
836
+ }
837
+ if (status == "done") {
838
+ data.result = record.result
839
+ }
840
+ if (record.previous !== void 0) {
841
+ data.previous = record.previous
842
+ }
843
+ if (record.buffer) {
844
+ data.buffer = { value: record.buffer.value }
845
+ }
846
+ if (record.sends?.size) {
847
+ data.sends = Object.fromEntries(record.sends)
848
+ }
849
+ if (status == "waiting" && record.deadline != null) {
850
+ data.deadline = record.deadline
851
+ }
852
+ if (record.serial) {
853
+ data.serial = record.serial
854
+ }
714
855
  const is_stale = status == "done"
715
856
  ? redone.has(name)
716
857
  : !(record.node.options.overlap == "queue" && active_statuses.has(status)) && !!record.args && (!same_args(c, record) || record.node.deps.some(dep => redone.has(dep)))
717
858
  const is_moved = is_stale || status == "done" && !!(record.runs.size || record.resume_runs || record.sub_runs.size || record.resume_subs) && !!record.args && !same_args(c, record)
718
859
  if (!is_moved && (record.runs.size || record.resume_runs)) {
719
860
  data.runs = { ...record.resume_runs }
720
- for (const [ unit, run_state ] of record.runs) data.runs[unit] = save_run(run_state)
861
+ for (const [ unit, run_state ] of record.runs) {
862
+ data.runs[unit] = save_run(run_state)
863
+ }
721
864
  } else if (held.has(name) && same_args(c, record) && !record.node.deps.some(dep => redone.has(dep))) {
722
865
  data.runs = {
723
866
  "": {
@@ -728,7 +871,10 @@ export function start_run(
728
871
  }
729
872
  }
730
873
  for (const [ dep, values ] of record.queued ?? []) {
731
- if (values.length) (data.queued ??= {})[dep] = [ ...values ]
874
+ if (values.length) {
875
+ const queued = data.queued ??= {}
876
+ queued[dep] = [ ...values ]
877
+ }
732
878
  }
733
879
  const in_flight = record.node.options.overlap == "queue" && active_statuses.has(status) && record.args
734
880
  const backlog = in_flight
@@ -741,27 +887,34 @@ export function start_run(
741
887
  ...record.backlog.slice(record.backlog_head)
742
888
  ]
743
889
  : record.backlog.slice(record.backlog_head)
744
- if (backlog.length) data.backlog = backlog.map(
745
- entry => entry.resume
746
- ? {
747
- args: [ ...entry.args ],
748
- resume: true,
749
- skipped: entry.skipped
750
- }
751
- : {
752
- args: [ ...entry.args ],
753
- skipped: entry.skipped
754
- }
755
- )
890
+ if (backlog.length) {
891
+ data.backlog = backlog.map(
892
+ entry => entry.resume
893
+ ? {
894
+ args: [ ...entry.args ],
895
+ resume: true,
896
+ skipped: entry.skipped
897
+ }
898
+ : {
899
+ args: [ ...entry.args ],
900
+ skipped: entry.skipped
901
+ }
902
+ )
903
+ }
756
904
  const items = record.items ?? record.resume_items
757
905
  const has_failed_items = !!items?.some(item => item?.failed)
758
906
  if (!is_stale && (!is_kept || status == "failed" || has_failed_items || failed_sub_keys(record).length)) {
759
- if (items) data.items = Array.from(
760
- { length: items.length },
761
- (_, index) => items[index] ?? null
762
- )
763
- if (!is_moved && record.sub_runs.size) data.subs = snapshot_subs(record)
764
- else if (!is_moved && record.resume_subs) data.subs = record.resume_subs
907
+ if (items) {
908
+ data.items = Array.from(
909
+ { length: items.length },
910
+ (_, index) => items[index] ?? null
911
+ )
912
+ }
913
+ if (!is_moved && record.sub_runs.size) {
914
+ data.subs = snapshot_subs(record)
915
+ } else if (!is_moved && record.resume_subs) {
916
+ data.subs = record.resume_subs
917
+ }
765
918
  }
766
919
  snapshot_nodes[name] = data
767
920
  }
@@ -770,11 +923,15 @@ export function start_run(
770
923
  for (const [ key, error ] of Object.entries(errors)) {
771
924
  const dot = key.indexOf(".")
772
925
  const data = snapshot_nodes[dot < 0 ? key : key.slice(0, dot)]
773
- if (!data) continue
926
+ if (!data) {
927
+ continue
928
+ }
774
929
  const is_kept = dot < 0 || !data.items || data.fatal
775
930
  ? data.status != "idle"
776
931
  : data.items[Number(key.slice(dot + 1))] != null
777
- if (is_kept) snapshot_errors[key] = save_error(error)
932
+ if (is_kept) {
933
+ snapshot_errors[key] = save_error(error)
934
+ }
778
935
  }
779
936
  return {
780
937
  errors: snapshot_errors,
@@ -787,15 +944,23 @@ export function start_run(
787
944
  return state
788
945
  },
789
946
  get status() {
790
- if (c.run_status != "running") return c.run_status
947
+ if (c.run_status != "running") {
948
+ return c.run_status
949
+ }
791
950
  let waiting = false
792
951
  for (const record of records.values()) {
793
- if (record.delaying) return "running"
952
+ if (record.delaying) {
953
+ return "running"
954
+ }
794
955
  if (record.status == "running") {
795
- if (record.sub_running || !record.sub_waiting) return "running"
956
+ if (record.sub_running || !record.sub_waiting) {
957
+ return "running"
958
+ }
959
+ waiting = true
960
+ }
961
+ if (record.status == "waiting") {
796
962
  waiting = true
797
963
  }
798
- if (record.status == "waiting") waiting = true
799
964
  }
800
965
  return waiting ? "waiting" : "running"
801
966
  },
@@ -816,7 +981,9 @@ export function start_run(
816
981
  }
817
982
  },
818
983
  then(on_fulfilled, on_rejected) {
819
- if (on_rejected) c.observed = true
984
+ if (on_rejected) {
985
+ c.observed = true
986
+ }
820
987
  return c.cycle.promise.then(on_fulfilled, on_rejected)
821
988
  }
822
989
  }
@@ -860,8 +1027,12 @@ export function start_run(
860
1027
  signal_target,
861
1028
  run_options.signal
862
1029
  )
863
- if (resumes_failure) retry_failed(c, true)
864
- for (const name of records.keys()) try_start(c, name)
1030
+ if (resumes_failure) {
1031
+ retry_failed(c, true)
1032
+ }
1033
+ for (const name of records.keys()) {
1034
+ try_start(c, name)
1035
+ }
865
1036
  start_pumps(c)
866
1037
  schedule(c)
867
1038
  return run
@@ -871,7 +1042,9 @@ export function start_run(
871
1042
  * @returns {void}
872
1043
  */
873
1044
  function watch(c) {
874
- if (c.watched) return
1045
+ if (c.watched) {
1046
+ return
1047
+ }
875
1048
  c.watched = true
876
1049
  c.cycle.promise.catch(noop)
877
1050
  }