@mark1russell7/harness 0.12.4 → 0.14.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/README.md +11 -3
- package/build/{cell-jEkGFgGL.d.ts → cell-D2QNOxE8.d.ts} +21 -2
- package/build/index.d.ts +254 -202
- package/build/index.js +113 -48
- package/build/index.js.map +1 -1
- package/build/schema.d.ts +1 -1
- package/image/native/src/bin/client.rs +7 -8
- package/image/native/src/bin/inject.rs +11 -10
- package/image/node/client-ioredis.mjs +4 -4
- package/image/node/client-sentinel.mjs +1 -1
- package/image/node-http/lines.mjs +2 -2
- package/package.json +3 -2
package/build/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { C as targetImageOf, E as unpinnedBases, S as subjectProblems, T as unlockedManifests, _ as pgClientImage, a as SHIPPED_NAMES, b as routerImage, c as grpcClientImage, d as imageOf, f as imageProblems, g as nodeHttpImage, h as nodeClientImage, i as SHIPPED_CLIENTS, l as harnessImage, m as mongoClientImage, n as PINNED, o as amqpClientImage, p as inContext, r as REPOSITORY, s as goHttpImage, t as CLIENT_NAMES, u as hikariClientImage, v as planOf, w as targetSourceOf, x as subjectClient, y as programOf } from "./image-Lg8LL6C3.js";
|
|
2
2
|
import { quantity, valueIn } from "@mark1russell7/quantity";
|
|
3
|
+
import { median, medianInterval as medianInterval$1, quantileSorted } from "@mark1russell7/rigor-statistics";
|
|
3
4
|
import { createHash } from "node:crypto";
|
|
4
5
|
//#region src/cell.ts
|
|
5
6
|
/** This function tells if a fault place is a hop of a topology. */
|
|
@@ -35,6 +36,37 @@ const INJECT = NOISE;
|
|
|
35
36
|
/** This function gives the δ_abs of a cell: its own, or `NOISE` for a cell that gives none. */
|
|
36
37
|
const noiseOf = (cell) => cell.noise ?? NOISE;
|
|
37
38
|
/**
|
|
39
|
+
* This function gives the pairing window of a run (SYS-25). On a runner of GitHub, the jitter of
|
|
40
|
+
* a program can be longer than the δ_abs of 1 ms. Thus each run measures it before its fault
|
|
41
|
+
* (`Run.jitter`), and its own measurement widens its window. A run without a jitter record is
|
|
42
|
+
* from before SYS-25. It reads as a bound of null, thus its window is δ_abs. The decision of
|
|
43
|
+
* 2026-10-19 keeps the rule of one miss: a pair that a window misses is still a finding.
|
|
44
|
+
*/
|
|
45
|
+
const pairingOf = (cell, run) => {
|
|
46
|
+
const noise = noiseOf(cell);
|
|
47
|
+
const bound = run.jitter?.bound ?? null;
|
|
48
|
+
return {
|
|
49
|
+
bound,
|
|
50
|
+
delta: bound !== null && valueIn(bound, "s") > valueIn(noise, "s") ? bound : noise
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* This function sums the pairings of the measurements of a cell. It gives the longest bound and
|
|
55
|
+
* the longest window. It also counts the pairings whose window is longer than δ_abs (`noise`). It
|
|
56
|
+
* is null when no measurement has a pairing.
|
|
57
|
+
*/
|
|
58
|
+
const pairingsOf = (runs, noise = NOISE) => {
|
|
59
|
+
const pairings = runs.flatMap((run) => run.pairing === void 0 ? [] : [run.pairing]);
|
|
60
|
+
if (pairings.length === 0) return null;
|
|
61
|
+
const longest = (values) => values.reduce((most, each) => valueIn(each, "s") > valueIn(most, "s") ? each : most);
|
|
62
|
+
const bounds = pairings.flatMap((pairing) => pairing.bound === null ? [] : [pairing.bound]);
|
|
63
|
+
return {
|
|
64
|
+
bound: bounds.length === 0 ? null : longest(bounds),
|
|
65
|
+
delta: longest(pairings.map((pairing) => pairing.delta)),
|
|
66
|
+
widened: pairings.filter((pairing) => valueIn(pairing.delta, "s") > valueIn(noise, "s")).length
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
38
70
|
* This function tells if a timer firing came late enough to void a run. A firing two jiffies or
|
|
39
71
|
* more behind its wheel slot came late because the host stopped a vCPU. With the HZ of the run,
|
|
40
72
|
* the rule is in time: the delay must also reach δ_abs, because each band already includes that
|
|
@@ -55,15 +87,18 @@ const STEPS = [
|
|
|
55
87
|
];
|
|
56
88
|
const s = (value) => quantity(Math.round(value * 1e6) / 1e6, "s");
|
|
57
89
|
const name = (run) => `env ${run.environment} run ${run.index}`;
|
|
58
|
-
/**
|
|
59
|
-
|
|
90
|
+
/**
|
|
91
|
+
* This function gives the value at quantile p of sorted values, by nearest rank: x_(⌈p·n⌉). It is
|
|
92
|
+
* `quantileSorted` of @mark1russell7/rigor-statistics with the method `"nearest-rank"`.
|
|
93
|
+
*/
|
|
94
|
+
const quantileOf = (sorted, p) => quantileSorted(sorted, p, "nearest-rank");
|
|
60
95
|
/** This function gives the spread of a set of times, or null for none. */
|
|
61
96
|
const spreadOf = (times) => {
|
|
62
97
|
if (times.length === 0) return null;
|
|
63
98
|
const sorted = times.map((time) => valueIn(time, "s")).sort((a, b) => a - b);
|
|
64
99
|
return {
|
|
65
100
|
count: sorted.length,
|
|
66
|
-
median: s(
|
|
101
|
+
median: s(median(sorted)),
|
|
67
102
|
p99: s(quantileOf(sorted, .99)),
|
|
68
103
|
p999: s(quantileOf(sorted, .999)),
|
|
69
104
|
max: s(sorted.at(-1))
|
|
@@ -104,30 +139,15 @@ const spreadWords = (spread) => {
|
|
|
104
139
|
const ms = (time) => Math.round(valueIn(time, "s") * 1e6) / 1e3;
|
|
105
140
|
return `median ${ms(spread.median)} ms, p99 ${ms(spread.p99)} ms, p99.9 ${ms(spread.p999)} ms, max ${ms(spread.max)} ms of ${spread.count}`;
|
|
106
141
|
};
|
|
107
|
-
/** This function gives P(X ≤ j) for X ~ Binomial(n, 1/2), exactly. */
|
|
108
|
-
const below = (n, j) => {
|
|
109
|
-
let term = 1;
|
|
110
|
-
let sum = 0;
|
|
111
|
-
for (let i = 0; i <= j; i += 1) {
|
|
112
|
-
sum += term;
|
|
113
|
-
term = term * (n - i) / (i + 1);
|
|
114
|
-
}
|
|
115
|
-
return sum / 2 ** n;
|
|
116
|
-
};
|
|
117
142
|
/**
|
|
118
143
|
* This function gives the distribution-free interval of a median: [x_(k), x_(n+1−k)], for the
|
|
119
144
|
* largest k whose two tails each hold 2.5 % or less. For eleven runs, it gives [x_(2), x_(10)],
|
|
120
|
-
* at 98.8 %.
|
|
145
|
+
* at 98.8 %. It is `medianInterval` of @mark1russell7/rigor-statistics at the level 0.95. An
|
|
146
|
+
* empty list throws a RangeError.
|
|
121
147
|
*/
|
|
122
148
|
const medianInterval = (sorted) => {
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
while (k + 1 <= n / 2 && below(n, k) <= .025) k += 1;
|
|
126
|
-
return k === 0 ? [sorted[0], sorted[n - 1]] : [sorted[k - 1], sorted[n - k]];
|
|
127
|
-
};
|
|
128
|
-
const middle = (sorted) => {
|
|
129
|
-
const half = Math.floor(sorted.length / 2);
|
|
130
|
-
return sorted.length % 2 === 1 ? sorted[half] : (sorted[half - 1] + sorted[half]) / 2;
|
|
149
|
+
const interval = medianInterval$1(sorted, .95);
|
|
150
|
+
return [interval.low, interval.high];
|
|
131
151
|
};
|
|
132
152
|
/**
|
|
133
153
|
* This function gives the verdict of a cell, from two tests:
|
|
@@ -210,7 +230,7 @@ const withRequests = (verdict, counted) => {
|
|
|
210
230
|
};
|
|
211
231
|
};
|
|
212
232
|
/** This function gives the median of some counts, or null for none. */
|
|
213
|
-
const medianCount = (values) => values.length === 0 ? null :
|
|
233
|
+
const medianCount = (values) => values.length === 0 ? null : median([...values].sort((a, b) => a - b));
|
|
214
234
|
/** This function sums what the group of a group cell did in its counted runs, and tests each stage that has a band. */
|
|
215
235
|
const groupVerdictOf = (prediction, counted, delta = NOISE) => {
|
|
216
236
|
const noise = valueIn(delta, "s");
|
|
@@ -243,7 +263,7 @@ const groupVerdictOf = (prediction, counted, delta = NOISE) => {
|
|
|
243
263
|
return {
|
|
244
264
|
stage: band.stage,
|
|
245
265
|
band: interval,
|
|
246
|
-
median: values.length === 0 ? null : s(
|
|
266
|
+
median: values.length === 0 ? null : s(median(values)),
|
|
247
267
|
outside,
|
|
248
268
|
decision: outside.length === 0 && values.length > 0 ? "holds" : "fails"
|
|
249
269
|
};
|
|
@@ -255,7 +275,7 @@ const groupVerdictOf = (prediction, counted, delta = NOISE) => {
|
|
|
255
275
|
const at = run.group?.stages[stage];
|
|
256
276
|
return at === void 0 ? [] : [valueIn(at, "s")];
|
|
257
277
|
});
|
|
258
|
-
medians[stage] = s(
|
|
278
|
+
medians[stage] = s(median(values.sort((a, b) => a - b)));
|
|
259
279
|
}
|
|
260
280
|
const lostCounts = counted.flatMap((run) => run.group?.writes.lost === null || run.group === void 0 ? [] : [run.group.writes.lost.length]);
|
|
261
281
|
const oldCounts = counted.flatMap((run) => run.group === void 0 ? [] : [run.group.writes.old]);
|
|
@@ -283,7 +303,7 @@ const groupVerdictOf = (prediction, counted, delta = NOISE) => {
|
|
|
283
303
|
errors: [...errors].map(([error, firsts]) => ({
|
|
284
304
|
name: error,
|
|
285
305
|
runs: firsts.length,
|
|
286
|
-
first: s(
|
|
306
|
+
first: s(median(firsts.sort((a, b) => a - b)))
|
|
287
307
|
})),
|
|
288
308
|
...lags.length === 0 ? {} : { lags: spreadOf(lags) }
|
|
289
309
|
};
|
|
@@ -337,7 +357,7 @@ const verdictOfBand = (prediction, runs, delta = NOISE) => {
|
|
|
337
357
|
kinds.set(kind, (kinds.get(kind) ?? 0) + 1);
|
|
338
358
|
}
|
|
339
359
|
const outcomes = [...kinds].map(([kind, n]) => `${n} ${kind}`).join(", ");
|
|
340
|
-
const timed = times.length === 0 ? "no time" : `median ${s(
|
|
360
|
+
const timed = times.length === 0 ? "no time" : `median ${s(median(times)).value} s from ${prediction.from}, range [${s(times[0]).value}, ${s(times.at(-1)).value}] s`;
|
|
341
361
|
const missed = outside.filter((each) => counted.some((run) => name(run) === each.run && run.reconnect !== void 0));
|
|
342
362
|
const late = missed.length === 0 ? "" : ` ${missed.length} runs had a wait of the reconnect outside its band.`;
|
|
343
363
|
return {
|
|
@@ -345,7 +365,7 @@ const verdictOfBand = (prediction, runs, delta = NOISE) => {
|
|
|
345
365
|
decision: "measured",
|
|
346
366
|
band: null,
|
|
347
367
|
outside: missed,
|
|
348
|
-
median: times.length === 0 ? null : s(
|
|
368
|
+
median: times.length === 0 ? null : s(median(times)),
|
|
349
369
|
why: `${counted.length} runs measured: ${outcomes}; ${timed}.${late} ${prediction.why}`
|
|
350
370
|
};
|
|
351
371
|
}
|
|
@@ -362,13 +382,13 @@ const verdictOfBand = (prediction, runs, delta = NOISE) => {
|
|
|
362
382
|
reordering.fast,
|
|
363
383
|
reordering.seen
|
|
364
384
|
].some((count) => (count ?? 0) > 0) ? ` Reordering: ${reorderingWords(reordering)}.` : "";
|
|
365
|
-
const why = samples.length === 0 ? `${counted.length} runs measured, with no reply: ${prediction.why}` : `${counted.length} runs, ${samples.length} replies: median ${s(
|
|
385
|
+
const why = samples.length === 0 ? `${counted.length} runs measured, with no reply: ${prediction.why}` : `${counted.length} runs, ${samples.length} replies: median ${s(median(samples)).value} s, p99 ${s(quantileOf(samples, .99)).value} s, slowest ${s(samples.at(-1)).value} s, ${retransmissions} retransmissions, ${ended.length} connections ended.${reordered} ${prediction.why}`;
|
|
366
386
|
return {
|
|
367
387
|
...empty,
|
|
368
388
|
decision: "measured",
|
|
369
389
|
band: null,
|
|
370
390
|
outside: [],
|
|
371
|
-
median: samples.length === 0 ? null : s(
|
|
391
|
+
median: samples.length === 0 ? null : s(median(samples)),
|
|
372
392
|
...reordering === void 0 ? {} : { reordering },
|
|
373
393
|
why
|
|
374
394
|
};
|
|
@@ -411,7 +431,7 @@ const verdictOfBand = (prediction, runs, delta = NOISE) => {
|
|
|
411
431
|
why: "no run measured its time"
|
|
412
432
|
};
|
|
413
433
|
const [from, to] = medianInterval(values);
|
|
414
|
-
const median = s(
|
|
434
|
+
const median$1 = s(median(values));
|
|
415
435
|
const interval = {
|
|
416
436
|
low: s(from),
|
|
417
437
|
high: s(to)
|
|
@@ -424,13 +444,13 @@ const verdictOfBand = (prediction, runs, delta = NOISE) => {
|
|
|
424
444
|
const disjoint = to < wide.low || from > wide.high;
|
|
425
445
|
const off = new Set(outside.map((each) => each.run)).size;
|
|
426
446
|
const counts = `${counted.length - off} of ${counted.length} runs inside [${band.low.value}, ${band.high.value}] s`;
|
|
427
|
-
const centre = `median ${median.value} s, its interval [${interval.low.value}, ${interval.high.value}] s`;
|
|
447
|
+
const centre = `median ${median$1.value} s, its interval [${interval.low.value}, ${interval.high.value}] s`;
|
|
428
448
|
const result = {
|
|
429
449
|
counted: counted.length,
|
|
430
450
|
voided,
|
|
431
451
|
band,
|
|
432
452
|
outside,
|
|
433
|
-
median,
|
|
453
|
+
median: median$1,
|
|
434
454
|
medianInterval: interval
|
|
435
455
|
};
|
|
436
456
|
if (outside.length > 0 || disjoint) return {
|
|
@@ -483,12 +503,12 @@ const verdictOfBand = (prediction, runs, delta = NOISE) => {
|
|
|
483
503
|
* These are the runs 39390222333 and 39903020657 of the client repository.
|
|
484
504
|
*
|
|
485
505
|
* The bound is 1.5 ms: the maximum and a margin of 0.48 ms. The pairing of a drop with its act
|
|
486
|
-
* uses it, or
|
|
487
|
-
* catalog of the cells). Read the records again after a change to the subject, to Node or to
|
|
506
|
+
* uses it, or the pairing window of the run when that window is longer. The band of a drop adds
|
|
507
|
+
* it to its high bound (the WS catalog of the cells). Read the records again after a change to the subject, to Node or to
|
|
488
508
|
* the runners.
|
|
489
509
|
*/
|
|
490
510
|
const DROP_HANDLING = quantity(1.5, "ms");
|
|
491
|
-
/** This function gives the window of the act of a drop
|
|
511
|
+
/** This function gives the window of the act of a drop, in seconds: `DROP_HANDLING`, or the pairing window (`delta`) when it is longer. */
|
|
492
512
|
const dropWindow = (delta) => Math.max(valueIn(DROP_HANDLING, "s"), valueIn(delta, "s"));
|
|
493
513
|
/** This function gives the interval between two instants on the one clock, in seconds to the microsecond. */
|
|
494
514
|
const between$3 = (from, to) => quantity(Math.round((to - from) / 1e3) / 1e6, "s");
|
|
@@ -563,9 +583,9 @@ const closeOrExit = (line, left, exit, delta = NOISE) => {
|
|
|
563
583
|
};
|
|
564
584
|
/**
|
|
565
585
|
* This function tells how a drop differs from the way that its prediction gives, or gives null.
|
|
566
|
-
* A close closes the socket at once
|
|
567
|
-
*
|
|
568
|
-
* the socket at the drop. A peer that answers the close frame can close it, and that is no finding.
|
|
586
|
+
* A close closes the socket at once, in the handling time of the program (`DROP_HANDLING`). If
|
|
587
|
+
* the pairing window of the run (`delta`) is longer, that window is the limit. A close frame is a
|
|
588
|
+
* write, and the program does not close the socket at the drop. A peer that answers the close frame can close it, and that is no finding.
|
|
569
589
|
*/
|
|
570
590
|
const dropFinding = (expected, drop, left, delta = NOISE, exited) => {
|
|
571
591
|
const noise = dropWindow(delta);
|
|
@@ -578,7 +598,25 @@ const dropFinding = (expected, drop, left, delta = NOISE, exited) => {
|
|
|
578
598
|
return soon ? "the program closed its socket at the drop, where a close frame leaves it open" : null;
|
|
579
599
|
};
|
|
580
600
|
const isWrite = (record) => record.ev === "tx";
|
|
581
|
-
/**
|
|
601
|
+
/**
|
|
602
|
+
* This function measures the jitter of a program from its acts before `until`, the start of the
|
|
603
|
+
* fault. An act is a `write` line or a `ping` line on the connection. Its delay goes from the line
|
|
604
|
+
* to the first write of data on the socket after it, before the next act and before `until`. An
|
|
605
|
+
* act with no such write does not count. The bound is the longest delay, to the microsecond.
|
|
606
|
+
*/
|
|
607
|
+
const jitterOfLines = (lines, socket, local, until) => {
|
|
608
|
+
const acts = lines.filter((line) => (line.ev === "write" || line.ev === "ping") && line.t < until && onConnection(line, local));
|
|
609
|
+
const delays = acts.flatMap((line, at) => {
|
|
610
|
+
const next = Math.min(acts[at + 1]?.t ?? until, until);
|
|
611
|
+
const write = socket.find((record) => isWrite(record) && (record.seg?.len.value ?? 0) > 0 && record.mono >= line.t && record.mono < next);
|
|
612
|
+
return write === void 0 ? [] : [write.mono - line.t];
|
|
613
|
+
});
|
|
614
|
+
return {
|
|
615
|
+
acts: delays.length,
|
|
616
|
+
bound: delays.length === 0 ? null : quantity(Math.round(Math.max(...delays) / 1e3) / 1e3, "ms")
|
|
617
|
+
};
|
|
618
|
+
};
|
|
619
|
+
/** This function gives each ping of the program on the connection, with the kernel's stamp of its write in the pairing window (`delta`). */
|
|
582
620
|
const pingsOf = (lines, socket, local, delta = NOISE) => lines.filter((line) => line.ev === "ping" && onConnection(line, local)).map((line) => eventOf(socket, line, isWrite, delta));
|
|
583
621
|
/**
|
|
584
622
|
* This function gives the first ping that got no answer: no segment with data reached the socket
|
|
@@ -589,7 +627,7 @@ const firstUnanswered = (pings, socket, until = Number.POSITIVE_INFINITY) => pin
|
|
|
589
627
|
* This function gives the first drop of the connection by its program. The kernel stamps it as the
|
|
590
628
|
* write of a close frame. Or it stamps the change of the socket out of ESTABLISHED: a close or an
|
|
591
629
|
* abort. That stamp comes in the handling time of the program after the drop line
|
|
592
|
-
* (`DROP_HANDLING`)
|
|
630
|
+
* (`DROP_HANDLING`). If the pairing window of the run (`delta`) is longer, that window is the limit.
|
|
593
631
|
*/
|
|
594
632
|
const dropOf = (lines, socket, local, delta = NOISE) => {
|
|
595
633
|
const line = lines.find((each) => each.ev === "drop" && onConnection(each, local));
|
|
@@ -1680,7 +1718,11 @@ const crossingsOf = (run, hop, toClient, toTarget) => {
|
|
|
1680
1718
|
* than the one that the prediction gives is a finding.
|
|
1681
1719
|
*/
|
|
1682
1720
|
const measure = (cell, run) => {
|
|
1683
|
-
const
|
|
1721
|
+
const socketRead = measureSocket(cell, run);
|
|
1722
|
+
const read = run.jitter === void 0 ? socketRead : {
|
|
1723
|
+
...socketRead,
|
|
1724
|
+
pairing: pairingOf(cell, run)
|
|
1725
|
+
};
|
|
1684
1726
|
const expected = cell.prediction.request;
|
|
1685
1727
|
if (cell.probe.http === void 0 && expected === void 0) return read;
|
|
1686
1728
|
const request = requestOf(run.events);
|
|
@@ -1696,6 +1738,24 @@ const measure = (cell, run) => {
|
|
|
1696
1738
|
finding
|
|
1697
1739
|
};
|
|
1698
1740
|
};
|
|
1741
|
+
/**
|
|
1742
|
+
* This function measures the jitter of the program of the observer in a run, from its records
|
|
1743
|
+
* (`Jitter`). The acts count up to the start of the fault, or up to the reply of the client when
|
|
1744
|
+
* the fault has no stamp. A run with no lines of a program, or no socket of the observer, has no act.
|
|
1745
|
+
*/
|
|
1746
|
+
const jitterOf = (cell, run) => {
|
|
1747
|
+
const lines = programLines(cell, run);
|
|
1748
|
+
const ready = run.events.find((event) => event.ev === "ready");
|
|
1749
|
+
const place = lines.length === 0 || ready === void 0 ? void 0 : socketOf(cell, run);
|
|
1750
|
+
if (ready === void 0 || place === void 0) return {
|
|
1751
|
+
acts: 0,
|
|
1752
|
+
bound: null
|
|
1753
|
+
};
|
|
1754
|
+
const socket = run.kernel.filter((record) => record.netns === place.netns && record.cookie === place.cookie);
|
|
1755
|
+
const local = run.events.find((event) => event.ev === "connected")?.["local"];
|
|
1756
|
+
const named = cell.observer === "server" ? socket.find((record) => record.dst !== void 0)?.dst ?? local : local;
|
|
1757
|
+
return jitterOfLines(lines, socket, named, run.fault?.t0 ?? ready.t);
|
|
1758
|
+
};
|
|
1699
1759
|
/** This function tells how a request reading differs from its prediction, or gives null. */
|
|
1700
1760
|
const requestFinding = (expected, read) => {
|
|
1701
1761
|
if (read === null) return `the second request never went out, where it should meet: ${requestWords(expected)}`;
|
|
@@ -1847,7 +1907,8 @@ const measureSocket = (cell, run) => {
|
|
|
1847
1907
|
const lines = programLines(cell, run);
|
|
1848
1908
|
const named = server ? socket.find((record) => record.dst !== void 0)?.dst ?? local : local;
|
|
1849
1909
|
const kernelEnded = reported?.mono ?? closeWait?.mono ?? own?.mono ?? seen?.t;
|
|
1850
|
-
const
|
|
1910
|
+
const paired = pairingOf(cell, run).delta;
|
|
1911
|
+
const first = dropOf(lines, socket, named, paired);
|
|
1851
1912
|
const drop = first !== void 0 && (kernelEnded === void 0 || first.at <= kernelEnded) ? first : void 0;
|
|
1852
1913
|
const dropped = drop !== void 0;
|
|
1853
1914
|
const outcome = dropped ? { kind: "dropped" } : reported !== void 0 ? {
|
|
@@ -1860,7 +1921,7 @@ const measureSocket = (cell, run) => {
|
|
|
1860
1921
|
const ended = drop?.at ?? kernelEnded;
|
|
1861
1922
|
const noticed = reported !== void 0 && seen !== void 0 && !dropped ? between(reported.mono, seen.t) : null;
|
|
1862
1923
|
const { prediction } = cell;
|
|
1863
|
-
const pings = pingsOf(lines, socket, named,
|
|
1924
|
+
const pings = pingsOf(lines, socket, named, paired);
|
|
1864
1925
|
const before = run.fault?.t1 ?? ready.t;
|
|
1865
1926
|
const referenceAt = (from) => {
|
|
1866
1927
|
if (from === "request-sent") return request.t;
|
|
@@ -2052,7 +2113,7 @@ const measureSocket = (cell, run) => {
|
|
|
2052
2113
|
left: closed,
|
|
2053
2114
|
exited: void 0
|
|
2054
2115
|
} : closeOrExit(drop.line, closed, exitOf(run, cookie), noiseOf(cell));
|
|
2055
|
-
const how = prediction.drop === void 0 || drop === void 0 || left === void 0 ? null : dropFinding(prediction.drop, drop, left,
|
|
2116
|
+
const how = prediction.drop === void 0 || drop === void 0 || left === void 0 ? null : dropFinding(prediction.drop, drop, left, paired, exited);
|
|
2056
2117
|
const found = [
|
|
2057
2118
|
matches ? null : `it ended with ${words}, not ${prediction.errno}`,
|
|
2058
2119
|
late,
|
|
@@ -5581,14 +5642,18 @@ const inEnvironment = async (cell, environment, count, say) => {
|
|
|
5581
5642
|
if (latency !== null) await lab.netem(latency, "target");
|
|
5582
5643
|
await lab.warm();
|
|
5583
5644
|
const manifest = await lab.manifest(await lab.sysctl(cell.sysctls), settings, targetSysctls);
|
|
5645
|
+
const timed = (run) => ({
|
|
5646
|
+
...run,
|
|
5647
|
+
jitter: jitterOf(cell, run)
|
|
5648
|
+
});
|
|
5584
5649
|
const warmup = {
|
|
5585
|
-
...await once(lab, cell, environment, -1, endsEnvironment(cell)),
|
|
5650
|
+
...timed(await once(lab, cell, environment, -1, endsEnvironment(cell))),
|
|
5586
5651
|
warmup: true
|
|
5587
5652
|
};
|
|
5588
5653
|
say(line(cell, warmup, measure(cell, warmup)));
|
|
5589
5654
|
const runs = [];
|
|
5590
5655
|
for (let index = 0; index < count; index += 1) {
|
|
5591
|
-
const run = await once(lab, cell, environment, index);
|
|
5656
|
+
const run = timed(await once(lab, cell, environment, index));
|
|
5592
5657
|
runs.push(run);
|
|
5593
5658
|
say(line(cell, run, measure(cell, run)));
|
|
5594
5659
|
}
|
|
@@ -5740,6 +5805,6 @@ const runCell = async (cell, say = () => {}) => {
|
|
|
5740
5805
|
}
|
|
5741
5806
|
};
|
|
5742
5807
|
//#endregion
|
|
5743
|
-
export { CLIENT_NAMES, CLUSTER_STAGES, CONVERGE_MS, DROP_HANDLING, GIVES_AWAY, INJECT, KEPT, LINGER_MS, LISTING, MEMBER_MARKS, MONITOR_DOWN, NODE_MARKS, NOISE, PINNED, PUMP, PUMP_SLACK, QUIET_MS, RELATIVE, REPLICA_SET_STAGES, REPOSITORY, SHIPPED_CLIENTS, SHIPPED_NAMES, STAGES, STATUS_SCRIPT, STEPS, STEP_DOWN, amqpClientImage, callOf, clockOffsetOf, closeOrExit, clusterArgs, clusterConf, clusterCutOf, clusterHostsOf, clusterOnce, clusterStagesOf, clusterViewOf, crossingsOf, cutOf, deadlineOf, delayVoids, deviceOf, dropFinding, dropOf, endpointAfter, errorsOf, exitOf, fieldOf, fieldsOf, firstUnanswered, goHttpImage, groupOnce, groupVerdictOf, grpcClientImage, harnessImage, hikariClientImage, hzOf, imageOf, imageProblems, inContext, infoOf, initiateScript, isHopPlace, judge, lagsOf, latestEndOf, leftAfter, logNameOf, matches, measure, measureDriver, measureGroup, medianInterval, memberCommand, memberConfig, memberLineOf, mongoClientImage, monotonicOf, nodeClientImage, nodeCommand, nodeHttpImage, nodeLineOf, nodeNameOf, nodesOnMonotonic, noiseOf, onMonotonic, openClusterLab, openGroupLab, openLab, openReplicaSetLab, peersOf, pgClientImage, pingsOf, plainOf, planOf, programLines, programOf, quantileOf, reconnectFinding, reconnectOf, referenceOf, reorderingOf, replicaSetArgs, replicaSetOnce, replicaSetStagesOf, requestOf, requestWords, restamped, routerImage, routesOf, runCell, sentinelConfig, socketAt, socketOf, socketsOf, spread, spreadOf, stagesOf, statusViewOf, subjectClient, subjectProblems, subscriptionsOf, targetImageOf, targetSourceOf, templated, toolJsonOf, toxicBody, unlockedManifests, unpinnedBases, verdictOf, viewOf, writesOf };
|
|
5808
|
+
export { CLIENT_NAMES, CLUSTER_STAGES, CONVERGE_MS, DROP_HANDLING, GIVES_AWAY, INJECT, KEPT, LINGER_MS, LISTING, MEMBER_MARKS, MONITOR_DOWN, NODE_MARKS, NOISE, PINNED, PUMP, PUMP_SLACK, QUIET_MS, RELATIVE, REPLICA_SET_STAGES, REPOSITORY, SHIPPED_CLIENTS, SHIPPED_NAMES, STAGES, STATUS_SCRIPT, STEPS, STEP_DOWN, amqpClientImage, callOf, clockOffsetOf, closeOrExit, clusterArgs, clusterConf, clusterCutOf, clusterHostsOf, clusterOnce, clusterStagesOf, clusterViewOf, crossingsOf, cutOf, deadlineOf, delayVoids, deviceOf, dropFinding, dropOf, endpointAfter, errorsOf, exitOf, fieldOf, fieldsOf, firstUnanswered, goHttpImage, groupOnce, groupVerdictOf, grpcClientImage, harnessImage, hikariClientImage, hzOf, imageOf, imageProblems, inContext, infoOf, initiateScript, isHopPlace, jitterOf, jitterOfLines, judge, lagsOf, latestEndOf, leftAfter, logNameOf, matches, measure, measureDriver, measureGroup, medianInterval, memberCommand, memberConfig, memberLineOf, mongoClientImage, monotonicOf, nodeClientImage, nodeCommand, nodeHttpImage, nodeLineOf, nodeNameOf, nodesOnMonotonic, noiseOf, onMonotonic, openClusterLab, openGroupLab, openLab, openReplicaSetLab, pairingOf, pairingsOf, peersOf, pgClientImage, pingsOf, plainOf, planOf, programLines, programOf, quantileOf, reconnectFinding, reconnectOf, referenceOf, reorderingOf, replicaSetArgs, replicaSetOnce, replicaSetStagesOf, requestOf, requestWords, restamped, routerImage, routesOf, runCell, sentinelConfig, socketAt, socketOf, socketsOf, spread, spreadOf, stagesOf, statusViewOf, subjectClient, subjectProblems, subscriptionsOf, targetImageOf, targetSourceOf, templated, toolJsonOf, toxicBody, unlockedManifests, unpinnedBases, verdictOf, viewOf, writesOf };
|
|
5744
5809
|
|
|
5745
5810
|
//# sourceMappingURL=index.js.map
|