@vzn/vx 0.0.616 → 0.0.617

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vzn/vx",
3
- "version": "0.0.616",
3
+ "version": "0.0.617",
4
4
  "description": "The fastest task runner and build cache for JavaScript monorepos.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -21,10 +21,10 @@
21
21
  "node": ">=18"
22
22
  },
23
23
  "optionalDependencies": {
24
- "@vzn/vx-linux-x64": "0.0.616",
25
- "@vzn/vx-linux-arm64": "0.0.616",
26
- "@vzn/vx-darwin-x64": "0.0.616",
27
- "@vzn/vx-darwin-arm64": "0.0.616"
24
+ "@vzn/vx-linux-x64": "0.0.617",
25
+ "@vzn/vx-linux-arm64": "0.0.617",
26
+ "@vzn/vx-darwin-x64": "0.0.617",
27
+ "@vzn/vx-darwin-arm64": "0.0.617"
28
28
  },
29
29
  "dependencies": {
30
30
  "@anthropic-ai/sandbox-runtime": "^0.0.76"
@@ -24,7 +24,17 @@ export function tieredReverseDepCount(
24
24
  ): Map<string, number> {
25
25
  const exec = new Map<string, TaskNode>()
26
26
  for (const [id, node] of nodes) if (!restoreTier.has(id)) exec.set(id, node)
27
- const counts = computeReverseDepCount(exec)
27
+ // An exec tier with no edge inside it (a warm run's groups) counts 0
28
+ // everywhere: no closure to build.
29
+ let linked = false
30
+ for (const node of exec.values()) {
31
+ if (node.deps.some((d) => exec.has(d))) {
32
+ linked = true
33
+ break
34
+ }
35
+ }
36
+ const counts = linked ? computeReverseDepCount(exec) : new Map<string, number>()
37
+ if (!linked) for (const id of exec.keys()) counts.set(id, 0)
28
38
  let feeds = false
29
39
  for (const node of exec.values()) {
30
40
  const weight = 1 + counts.get(node.id)!
@@ -324,6 +324,9 @@ export interface ScheduleOptions {
324
324
  class ReadyHeap {
325
325
  private readonly ids: string[] = []
326
326
  private readonly seq: number[] = []
327
+ // Each slot's priority, read once at push: a map lookup per comparison
328
+ // was two per heap level on every push and pop.
329
+ private readonly prio: number[] = []
327
330
  private next = 0
328
331
  constructor(private readonly priority: ReadonlyMap<string, number>) {}
329
332
  get size(): number {
@@ -331,8 +334,8 @@ class ReadyHeap {
331
334
  }
332
335
  /** True if slot i outranks slot j (higher priority, or equal priority + earlier seq). */
333
336
  private higher(i: number, j: number): boolean {
334
- const pi = this.priority.get(this.ids[i]!) ?? 0
335
- const pj = this.priority.get(this.ids[j]!) ?? 0
337
+ const pi = this.prio[i]!
338
+ const pj = this.prio[j]!
336
339
  return pi !== pj ? pi > pj : this.seq[i]! < this.seq[j]!
337
340
  }
338
341
  private swap(i: number, j: number): void {
@@ -342,6 +345,9 @@ class ReadyHeap {
342
345
  const si = this.seq[i]!
343
346
  this.seq[i] = this.seq[j]!
344
347
  this.seq[j] = si
348
+ const pi = this.prio[i]!
349
+ this.prio[i] = this.prio[j]!
350
+ this.prio[j] = pi
345
351
  }
346
352
  /**
347
353
  * `seq` defaults to a fresh monotonic counter. A parked-then-repushed
@@ -361,6 +367,7 @@ class ReadyHeap {
361
367
  push(id: string, seq: number = this.next++): void {
362
368
  this.ids.push(id)
363
369
  this.seq.push(seq)
370
+ this.prio.push(this.priority.get(id) ?? 0)
364
371
  let i = this.ids.length - 1
365
372
  while (i > 0) {
366
373
  const parent = (i - 1) >> 1
@@ -379,9 +386,11 @@ class ReadyHeap {
379
386
  const top = this.ids[0]!
380
387
  const lastId = this.ids.pop()!
381
388
  const lastSeq = this.seq.pop()!
389
+ const lastPrio = this.prio.pop()!
382
390
  if (n > 1) {
383
391
  this.ids[0] = lastId
384
392
  this.seq[0] = lastSeq
393
+ this.prio[0] = lastPrio
385
394
  let i = 0
386
395
  for (;;) {
387
396
  const l = 2 * i + 1
@@ -701,14 +710,18 @@ export async function runGraph(options: ScheduleOptions): Promise<Map<string, Ta
701
710
  // could fail anyway.
702
711
  const aborted = (): boolean => options.signal?.aborted === true
703
712
  const serverDied = options.serverDied ?? ((): boolean => false)
704
- const deadServerVia = (id: string): string | undefined =>
705
- deadServerBehind(nodes, serverDied, id)
706
713
  const servers =
707
714
  options.serverDied === undefined
708
715
  ? []
709
716
  : [...nodes.values()]
710
717
  .filter((n) => n.config.exec?.persistent !== undefined)
711
718
  .map((n) => n.id)
719
+ // Only a server can die: with none in the graph, no walk (a stack and
720
+ // a set per dependency of every exec-tier task, X-171).
721
+ const deadServerVia =
722
+ servers.length === 0
723
+ ? (): undefined => undefined
724
+ : (id: string): string | undefined => deadServerBehind(nodes, serverDied, id)
712
725
  const willSkip = (id: string): boolean => {
713
726
  if (failFastTripped || aborted()) return true
714
727
  if (continueMode === 'never' && servers.some(serverDied)) {