@ac-bench/lib 0.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/LICENSE +28 -0
- package/README.md +41 -0
- package/dist/child/channel.d.ts +28 -0
- package/dist/child/channel.d.ts.map +1 -0
- package/dist/child/channel.js +68 -0
- package/dist/child/channel.js.map +1 -0
- package/dist/child/event-sink.d.ts +13 -0
- package/dist/child/event-sink.d.ts.map +1 -0
- package/dist/child/event-sink.js +34 -0
- package/dist/child/event-sink.js.map +1 -0
- package/dist/child/main.d.ts +2 -0
- package/dist/child/main.d.ts.map +1 -0
- package/dist/child/main.js +157 -0
- package/dist/child/main.js.map +1 -0
- package/dist/cooldown.d.ts +51 -0
- package/dist/cooldown.d.ts.map +1 -0
- package/dist/cooldown.js +118 -0
- package/dist/cooldown.js.map +1 -0
- package/dist/current-environment.d.ts +8 -0
- package/dist/current-environment.d.ts.map +1 -0
- package/dist/current-environment.js +10 -0
- package/dist/current-environment.js.map +1 -0
- package/dist/environment-monitor.d.ts +59 -0
- package/dist/environment-monitor.d.ts.map +1 -0
- package/dist/environment-monitor.js +163 -0
- package/dist/environment-monitor.js.map +1 -0
- package/dist/escalation.d.ts +24 -0
- package/dist/escalation.d.ts.map +1 -0
- package/dist/escalation.js +73 -0
- package/dist/escalation.js.map +1 -0
- package/dist/fork-runner.d.ts +52 -0
- package/dist/fork-runner.d.ts.map +1 -0
- package/dist/fork-runner.js +348 -0
- package/dist/fork-runner.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/ipc-report-receiver.d.ts +47 -0
- package/dist/ipc-report-receiver.d.ts.map +1 -0
- package/dist/ipc-report-receiver.js +149 -0
- package/dist/ipc-report-receiver.js.map +1 -0
- package/dist/isolated-runner.d.ts +67 -0
- package/dist/isolated-runner.d.ts.map +1 -0
- package/dist/isolated-runner.js +537 -0
- package/dist/isolated-runner.js.map +1 -0
- package/dist/measure-diagnostic-proxy.d.ts +15 -0
- package/dist/measure-diagnostic-proxy.d.ts.map +1 -0
- package/dist/measure-diagnostic-proxy.js +50 -0
- package/dist/measure-diagnostic-proxy.js.map +1 -0
- package/dist/measurement-plan.d.ts +50 -0
- package/dist/measurement-plan.d.ts.map +1 -0
- package/dist/measurement-plan.js +2 -0
- package/dist/measurement-plan.js.map +1 -0
- package/dist/reporter-context.d.ts +19 -0
- package/dist/reporter-context.d.ts.map +1 -0
- package/dist/reporter-context.js +21 -0
- package/dist/reporter-context.js.map +1 -0
- package/dist/run-bench.d.ts +61 -0
- package/dist/run-bench.d.ts.map +1 -0
- package/dist/run-bench.js +151 -0
- package/dist/run-bench.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
+
}
|
|
18
|
+
else if (async) {
|
|
19
|
+
env.stack.push({ async: true });
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
+
return function (env) {
|
|
25
|
+
function fail(e) {
|
|
26
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
+
env.hasError = true;
|
|
28
|
+
}
|
|
29
|
+
var r, s = 0;
|
|
30
|
+
function next() {
|
|
31
|
+
while (r = env.stack.pop()) {
|
|
32
|
+
try {
|
|
33
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
+
if (r.dispose) {
|
|
35
|
+
var result = r.dispose.call(r.value);
|
|
36
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
+
}
|
|
38
|
+
else s |= 1;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
fail(e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
+
if (env.hasError) throw env.error;
|
|
46
|
+
}
|
|
47
|
+
return next();
|
|
48
|
+
};
|
|
49
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
+
var e = new Error(message);
|
|
51
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
+
});
|
|
53
|
+
import { fileURLToPath } from "node:url";
|
|
54
|
+
import { BENCH_PROTOCOL_VERSION, parseChildMessage, ProtocolVersionMismatchError, } from "@ac-bench/core/runner";
|
|
55
|
+
import { reportProcessOutput } from "@ac-kit/app-system";
|
|
56
|
+
import { formatError } from "@ac-kit/core";
|
|
57
|
+
import { forkProcess } from "@ac-kit/node";
|
|
58
|
+
import { IpcReportReceiver } from "./ipc-report-receiver.js";
|
|
59
|
+
/** No message from a child for this long means it is no longer making progress. */
|
|
60
|
+
export const DEFAULT_HEARTBEAT_TIMEOUT_MS = 30000;
|
|
61
|
+
const HANDSHAKE_TIMEOUT_MS = 10000;
|
|
62
|
+
/** A child stopped producing messages without having finished. */
|
|
63
|
+
export class ChildTimeoutError extends Error {
|
|
64
|
+
timeoutMs;
|
|
65
|
+
constructor(timeoutMs) {
|
|
66
|
+
super(`child produced no message for ${timeoutMs}ms`);
|
|
67
|
+
this.timeoutMs = timeoutMs;
|
|
68
|
+
this.name = "ChildTimeoutError";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** A fork unit outlived its wall-clock budget. */
|
|
72
|
+
export class ConditionTimeoutError extends Error {
|
|
73
|
+
timeoutMs;
|
|
74
|
+
constructor(timeoutMs) {
|
|
75
|
+
super(`condition exceeded its ${timeoutMs}ms budget`);
|
|
76
|
+
this.timeoutMs = timeoutMs;
|
|
77
|
+
this.name = "ConditionTimeoutError";
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** A child exited before reporting that it was done. */
|
|
81
|
+
export class ChildExitedError extends Error {
|
|
82
|
+
code;
|
|
83
|
+
signal;
|
|
84
|
+
constructor(code, signal, options) {
|
|
85
|
+
super(signal === null
|
|
86
|
+
? `child exited with code ${code}`
|
|
87
|
+
: `child was killed with ${signal}`, options);
|
|
88
|
+
this.code = code;
|
|
89
|
+
this.signal = signal;
|
|
90
|
+
this.name = "ChildExitedError";
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Forks a discovery child for `file` and returns the condition tree it
|
|
95
|
+
* registered, without executing a single case.
|
|
96
|
+
*/
|
|
97
|
+
export async function discoverConditionsInFile(file, options) {
|
|
98
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
99
|
+
try {
|
|
100
|
+
const child = __addDisposableResource(env_1, await spawnChild_(options), true);
|
|
101
|
+
const messages = childMessages_(child, options.heartbeatTimeoutMs ?? DEFAULT_HEARTBEAT_TIMEOUT_MS);
|
|
102
|
+
await handshake_(child, messages, options);
|
|
103
|
+
await child.send({ t: "list", file });
|
|
104
|
+
for await (const raw of messages) {
|
|
105
|
+
const message = parseChildMessage(raw);
|
|
106
|
+
if (message.t === "conditions") {
|
|
107
|
+
return message.conditions;
|
|
108
|
+
}
|
|
109
|
+
if (message.t === "fatal") {
|
|
110
|
+
throw asError_(message.error);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const exit = await child.waitForExit();
|
|
114
|
+
throw new ChildExitedError(exit.code, exit.signal);
|
|
115
|
+
}
|
|
116
|
+
catch (e_1) {
|
|
117
|
+
env_1.error = e_1;
|
|
118
|
+
env_1.hasError = true;
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
const result_1 = __disposeResources(env_1);
|
|
122
|
+
if (result_1)
|
|
123
|
+
await result_1;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Forks a child, runs one fork unit in it, and replays everything it reports
|
|
128
|
+
* into `sink` in order.
|
|
129
|
+
*
|
|
130
|
+
* The child's own scopes are closed out here if it dies without saying it was
|
|
131
|
+
* done, so a crash can never strand a scope.
|
|
132
|
+
*/
|
|
133
|
+
export async function runForkUnitInChild(start, sink, onDiagnostic, options) {
|
|
134
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
135
|
+
try {
|
|
136
|
+
const receiver = new IpcReportReceiver({
|
|
137
|
+
sink,
|
|
138
|
+
send: (message) => child.send(message),
|
|
139
|
+
onDiagnostic,
|
|
140
|
+
onProtocolFailure: () => {
|
|
141
|
+
void child.terminate();
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
let outputDrained = Promise.resolve();
|
|
145
|
+
// Declared before `child` so it is disposed after it, once output has ended.
|
|
146
|
+
const _outputFlush = __addDisposableResource(env_2, {
|
|
147
|
+
[Symbol.asyncDispose]: () => outputDrained,
|
|
148
|
+
}, true);
|
|
149
|
+
const child = __addDisposableResource(env_2, await spawnChild_(options), true);
|
|
150
|
+
outputDrained = reportProcessOutput(child, {
|
|
151
|
+
// Output belongs to whatever the child currently has open rather than to
|
|
152
|
+
// the fork unit's ancestor.
|
|
153
|
+
write: (event) => sink.write(event.kind === "output"
|
|
154
|
+
? {
|
|
155
|
+
...event,
|
|
156
|
+
scopeId: receiver.deepestOpenScope ?? start.parentScopeId,
|
|
157
|
+
}
|
|
158
|
+
: event),
|
|
159
|
+
flush: () => { },
|
|
160
|
+
close: () => { },
|
|
161
|
+
});
|
|
162
|
+
const messages = childMessages_(child, options.heartbeatTimeoutMs ?? DEFAULT_HEARTBEAT_TIMEOUT_MS);
|
|
163
|
+
const deadline = conditionDeadline_(options.conditionTimeoutMs);
|
|
164
|
+
try {
|
|
165
|
+
await handshake_(child, messages, options);
|
|
166
|
+
await child.send({ t: "start", ...start });
|
|
167
|
+
for await (const raw of messages) {
|
|
168
|
+
await receiver.receive(raw);
|
|
169
|
+
if (receiver.status !== null || receiver.fatal !== null) {
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
if (deadline !== null && Date.now() > deadline) {
|
|
173
|
+
throw new ConditionTimeoutError(options.conditionTimeoutMs ?? 0);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
// A channel that breaks on the way out cannot retroactively invalidate a run
|
|
179
|
+
// the child already reported as finished.
|
|
180
|
+
if (receiver.fatal === null && receiver.status !== null) {
|
|
181
|
+
onDiagnostic({
|
|
182
|
+
severity: "warning",
|
|
183
|
+
code: "transport-after-done",
|
|
184
|
+
message: `the channel failed after the child reported it was done: ${formatError(error)}`,
|
|
185
|
+
});
|
|
186
|
+
return { status: receiver.status, error: null };
|
|
187
|
+
}
|
|
188
|
+
// Ask first, then escalate: `terminate()` is SIGTERM, then SIGKILL.
|
|
189
|
+
await abortChild_(child, error);
|
|
190
|
+
const explained = await explainWithExit_(child, error);
|
|
191
|
+
await receiver.closeOpenScopes(explained);
|
|
192
|
+
return { status: "failed", error: explained };
|
|
193
|
+
}
|
|
194
|
+
if (receiver.fatal !== null) {
|
|
195
|
+
const error = asError_(receiver.fatal);
|
|
196
|
+
await receiver.closeOpenScopes(error);
|
|
197
|
+
return { status: "failed", error };
|
|
198
|
+
}
|
|
199
|
+
if (receiver.status === null) {
|
|
200
|
+
const exit = await child.waitForExit();
|
|
201
|
+
const error = new ChildExitedError(exit.code, exit.signal);
|
|
202
|
+
await receiver.closeOpenScopes(error);
|
|
203
|
+
return { status: "failed", error };
|
|
204
|
+
}
|
|
205
|
+
return { status: receiver.status, error: null };
|
|
206
|
+
}
|
|
207
|
+
catch (e_2) {
|
|
208
|
+
env_2.error = e_2;
|
|
209
|
+
env_2.hasError = true;
|
|
210
|
+
}
|
|
211
|
+
finally {
|
|
212
|
+
const result_2 = __disposeResources(env_2);
|
|
213
|
+
if (result_2)
|
|
214
|
+
await result_2;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function childEntryPath_() {
|
|
218
|
+
return fileURLToPath(import.meta.resolve("@ac-bench/lib/child"));
|
|
219
|
+
}
|
|
220
|
+
async function spawnChild_(options) {
|
|
221
|
+
const child = await forkProcess(childEntryPath_(), {
|
|
222
|
+
serialization: "advanced",
|
|
223
|
+
signal: options.signal,
|
|
224
|
+
execArgv: [
|
|
225
|
+
"--import",
|
|
226
|
+
import.meta.resolve("tsx/esm"),
|
|
227
|
+
...(options.execArgv ?? []),
|
|
228
|
+
],
|
|
229
|
+
env: { ...process.env, ...options.env },
|
|
230
|
+
stdout: "pipe",
|
|
231
|
+
stderr: "pipe",
|
|
232
|
+
});
|
|
233
|
+
options.onChildPid?.(child.pid);
|
|
234
|
+
return child;
|
|
235
|
+
}
|
|
236
|
+
async function handshake_(child, messages, options) {
|
|
237
|
+
await child.send({
|
|
238
|
+
t: "hello",
|
|
239
|
+
version: BENCH_PROTOCOL_VERSION,
|
|
240
|
+
runId: options.runId,
|
|
241
|
+
artifactCacheRoot: options.artifactCacheRoot,
|
|
242
|
+
...(options.setupFiles ? { setupFiles: [...options.setupFiles] } : {}),
|
|
243
|
+
});
|
|
244
|
+
const first = await withTimeout_(messages.next(), HANDSHAKE_TIMEOUT_MS);
|
|
245
|
+
if (first.done === true) {
|
|
246
|
+
const exit = await child.waitForExit();
|
|
247
|
+
throw new ChildExitedError(exit.code, exit.signal);
|
|
248
|
+
}
|
|
249
|
+
const message = parseChildMessage(first.value);
|
|
250
|
+
if (message.t !== "hello") {
|
|
251
|
+
throw new ProtocolVersionMismatchError(BENCH_PROTOCOL_VERSION, -1);
|
|
252
|
+
}
|
|
253
|
+
if (message.version !== BENCH_PROTOCOL_VERSION) {
|
|
254
|
+
throw new ProtocolVersionMismatchError(BENCH_PROTOCOL_VERSION, message.version);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Every message the child sends, in order, ending when it exits.
|
|
259
|
+
*
|
|
260
|
+
* @throws {ChildTimeoutError} When nothing arrives for `timeoutMs`.
|
|
261
|
+
*/
|
|
262
|
+
async function* childMessages_(child, timeoutMs) {
|
|
263
|
+
const pending = [];
|
|
264
|
+
let notify = null;
|
|
265
|
+
let exited = false;
|
|
266
|
+
const unsubscribe = child.subscribe("message", (message) => {
|
|
267
|
+
pending.push(message);
|
|
268
|
+
notify?.();
|
|
269
|
+
});
|
|
270
|
+
async function watchExit() {
|
|
271
|
+
await child.waitForExit();
|
|
272
|
+
exited = true;
|
|
273
|
+
notify?.();
|
|
274
|
+
}
|
|
275
|
+
void watchExit();
|
|
276
|
+
try {
|
|
277
|
+
for (;;) {
|
|
278
|
+
while (pending.length > 0) {
|
|
279
|
+
yield pending.shift();
|
|
280
|
+
}
|
|
281
|
+
if (exited) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
285
|
+
notify = resolve;
|
|
286
|
+
const timer = setTimeout(resolve, timeoutMs);
|
|
287
|
+
await promise;
|
|
288
|
+
clearTimeout(timer);
|
|
289
|
+
notify = null;
|
|
290
|
+
if (pending.length === 0 && !exited) {
|
|
291
|
+
throw new ChildTimeoutError(timeoutMs);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
finally {
|
|
296
|
+
unsubscribe?.();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
async function withTimeout_(promise, timeoutMs) {
|
|
300
|
+
const { promise: timedOut, reject } = Promise.withResolvers();
|
|
301
|
+
const timer = setTimeout(() => reject(new ChildTimeoutError(timeoutMs)), timeoutMs);
|
|
302
|
+
try {
|
|
303
|
+
return await Promise.race([promise, timedOut]);
|
|
304
|
+
}
|
|
305
|
+
finally {
|
|
306
|
+
clearTimeout(timer);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function asError_(value) {
|
|
310
|
+
return value instanceof Error
|
|
311
|
+
? value
|
|
312
|
+
: new Error(typeof value === "string" ? value : JSON.stringify(value));
|
|
313
|
+
}
|
|
314
|
+
function conditionDeadline_(timeoutMs) {
|
|
315
|
+
return timeoutMs === undefined || timeoutMs <= 0
|
|
316
|
+
? null
|
|
317
|
+
: Date.now() + timeoutMs;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* First rung of the escalation ladder: the child is told to stop, and only then
|
|
321
|
+
* signalled. A child that honours it closes its own scopes.
|
|
322
|
+
*/
|
|
323
|
+
async function abortChild_(child, reason) {
|
|
324
|
+
try {
|
|
325
|
+
await child.send({ t: "abort", reason: formatError(reason) });
|
|
326
|
+
}
|
|
327
|
+
catch {
|
|
328
|
+
// The channel is already gone; the signal below is what is left.
|
|
329
|
+
}
|
|
330
|
+
await child.terminate();
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* A broken channel names the symptom (`write EPIPE`); the child's exit status
|
|
334
|
+
* names the cause. The verdicts the parent reaches on its own already explain
|
|
335
|
+
* themselves, and the child died because of them rather than the other way
|
|
336
|
+
* round.
|
|
337
|
+
*/
|
|
338
|
+
async function explainWithExit_(child, error) {
|
|
339
|
+
if (error instanceof ChildExitedError ||
|
|
340
|
+
error instanceof ChildTimeoutError ||
|
|
341
|
+
error instanceof ConditionTimeoutError ||
|
|
342
|
+
error instanceof ProtocolVersionMismatchError) {
|
|
343
|
+
return error;
|
|
344
|
+
}
|
|
345
|
+
const exit = await child.waitForExit();
|
|
346
|
+
return new ChildExitedError(exit.code, exit.signal, { cause: error });
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=fork-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fork-runner.js","sourceRoot":"","sources":["../src/fork-runner.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from "./cooldown.js";
|
|
2
|
+
export * from "./current-environment.js";
|
|
3
|
+
export * from "./environment-monitor.js";
|
|
4
|
+
export * from "./escalation.js";
|
|
5
|
+
export * from "./fork-runner.js";
|
|
6
|
+
export * from "./ipc-report-receiver.js";
|
|
7
|
+
export * from "./isolated-runner.js";
|
|
8
|
+
export * from "./measure-diagnostic-proxy.js";
|
|
9
|
+
export * from "./measurement-plan.js";
|
|
10
|
+
export * from "./reporter-context.js";
|
|
11
|
+
export * from "./run-bench.js";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from "./cooldown.js";
|
|
2
|
+
export * from "./current-environment.js";
|
|
3
|
+
export * from "./environment-monitor.js";
|
|
4
|
+
export * from "./escalation.js";
|
|
5
|
+
export * from "./fork-runner.js";
|
|
6
|
+
export * from "./ipc-report-receiver.js";
|
|
7
|
+
export * from "./isolated-runner.js";
|
|
8
|
+
export * from "./measure-diagnostic-proxy.js";
|
|
9
|
+
export * from "./measurement-plan.js";
|
|
10
|
+
export * from "./reporter-context.js";
|
|
11
|
+
export * from "./run-bench.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { MeasureData, ParentMessage } from "@ac-bench/core/runner";
|
|
2
|
+
import { ISink, ReportDiagnostic, ReportScopeStatus } from "@ac-kit/app-report";
|
|
3
|
+
/** The child's `seq` did not follow the previous one. */
|
|
4
|
+
export declare class SequenceGapError extends Error {
|
|
5
|
+
readonly expected: number;
|
|
6
|
+
readonly received: number;
|
|
7
|
+
constructor(expected: number, received: number);
|
|
8
|
+
}
|
|
9
|
+
export type IpcReportReceiverOptions = {
|
|
10
|
+
readonly sink: ISink<MeasureData>;
|
|
11
|
+
readonly send: (message: ParentMessage) => Promise<void> | void;
|
|
12
|
+
readonly onDiagnostic: (diagnostic: ReportDiagnostic) => void;
|
|
13
|
+
/** The child can no longer be trusted and must be terminated. */
|
|
14
|
+
readonly onProtocolFailure: (error: unknown) => void;
|
|
15
|
+
readonly ackEvery?: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Turns one child's message stream into sink writes, asserting the sequence,
|
|
19
|
+
* renewing the child's credit, and remembering which scopes it left open so a
|
|
20
|
+
* crash can still be closed out.
|
|
21
|
+
*/
|
|
22
|
+
export declare class IpcReportReceiver {
|
|
23
|
+
private readonly options;
|
|
24
|
+
private expectedSeq;
|
|
25
|
+
private protocolErrors;
|
|
26
|
+
private lastAcked;
|
|
27
|
+
private readonly tracker;
|
|
28
|
+
/** The status the child reported, or `null` while it is still running. */
|
|
29
|
+
status: ReportScopeStatus | null;
|
|
30
|
+
/** The error the child reported as fatal, if any. */
|
|
31
|
+
fatal: unknown;
|
|
32
|
+
constructor(options: IpcReportReceiverOptions);
|
|
33
|
+
/** Scopes the child opened and never closed, deepest last. */
|
|
34
|
+
get openScopes(): readonly string[];
|
|
35
|
+
/** The innermost scope the child has open, for attributing its output. */
|
|
36
|
+
get deepestOpenScope(): string | null;
|
|
37
|
+
receive(raw: unknown): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Writes a synthetic `scope-end` for everything the child left open, so a
|
|
40
|
+
* crash cannot strand a scope. Innermost first.
|
|
41
|
+
*/
|
|
42
|
+
closeOpenScopes(error: unknown): Promise<void>;
|
|
43
|
+
private writeEvent;
|
|
44
|
+
private recordProtocolError;
|
|
45
|
+
private acknowledge;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=ipc-report-receiver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ipc-report-receiver.d.ts","sourceRoot":"","sources":["../src/ipc-report-receiver.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,WAAW,EACX,aAAa,EAGb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,KAAK,EAEL,gBAAgB,EAChB,iBAAiB,EAEjB,MAAM,oBAAoB,CAAC;AAS5B,yDAAyD;AACzD,qBAAa,gBAAiB,SAAQ,KAAK;IAEzC,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAF1B,YACU,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAIzB;CACD;AAED,MAAM,MAAM,wBAAwB,GAAG;IACtC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAChE,QAAQ,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC9D,iEAAiE;IACjE,QAAQ,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF;;;;GAIG;AACH,qBAAa,iBAAiB;IAYjB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAXpC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAE9C,0EAA0E;IAC1E,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAQ;IAExC,qDAAqD;IACrD,KAAK,EAAE,OAAO,CAAQ;IAEtB,YAA6B,OAAO,EAAE,wBAAwB,EAAI;IAElE,8DAA8D;IAC9D,IAAI,UAAU,IAAI,SAAS,MAAM,EAAE,CAElC;IAED,0EAA0E;IAC1E,IAAI,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAIpC;IAEK,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDzC;IAED;;;OAGG;IACG,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAcnD;YAEa,UAAU;IAWxB,OAAO,CAAC,mBAAmB;YAcb,WAAW;CAqBzB"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { parseChildMessage, parseMeasureData, } from "@ac-bench/core/runner";
|
|
2
|
+
import { parseReportEvent, ScopeTracker, } from "@ac-kit/app-report";
|
|
3
|
+
import { formatError } from "@ac-kit/core";
|
|
4
|
+
/** How many events the parent consumes before renewing the child's credit. */
|
|
5
|
+
const ACK_EVERY = 128;
|
|
6
|
+
/** Consecutive protocol errors after which the child is no longer trusted. */
|
|
7
|
+
const MAX_PROTOCOL_ERRORS = 3;
|
|
8
|
+
/** The child's `seq` did not follow the previous one. */
|
|
9
|
+
export class SequenceGapError extends Error {
|
|
10
|
+
expected;
|
|
11
|
+
received;
|
|
12
|
+
constructor(expected, received) {
|
|
13
|
+
super(`expected child sequence ${expected}, got ${received}`);
|
|
14
|
+
this.expected = expected;
|
|
15
|
+
this.received = received;
|
|
16
|
+
this.name = "SequenceGapError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Turns one child's message stream into sink writes, asserting the sequence,
|
|
21
|
+
* renewing the child's credit, and remembering which scopes it left open so a
|
|
22
|
+
* crash can still be closed out.
|
|
23
|
+
*/
|
|
24
|
+
export class IpcReportReceiver {
|
|
25
|
+
options;
|
|
26
|
+
expectedSeq = 1;
|
|
27
|
+
protocolErrors = 0;
|
|
28
|
+
lastAcked = 0;
|
|
29
|
+
tracker = new ScopeTracker();
|
|
30
|
+
/** The status the child reported, or `null` while it is still running. */
|
|
31
|
+
status = null;
|
|
32
|
+
/** The error the child reported as fatal, if any. */
|
|
33
|
+
fatal = null;
|
|
34
|
+
constructor(options) {
|
|
35
|
+
this.options = options;
|
|
36
|
+
}
|
|
37
|
+
/** Scopes the child opened and never closed, deepest last. */
|
|
38
|
+
get openScopes() {
|
|
39
|
+
return this.tracker.open().map((record) => record.id);
|
|
40
|
+
}
|
|
41
|
+
/** The innermost scope the child has open, for attributing its output. */
|
|
42
|
+
get deepestOpenScope() {
|
|
43
|
+
const open = this.tracker.open();
|
|
44
|
+
return open[open.length - 1]?.id ?? null;
|
|
45
|
+
}
|
|
46
|
+
async receive(raw) {
|
|
47
|
+
let message;
|
|
48
|
+
try {
|
|
49
|
+
message = parseChildMessage(raw);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
this.recordProtocolError(error);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (message.t === "hello" || message.t === "conditions") {
|
|
56
|
+
this.recordProtocolError(new Error(`unexpected "${message.t}" message during a run`));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (message.seq !== this.expectedSeq) {
|
|
60
|
+
this.recordProtocolError(new SequenceGapError(this.expectedSeq, message.seq));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
this.expectedSeq += 1;
|
|
64
|
+
this.protocolErrors = 0;
|
|
65
|
+
switch (message.t) {
|
|
66
|
+
case "event":
|
|
67
|
+
await this.writeEvent(message.event);
|
|
68
|
+
break;
|
|
69
|
+
case "dropped":
|
|
70
|
+
this.options.onDiagnostic({
|
|
71
|
+
severity: "warning",
|
|
72
|
+
code: "events-dropped",
|
|
73
|
+
message: `${message.count} report events were dropped by the child`,
|
|
74
|
+
attributes: { kinds: message.kinds },
|
|
75
|
+
});
|
|
76
|
+
break;
|
|
77
|
+
case "done":
|
|
78
|
+
this.status = message.status;
|
|
79
|
+
break;
|
|
80
|
+
case "fatal":
|
|
81
|
+
this.fatal = message.error;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
// A child that has reported an outcome is already disconnecting: renewing
|
|
85
|
+
// its credit now races its `process.disconnect()` and writes to a dead pipe.
|
|
86
|
+
if (this.status === null && this.fatal === null) {
|
|
87
|
+
await this.acknowledge();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Writes a synthetic `scope-end` for everything the child left open, so a
|
|
92
|
+
* crash cannot strand a scope. Innermost first.
|
|
93
|
+
*/
|
|
94
|
+
async closeOpenScopes(error) {
|
|
95
|
+
for (const record of [...this.tracker.open()].toReversed()) {
|
|
96
|
+
const event = {
|
|
97
|
+
kind: "scope-end",
|
|
98
|
+
timestamp: Date.now(),
|
|
99
|
+
scopeId: record.id,
|
|
100
|
+
status: "failed",
|
|
101
|
+
durationMs: Date.now() - record.startedAt,
|
|
102
|
+
error,
|
|
103
|
+
};
|
|
104
|
+
this.tracker.observe(event);
|
|
105
|
+
await this.options.sink.write(event);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async writeEvent(raw) {
|
|
109
|
+
try {
|
|
110
|
+
const event = parseReportEvent(raw, parseMeasureData);
|
|
111
|
+
this.tracker.observe(event);
|
|
112
|
+
await this.options.sink.write(event);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
this.recordProtocolError(error);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
recordProtocolError(error) {
|
|
119
|
+
this.protocolErrors += 1;
|
|
120
|
+
this.options.onDiagnostic({
|
|
121
|
+
severity: "error",
|
|
122
|
+
code: "protocol-error",
|
|
123
|
+
message: formatError(error),
|
|
124
|
+
});
|
|
125
|
+
if (this.protocolErrors >= MAX_PROTOCOL_ERRORS) {
|
|
126
|
+
this.options.onProtocolFailure(error);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async acknowledge() {
|
|
130
|
+
const consumed = this.expectedSeq - 1;
|
|
131
|
+
if (consumed - this.lastAcked < (this.options.ackEvery ?? ACK_EVERY)) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
this.lastAcked = consumed;
|
|
135
|
+
try {
|
|
136
|
+
await this.options.send({ t: "ack", seq: consumed });
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
// Credit renewal is advisory: a lost ack can stall the child into the
|
|
140
|
+
// heartbeat timeout, but it can never corrupt what it already reported.
|
|
141
|
+
this.options.onDiagnostic({
|
|
142
|
+
severity: "warning",
|
|
143
|
+
code: "ack-failed",
|
|
144
|
+
message: `could not renew the child's credit: ${formatError(error)}`,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=ipc-report-receiver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ipc-report-receiver.js","sourceRoot":"","sources":["../src/ipc-report-receiver.ts"],"names":[],"mappings":"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"}
|