@vzn/vx 0.0.651 → 0.0.653
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/README.md +3 -4
- package/launcher.sh +2 -1
- package/package.json +5 -5
- package/schemas/error.json +1 -1
- package/schemas/show.json +15 -20
- package/skills/vx/SKILL.md +3 -3
- package/src/bin.ts +37 -3
- package/src/cache/archive.ts +197 -32
- package/src/cache/cache.ts +882 -230
- package/src/cache/checkpointer.ts +102 -0
- package/src/cache/file-hashes.ts +2 -1
- package/src/cache/fold-memo.ts +24 -4
- package/src/cache/fs-clock.ts +26 -0
- package/src/cache/git-inputs.ts +188 -22
- package/src/cache/history-stream.ts +151 -0
- package/src/cache/history-writer.ts +76 -0
- package/src/cache/index.ts +12 -1
- package/src/cache/inputs.ts +616 -135
- package/src/cache/key-fold.ts +1 -1
- package/src/cache/layer.ts +29 -16
- package/src/cache/layered-cache.ts +28 -7
- package/src/cache/lockfile-memo.ts +2 -1
- package/src/cache/output-index.ts +106 -44
- package/src/cache/plugin-cache.ts +2 -2
- package/src/cache/policy.ts +6 -2
- package/src/cache/remote-lane.ts +3 -1
- package/src/cache/run-history.ts +94 -25
- package/src/cache/schema.ts +46 -10
- package/src/cli/cache.ts +149 -36
- package/src/cli/completions.ts +2 -2
- package/src/cli/core-alias.ts +9 -2
- package/src/cli/docs.ts +4 -2
- package/src/cli/help.ts +27 -4
- package/src/cli/index.ts +62 -7
- package/src/cli/info.ts +5 -4
- package/src/cli/init.ts +55 -20
- package/src/cli/last.ts +218 -43
- package/src/cli/lock.ts +187 -24
- package/src/cli/plan-format.ts +24 -21
- package/src/cli/plugin-commands.ts +6 -1
- package/src/cli/plugin-templates.ts +36 -45
- package/src/cli/run.ts +68 -34
- package/src/cli/select.ts +160 -64
- package/src/cli/show.ts +70 -28
- package/src/cli/task-verb.ts +12 -7
- package/src/cli/upgrade.ts +210 -76
- package/src/cli/watch-filter.ts +88 -15
- package/src/cli/watch-fs.ts +34 -47
- package/src/cli/watch-judge.ts +73 -9
- package/src/cli/watch-set.ts +10 -8
- package/src/cli/watch.ts +190 -33
- package/src/cli/why.ts +107 -33
- package/src/cli/workspace-config.ts +11 -1
- package/src/config.ts +56 -30
- package/src/exec/env.ts +3 -1
- package/src/exec/executor.ts +116 -16
- package/src/exec/index.ts +1 -0
- package/src/exec/kill-tree.ts +7 -7
- package/src/exec/runner.ts +270 -108
- package/src/exec/sandbox-binds.ts +109 -18
- package/src/exec/sandbox-paths.ts +3 -1
- package/src/exec/sandbox-runtime.ts +446 -64
- package/src/exec/sandbox-violations.ts +250 -46
- package/src/exec/spawn-off.ts +10 -5
- package/src/exec/task-proxy.ts +93 -0
- package/src/exec/warm-shell.ts +29 -7
- package/src/graph/definition.ts +16 -3
- package/src/graph/folds.ts +89 -16
- package/src/graph/index.ts +8 -0
- package/src/graph/priorities.ts +8 -5
- package/src/graph/scheduler.ts +176 -39
- package/src/graph/stand-ins.ts +36 -0
- package/src/graph/task-graph.ts +347 -160
- package/src/graph/task-status.ts +5 -1
- package/src/handoff.ts +45 -10
- package/src/history/failure-mode.ts +39 -6
- package/src/history/history.ts +103 -30
- package/src/history/index.ts +2 -0
- package/src/history/metrics.ts +193 -73
- package/src/index.ts +6 -3
- package/src/orchestrator/admission.ts +14 -10
- package/src/orchestrator/affected-tasks.ts +35 -13
- package/src/orchestrator/command-windows.ts +8 -5
- package/src/orchestrator/deferred-outputs.ts +42 -13
- package/src/orchestrator/doctor.ts +21 -9
- package/src/orchestrator/download-policy.ts +8 -10
- package/src/orchestrator/excluded-keys.ts +15 -3
- package/src/orchestrator/execute-args.ts +9 -2
- package/src/orchestrator/execute-task.ts +612 -138
- package/src/orchestrator/graph-memo.ts +26 -4
- package/src/orchestrator/graph-stage.ts +27 -4
- package/src/orchestrator/held-servers.ts +36 -14
- package/src/orchestrator/hit-restore.ts +141 -93
- package/src/orchestrator/index.ts +4 -1
- package/src/orchestrator/keyed-projects.ts +53 -0
- package/src/orchestrator/local-floor.ts +21 -3
- package/src/orchestrator/local-shortcircuit.ts +2 -2
- package/src/orchestrator/lockfile-claim.ts +30 -4
- package/src/orchestrator/miss-save.ts +60 -61
- package/src/orchestrator/options.ts +13 -0
- package/src/orchestrator/output-host.ts +16 -4
- package/src/orchestrator/output-log.ts +1 -54
- package/src/orchestrator/persistent-task.ts +32 -16
- package/src/orchestrator/persistent.ts +152 -15
- package/src/orchestrator/placement.ts +82 -16
- package/src/orchestrator/plan.ts +39 -17
- package/src/orchestrator/plugin-host.ts +238 -110
- package/src/orchestrator/plugin.ts +59 -27
- package/src/orchestrator/prepare.ts +194 -38
- package/src/orchestrator/projects.ts +89 -10
- package/src/orchestrator/read-only.ts +115 -0
- package/src/orchestrator/remote-prefetch.ts +1 -1
- package/src/orchestrator/run-context.ts +6 -2
- package/src/orchestrator/run-failures.ts +101 -23
- package/src/orchestrator/run-id.ts +13 -2
- package/src/orchestrator/run-keys.ts +87 -28
- package/src/orchestrator/run-live.ts +16 -13
- package/src/orchestrator/run-lock.ts +27 -4
- package/src/orchestrator/run-records.ts +95 -74
- package/src/orchestrator/run-report.ts +3 -2
- package/src/orchestrator/run-stop.ts +17 -9
- package/src/orchestrator/run.ts +531 -122
- package/src/orchestrator/sandbox-fix.ts +40 -12
- package/src/orchestrator/sandbox-request.ts +314 -44
- package/src/orchestrator/save-lane.ts +24 -13
- package/src/orchestrator/shell-verdict.ts +29 -1
- package/src/orchestrator/signals.ts +103 -8
- package/src/orchestrator/stable-keys.ts +34 -27
- package/src/orchestrator/task-artifacts.ts +16 -3
- package/src/orchestrator/task-hash.ts +191 -34
- package/src/orchestrator/telemetry-host.ts +25 -6
- package/src/orchestrator/telemetry.ts +85 -13
- package/src/orchestrator/upstream.ts +3 -1
- package/src/report/events.ts +23 -6
- package/src/report/forecast.ts +103 -37
- package/src/report/framed-output.ts +179 -162
- package/src/report/index.ts +2 -1
- package/src/report/logger.ts +108 -31
- package/src/report/plain-output.ts +15 -9
- package/src/report/status-line.ts +28 -55
- package/src/report/summary.ts +61 -18
- package/src/settings.ts +50 -14
- package/src/ui/components.ts +36 -42
- package/src/ui/index.ts +3 -1
- package/src/ui/live-region.ts +67 -8
- package/src/ui/terminal.ts +12 -0
- package/src/ui/theme.ts +16 -1
- package/src/util/config-frame.ts +142 -6
- package/src/util/edit-distance.ts +17 -1
- package/src/util/errors.ts +23 -7
- package/src/util/foreign-cache-dir.ts +60 -0
- package/src/util/git-ignored.ts +59 -5
- package/src/util/index.ts +15 -1
- package/src/util/paths.ts +51 -7
- package/src/util/plain-text.ts +19 -0
- package/src/util/secret-mask.ts +57 -1
- package/src/util/settle.ts +18 -1
- package/src/util/size.ts +12 -2
- package/src/util/tail.ts +4 -1
- package/src/util/write-file.ts +86 -9
- package/src/workspace/affected.ts +225 -27
- package/src/workspace/bracket-literal.ts +2 -2
- package/src/workspace/config-bytecode.ts +23 -4
- package/src/workspace/config-eval.ts +90 -16
- package/src/workspace/config-imports.ts +96 -41
- package/src/workspace/config-schema.ts +192 -86
- package/src/workspace/dependencies-lock.ts +7 -14
- package/src/workspace/filter.ts +18 -2
- package/src/workspace/index.ts +3 -1
- package/src/workspace/json-data.ts +34 -8
- package/src/workspace/lockfile.ts +86 -37
- package/src/workspace/migration.ts +58 -31
- package/src/workspace/module-state.ts +62 -0
- package/src/workspace/nested-dirs.ts +8 -0
- package/src/workspace/project-loader.ts +276 -32
- package/src/workspace/repo-id.ts +29 -6
- package/src/workspace/workspace.ts +190 -30
package/src/exec/executor.ts
CHANGED
|
@@ -43,6 +43,16 @@ export interface ExecuteSandbox {
|
|
|
43
43
|
* machine's paths and platform, hands `sandboxRequestFor`.
|
|
44
44
|
*/
|
|
45
45
|
readonly keyed?: readonly string[]
|
|
46
|
+
/**
|
|
47
|
+
* The dependencies' outputs it may read (absolute), which an executor
|
|
48
|
+
* that builds the request again hands `sandboxRequestFor` too.
|
|
49
|
+
*/
|
|
50
|
+
readonly dependencyReads?: readonly string[]
|
|
51
|
+
/**
|
|
52
|
+
* The heads of those outputs (absolute): a refused read under one is a
|
|
53
|
+
* file beside them, reported. Handed `sandboxRequestFor` with them.
|
|
54
|
+
*/
|
|
55
|
+
readonly dependencyReported?: readonly string[]
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
/** One declared input file, as the cache key saw it. */
|
|
@@ -74,8 +84,9 @@ export interface TaskInputs {
|
|
|
74
84
|
* Dependencies whose cache keys are folded. `outputs` lists each one's
|
|
75
85
|
* declared output files (workspace-relative POSIX, as stored with its cache
|
|
76
86
|
* entry) — restored on disk before this task runs, so an input-shipping
|
|
77
|
-
* executor can include them in the input root.
|
|
78
|
-
*
|
|
87
|
+
* executor can include them in the input root. A non-cacheable
|
|
88
|
+
* dependency's are its declared outputs found on disk; a cacheable one
|
|
89
|
+
* with no entry in the local index lists none.
|
|
79
90
|
*/
|
|
80
91
|
readonly upstream: ReadonlyArray<{
|
|
81
92
|
readonly taskId: string
|
|
@@ -104,11 +115,17 @@ export interface ServerSpec {
|
|
|
104
115
|
readonly sandbox?: { readonly config: SandboxConfig; readonly nested: readonly string[] }
|
|
105
116
|
}
|
|
106
117
|
|
|
118
|
+
/**
|
|
119
|
+
* One task's command, as core hands it to an executor. A plugin
|
|
120
|
+
* executor's `outputs`, `envDefine` and `forwardArgs` are frozen copies:
|
|
121
|
+
* core saves the outputs after the command, and a config or the run's
|
|
122
|
+
* args are shared with other tasks.
|
|
123
|
+
*/
|
|
107
124
|
export interface ExecuteRequest {
|
|
108
125
|
/** `${project}#${task}` — for executors that route or log by task. */
|
|
109
126
|
readonly taskId: string
|
|
110
127
|
readonly workspaceRoot: string
|
|
111
|
-
/** Present for cacheable tasks (the miss path); absent
|
|
128
|
+
/** Present for cacheable tasks (the miss path); absent for a task without `cache: true`. */
|
|
112
129
|
readonly inputs?: TaskInputs
|
|
113
130
|
/**
|
|
114
131
|
* The task's cache key (present when the task is cacheable). An executor
|
|
@@ -145,6 +162,18 @@ export interface ExecuteRequest {
|
|
|
145
162
|
* executor's `platforms`: its key includes it. Absent when the task names none.
|
|
146
163
|
*/
|
|
147
164
|
readonly platform?: string
|
|
165
|
+
/**
|
|
166
|
+
* The worker type to run it on, one of the executor's `workers`: the
|
|
167
|
+
* task's `exec.worker`, else the first type with one of its platforms.
|
|
168
|
+
* Absent when the executor names no types.
|
|
169
|
+
*/
|
|
170
|
+
readonly worker?: string
|
|
171
|
+
/**
|
|
172
|
+
* Which attempt of the task this is, from 2 when it retries; absent on
|
|
173
|
+
* the first. An executor that can, runs a retry somewhere other than
|
|
174
|
+
* the attempt before it, so the machine is not the flake.
|
|
175
|
+
*/
|
|
176
|
+
readonly attempt?: number
|
|
148
177
|
/**
|
|
149
178
|
* Whether this task's outputs must land on the submitter's disk now.
|
|
150
179
|
* 'eager' (or absent) = materialise as today. 'deferred' = leave them
|
|
@@ -179,7 +208,8 @@ export interface ExecuteRequest {
|
|
|
179
208
|
readonly onStderr: (chunk: string) => void
|
|
180
209
|
/**
|
|
181
210
|
* Aborted when the run stops (Ctrl-C, SIGTERM, SIGHUP or an embedder's
|
|
182
|
-
* `RunOptions.signal`)
|
|
211
|
+
* `RunOptions.signal`), when `timeoutMs` elapses, or when fail-fast
|
|
212
|
+
* withdraws a task `running` says is not begun. An executor ends its
|
|
183
213
|
* work and returns: a child an executor spawned is not one core can
|
|
184
214
|
* reach (H-10, H-12). One already aborted is work not to start (B-55).
|
|
185
215
|
* Any exit after the timeout's abort, a 0 included, is a timeout. Core
|
|
@@ -225,10 +255,11 @@ export interface ExecuteResult extends RunResult {
|
|
|
225
255
|
*/
|
|
226
256
|
readonly outputs?: { kind: 'disk' } | { kind: 'deferred'; materialize: () => Promise<void> }
|
|
227
257
|
/**
|
|
228
|
-
* Tracked files the command changed where it ran,
|
|
229
|
-
* POSIX: an executor that runs it
|
|
230
|
-
* none of it. One the key read
|
|
231
|
-
*
|
|
258
|
+
* Tracked files the command changed where it ran, and untracked ones it
|
|
259
|
+
* found there, workspace-relative POSIX: an executor that runs it
|
|
260
|
+
* elsewhere says so, as this disk shows none of it. One the key read, or
|
|
261
|
+
* one its inputs declare, withholds the save under the key, as an input
|
|
262
|
+
* changed here does.
|
|
232
263
|
*/
|
|
233
264
|
readonly changed?: readonly string[]
|
|
234
265
|
/**
|
|
@@ -280,9 +311,12 @@ export interface TaskExecutor {
|
|
|
280
311
|
/** Runs the command somewhere else. Never offered a `pinnedLocal` task. */
|
|
281
312
|
readonly remote?: boolean
|
|
282
313
|
/**
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
314
|
+
* Enforces `ExecuteRequest.sandbox` where it runs the command, as the
|
|
315
|
+
* local one does; the request's violations come back on the result. Only
|
|
316
|
+
* such an executor is offered a task that declares `exec.sandbox`, here
|
|
317
|
+
* or remote: one that ran it unsandboxed passed a boundary it never
|
|
318
|
+
* checked and cached the output. A `remote` one is offered the
|
|
319
|
+
* dependants of a sandboxed task too.
|
|
286
320
|
*/
|
|
287
321
|
readonly sandbox?: boolean
|
|
288
322
|
/**
|
|
@@ -327,6 +361,14 @@ export interface TaskExecutor {
|
|
|
327
361
|
* declares none is never offered such a task off this machine.
|
|
328
362
|
*/
|
|
329
363
|
readonly platforms?: readonly string[]
|
|
364
|
+
/**
|
|
365
|
+
* Its worker types in order of preference, each with the platforms its
|
|
366
|
+
* machines run (`@vzn/vx-dte`'s `workers`). A task naming `exec.worker`
|
|
367
|
+
* is offered it only when it has that type on one of the task's
|
|
368
|
+
* platforms; any other task goes to the first type that fits, on
|
|
369
|
+
* `ExecuteRequest.worker`. Its `platforms` must list every one of them.
|
|
370
|
+
*/
|
|
371
|
+
readonly workers?: ReadonlyArray<readonly [name: string, platforms: readonly string[]]>
|
|
330
372
|
/**
|
|
331
373
|
* How many tasks this executor runs at once. Its tasks then occupy a pool
|
|
332
374
|
* of this size instead of the local worker slots, so a remote pool is not
|
|
@@ -334,7 +376,11 @@ export interface TaskExecutor {
|
|
|
334
376
|
* is refused when the executor is resolved. Absent = the local pool.
|
|
335
377
|
*/
|
|
336
378
|
readonly capacity?: number
|
|
337
|
-
/**
|
|
379
|
+
/**
|
|
380
|
+
* Per-task opt-out at placement time. Absent = accepts every task it is
|
|
381
|
+
* offered. `false` or `undefined` declines; any other non-boolean is
|
|
382
|
+
* refused, naming the plugin.
|
|
383
|
+
*/
|
|
338
384
|
accepts?(task: TaskPlacement): boolean
|
|
339
385
|
/**
|
|
340
386
|
* The tasks placed here that will run and have NOT finished yet — called
|
|
@@ -377,6 +423,13 @@ export interface TaskExecutor {
|
|
|
377
423
|
* anything but a finite number, reports none.
|
|
378
424
|
*/
|
|
379
425
|
idealMs?(): number | undefined
|
|
426
|
+
/**
|
|
427
|
+
* The workers that would have run the run best, judged after it from
|
|
428
|
+
* what each task took: for the run summary, so its reader can change
|
|
429
|
+
* how many workers the executor may start and of what size. Asked once
|
|
430
|
+
* at the end, only when a sink is on. A throw reports none.
|
|
431
|
+
*/
|
|
432
|
+
advice?(): readonly WorkerAdvice[]
|
|
380
433
|
/**
|
|
381
434
|
* Its own Chrome-trace events for `vx run --profile` (the machines it ran
|
|
382
435
|
* tasks on, in time), asked once at the end, only when the flag is set.
|
|
@@ -388,8 +441,17 @@ export interface TaskExecutor {
|
|
|
388
441
|
* Where a task it was handed runs (`small#2`), for the live row; asked
|
|
389
442
|
* per frame. `null` while it holds the task for a machine to begin it:
|
|
390
443
|
* the row says `waiting`, and its clock starts when a machine begins it.
|
|
444
|
+
* Under `--continue=never` a failure aborts the `signal` of each task it
|
|
445
|
+
* answers `null` for, and the task is skipped, never started.
|
|
391
446
|
*/
|
|
392
447
|
running?(taskId: string): string | null | undefined
|
|
448
|
+
/**
|
|
449
|
+
* A `servers` executor's: no task left in the run uses persistent task
|
|
450
|
+
* `taskId`, so each copy it started beside a dependant stops now, not at
|
|
451
|
+
* teardown. Core asks once, as the run stops its own copy (`schema.md`,
|
|
452
|
+
* "Stopped once nothing needs it"). A throw is ignored.
|
|
453
|
+
*/
|
|
454
|
+
unneeded?(taskId: string): void
|
|
393
455
|
execute(req: ExecuteRequest): Promise<ExecuteResult>
|
|
394
456
|
}
|
|
395
457
|
|
|
@@ -413,7 +475,11 @@ export interface MachineReport {
|
|
|
413
475
|
/** Bytes in use at once, at the most and on average. */
|
|
414
476
|
memoryPeakBytes: number
|
|
415
477
|
memoryAvgBytes: number
|
|
416
|
-
/**
|
|
478
|
+
/**
|
|
479
|
+
* Its machine's busy core-time over the core-time it had, from its first
|
|
480
|
+
* task's send to its last one's end, 0 to 1 (its tasks' own where its
|
|
481
|
+
* machine said none): whether cores were left idle.
|
|
482
|
+
*/
|
|
417
483
|
utilization: number
|
|
418
484
|
/** Cores the executor booked for the tasks it ran, on average over its time online. */
|
|
419
485
|
bookedAvg?: number
|
|
@@ -423,6 +489,27 @@ export interface MachineReport {
|
|
|
423
489
|
startMs?: number
|
|
424
490
|
}
|
|
425
491
|
|
|
492
|
+
/**
|
|
493
|
+
* Workers that would have run the run best (`TaskExecutor.advice`): `of`
|
|
494
|
+
* says on what. `declared`: as many of each size the executor may start
|
|
495
|
+
* as end it soonest; `more`: past each size's limit, when that ends it
|
|
496
|
+
* sooner; `any`: one shape a platform, of any cores, ending as soon for
|
|
497
|
+
* the least core time.
|
|
498
|
+
*/
|
|
499
|
+
export interface WorkerAdvice {
|
|
500
|
+
of: 'declared' | 'more' | 'any'
|
|
501
|
+
/** The run's end on them, from its start. */
|
|
502
|
+
endMs: number
|
|
503
|
+
workers: readonly {
|
|
504
|
+
count: number
|
|
505
|
+
cores: number
|
|
506
|
+
memoryBytes: number
|
|
507
|
+
platform?: string
|
|
508
|
+
/** The size it is, for `declared` and `more`. */
|
|
509
|
+
size?: string
|
|
510
|
+
}[]
|
|
511
|
+
}
|
|
512
|
+
|
|
426
513
|
/**
|
|
427
514
|
* What a remote executor rejects with when it gives a task back: core runs
|
|
428
515
|
* the same request on the local floor and says `reason` once (a remote that
|
|
@@ -535,8 +622,8 @@ export function assertExecuteResult(
|
|
|
535
622
|
|
|
536
623
|
/**
|
|
537
624
|
* Place one task: the first executor, in declaration order, that may take
|
|
538
|
-
* it — a `remote` executor is skipped for a `pinnedLocal` task,
|
|
539
|
-
* `accepts()` decides. Decided once per task before scheduling. The local
|
|
625
|
+
* it — a `remote` executor is skipped for a `pinnedLocal` task, any one
|
|
626
|
+
* `barred` names is skipped, then `accepts()` decides. Decided once per task before scheduling. The local
|
|
540
627
|
* executor accepts everything, so with it declared the only throw is an
|
|
541
628
|
* `accepts()` that threw: refused as `label` names that executor, where it
|
|
542
629
|
* surfaced as a bare stack naming no plugin (item 1022).
|
|
@@ -547,10 +634,12 @@ export function selectExecutor(
|
|
|
547
634
|
label: (executor: TaskExecutor) => string = (e) => `executor '${e.name}'`,
|
|
548
635
|
/** `task.pinnedLocal` as `executor` sees it: one that enforces the sandbox or carries servers lifts some pins. */
|
|
549
636
|
pinnedFor: (executor: TaskExecutor) => boolean = () => task.pinnedLocal,
|
|
637
|
+
/** Never offered the task: a sandboxed one is barred from an executor that does not enforce it. */
|
|
638
|
+
barred: (executor: TaskExecutor) => boolean = () => false,
|
|
550
639
|
): TaskExecutor {
|
|
551
640
|
for (const executor of executors) {
|
|
552
641
|
const pinned = pinnedFor(executor)
|
|
553
|
-
if (pinned && executor.remote === true) continue
|
|
642
|
+
if ((pinned && executor.remote === true) || barred(executor)) continue
|
|
554
643
|
if (executor.accepts === undefined) return executor
|
|
555
644
|
let taken: unknown
|
|
556
645
|
try {
|
|
@@ -563,6 +652,17 @@ export function selectExecutor(
|
|
|
563
652
|
taken.catch(() => {})
|
|
564
653
|
throw new Error('returned a Promise; accepts is synchronous')
|
|
565
654
|
}
|
|
655
|
+
// `'no'` was truthy and took the task; admit refuses the same answer.
|
|
656
|
+
if (taken !== undefined && typeof taken !== 'boolean') {
|
|
657
|
+
const t = typeof taken
|
|
658
|
+
const what =
|
|
659
|
+
taken === null
|
|
660
|
+
? 'null'
|
|
661
|
+
: Array.isArray(taken)
|
|
662
|
+
? 'an array'
|
|
663
|
+
: `${t === 'object' ? 'an' : 'a'} ${t}`
|
|
664
|
+
throw new Error(`returned ${what}, not true or false`)
|
|
665
|
+
}
|
|
566
666
|
} catch (err) {
|
|
567
667
|
const m = thrownMessage(err)
|
|
568
668
|
throw new UserError(`${label(executor)} failed in accepts for ${task.taskId}: ${m}`)
|
package/src/exec/index.ts
CHANGED
package/src/exec/kill-tree.ts
CHANGED
|
@@ -151,7 +151,7 @@ function stopGuard(): void {
|
|
|
151
151
|
|
|
152
152
|
function guardWrite(line: string): void {
|
|
153
153
|
if (typeof guardFd !== 'number') return
|
|
154
|
-
let deadline =
|
|
154
|
+
let deadline = performance.now() + GUARD_STALL_MS
|
|
155
155
|
// A turn's batch can be more than the queue takes at once: it goes in
|
|
156
156
|
// pieces as the guard drains it, and only a guard that takes nothing for
|
|
157
157
|
// the whole stall is gone. With one deadline for the batch, 2000 strikes
|
|
@@ -162,9 +162,9 @@ function guardWrite(line: string): void {
|
|
|
162
162
|
const n = writeSync(guardFd, bytes, 0, Math.min(bytes.length, GUARD_PIECE))
|
|
163
163
|
if (n === bytes.length) return
|
|
164
164
|
bytes = bytes.subarray(n)
|
|
165
|
-
deadline =
|
|
165
|
+
deadline = performance.now() + GUARD_STALL_MS
|
|
166
166
|
} catch (err) {
|
|
167
|
-
if ((err as NodeJS.ErrnoException).code !== 'EAGAIN' ||
|
|
167
|
+
if ((err as NodeJS.ErrnoException).code !== 'EAGAIN' || performance.now() >= deadline) break
|
|
168
168
|
Bun.sleepSync(1)
|
|
169
169
|
}
|
|
170
170
|
}
|
|
@@ -414,7 +414,7 @@ export async function untilGroupsGone(
|
|
|
414
414
|
children: readonly Child[],
|
|
415
415
|
graceMs: number,
|
|
416
416
|
): Promise<Child[]> {
|
|
417
|
-
const deadline =
|
|
417
|
+
const deadline = performance.now() + graceMs
|
|
418
418
|
let timer: ReturnType<typeof setTimeout> | undefined
|
|
419
419
|
// Not unref'd: it is what guarantees progress when every other handle
|
|
420
420
|
// has drained, and the grace is bounded either way.
|
|
@@ -426,8 +426,8 @@ export async function untilGroupsGone(
|
|
|
426
426
|
])
|
|
427
427
|
if (timer !== undefined) clearTimeout(timer)
|
|
428
428
|
let left = children.filter(groupAlive)
|
|
429
|
-
while (left.length > 0 &&
|
|
430
|
-
await Bun.sleep(Math.min(GROUP_POLL_MS, deadline -
|
|
429
|
+
while (left.length > 0 && performance.now() < deadline) {
|
|
430
|
+
await Bun.sleep(Math.min(GROUP_POLL_MS, deadline - performance.now()))
|
|
431
431
|
left = left.filter(groupAlive)
|
|
432
432
|
}
|
|
433
433
|
return left
|
|
@@ -443,7 +443,7 @@ export async function untilGroupsGone(
|
|
|
443
443
|
* and a group that ignored the SIGTERM went un-killed; there the group
|
|
444
444
|
* signal is the answer and the grace ends the wait.
|
|
445
445
|
*/
|
|
446
|
-
function groupAlive(child: Child): boolean {
|
|
446
|
+
export function groupAlive(child: Child): boolean {
|
|
447
447
|
if (!(child.pid > 0) || goneGroups.has(child)) return false
|
|
448
448
|
try {
|
|
449
449
|
process.kill(-child.pid, 0)
|