@mark1russell7/harness 0.11.11 → 0.11.12
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 -0
- package/build/{cell-6DQfSaJP.d.ts → cell-yNKJmsCj.d.ts} +5 -2
- package/build/index.d.ts +1 -1
- package/build/index.js +39 -6
- package/build/index.js.map +1 -1
- package/build/schema.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -241,6 +241,9 @@ Each run starts from kernels that keep nothing from the run before it (`lab.forg
|
|
|
241
241
|
- **Recovery.** After a stall (`prediction.recovers`), it times the send to the first segment back after the stall stopped. That segment is the answer of the server to the retransmission that got through. A run whose stall stopped outside the window of its prediction is void. A run where nothing came back is a finding.
|
|
242
242
|
- **An end of file.** A FIN counts from the change of state of the socket of the peer when it closes (`peer-closed`). It ends at the change of the socket of the observer to CLOSE_WAIT. The kernel stamps the two changes.
|
|
243
243
|
- **A check of a pool.** A check on an idle connection counts from the first segment with data that the socket sends after the fault (`first-sent`). The keepalive of HikariCP comes at a phase from the creation of its connection. Thus no line of the client gives its time, and the kernel stamps it. The prediction gives the latest time of that send after the reply (`startsBy`), and the run waits that much longer.
|
|
244
|
+
- **The connect of a pooler.** A band of a driver can be on the socket that a hop opens toward the target (`socket: "upstream"`). It is the first socket of a hop that moves to SYN_SENT after the outset. A pooler connects to the server by itself, thus no line of the client names that socket.
|
|
245
|
+
- A connect timer counts from the change of that socket to SYN_SENT (`syn-sent`).
|
|
246
|
+
- The band ends at the error that the kernel reports, for example ETIMEDOUT after the SYNs. Without an error, it ends when the program closes its socket in SYN_SENT (`closed`). That close has no error and no FIN, only the change to CLOSE. A refused connect also leaves SYN_SENT, but it has its error.
|
|
244
247
|
- **A detection by the program** (`application.ts`). The kernel has no report of it. Thus the program of the observer writes a line before each of its own acts, and the kernel stamps each act on the socket.
|
|
245
248
|
- The program writes `ping` before each ping of its heartbeat. The kernel stamps the write of the ping (`tx`).
|
|
246
249
|
- The reference is the first ping that got no answer (`ping-sent`): no segment with data reached the socket after its write, up to the detection. Its write starts the timer of the heartbeat that the fault met. The fault can come at any time, and its stamps are not necessary.
|
|
@@ -231,8 +231,11 @@ interface Toxic {
|
|
|
231
231
|
* A check of a pool on an idle connection counts from the first segment with data that the socket
|
|
232
232
|
* sends after the fault (`first-sent`). The keepalive of HikariCP comes at a phase from the
|
|
233
233
|
* creation of its connection, thus no line of the client gives its time. The kernel stamps it.
|
|
234
|
+
*
|
|
235
|
+
* A connect timer counts from the change of its socket to SYN_SENT (`syn-sent`). A pooler connects
|
|
236
|
+
* to the server by itself, thus the kernel stamps that connect, and no line of the client does.
|
|
234
237
|
*/
|
|
235
|
-
type Reference = "last-received" | "first-retransmission" | "request-sent" | "peer-closed" | "fault" | "client-start" | "ping-sent" | "first-sent";
|
|
238
|
+
type Reference = "last-received" | "first-retransmission" | "request-sent" | "peer-closed" | "fault" | "client-start" | "ping-sent" | "first-sent" | "syn-sent";
|
|
236
239
|
/**
|
|
237
240
|
* This prediction tells when a connection moves again after a stall. That occurs at the first
|
|
238
241
|
* firing of its retransmission timer after the stall stops, and its reply comes back one round
|
|
@@ -1018,4 +1021,4 @@ interface RunTopology {
|
|
|
1018
1021
|
}
|
|
1019
1022
|
//#endregion
|
|
1020
1023
|
export { isHopPlace as $, Recovers as A, RunPart as B, Observer as C, ProxyHop as D, ProbeEvent as E, RequestPrediction as F, ShippedImage as G, SentinelEvent as H, RouterHop as I, Subject as J, Stage as K, RttRange as L, ReplicaSet as M, ReplicaSetStage as N, ProxyTime as O, Replies as P, WsProbe as Q, Run as R, MiddleboxForm as S, Prediction as T, SentinelStage as U, RunTopology as V, Shipped as W, Topology as X, Target as Y, Toxic as Z, ImageSource as _, DriverBand as a, MiddleboxEvent as b, FaultPlace as c, GroupPrediction as d, latestEndOf as et, GroupRole as f, HttpProbe as g, HopPlace as h, ClientImage as i, Reference as j, Reconnects as k, Group as l, Hop as m, Cell as n, DriverStep as o, HarnessImage as p, StageBand as q, Client as r, Fault as s, BuildImage as t, GroupPlace as u, KernelRecord as v, PinnedImage as w, MiddleboxExpectation as x, LineMatch as y, RunGroup as z };
|
|
1021
|
-
//# sourceMappingURL=cell-
|
|
1024
|
+
//# sourceMappingURL=cell-yNKJmsCj.d.ts.map
|
package/build/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as isHopPlace, A as Recovers, B as RunPart, C as Observer, D as ProxyHop, E as ProbeEvent, F as RequestPrediction, G as ShippedImage, H as SentinelEvent, I as RouterHop, J as Subject, K as Stage, L as RttRange, M as ReplicaSet, N as ReplicaSetStage, O as ProxyTime, P as Replies, Q as WsProbe, R as Run, S as MiddleboxForm, T as Prediction, U as SentinelStage, V as RunTopology, W as Shipped, X as Topology, Y as Target, Z as Toxic, _ as ImageSource, a as DriverBand, b as MiddleboxEvent, c as FaultPlace, d as GroupPrediction, et as latestEndOf, f as GroupRole, g as HttpProbe, h as HopPlace, i as ClientImage, j as Reference, k as Reconnects, l as Group, m as Hop, n as Cell, o as DriverStep, p as HarnessImage, q as StageBand, r as Client, s as Fault, t as BuildImage, u as GroupPlace, v as KernelRecord, w as PinnedImage, x as MiddleboxExpectation, y as LineMatch, z as RunGroup } from "./cell-
|
|
1
|
+
import { $ as isHopPlace, A as Recovers, B as RunPart, C as Observer, D as ProxyHop, E as ProbeEvent, F as RequestPrediction, G as ShippedImage, H as SentinelEvent, I as RouterHop, J as Subject, K as Stage, L as RttRange, M as ReplicaSet, N as ReplicaSetStage, O as ProxyTime, P as Replies, Q as WsProbe, R as Run, S as MiddleboxForm, T as Prediction, U as SentinelStage, V as RunTopology, W as Shipped, X as Topology, Y as Target, Z as Toxic, _ as ImageSource, a as DriverBand, b as MiddleboxEvent, c as FaultPlace, d as GroupPrediction, et as latestEndOf, f as GroupRole, g as HttpProbe, h as HopPlace, i as ClientImage, j as Reference, k as Reconnects, l as Group, m as Hop, n as Cell, o as DriverStep, p as HarnessImage, q as StageBand, r as Client, s as Fault, t as BuildImage, u as GroupPlace, v as KernelRecord, w as PinnedImage, x as MiddleboxExpectation, y as LineMatch, z as RunGroup } from "./cell-yNKJmsCj.js";
|
|
2
2
|
import { Quantity } from "@mark1russell7/quantity";
|
|
3
3
|
import "testcontainers";
|
|
4
4
|
//#region src/application.d.ts
|
package/build/index.js
CHANGED
|
@@ -682,8 +682,28 @@ const peerPlace = (run, local) => {
|
|
|
682
682
|
const peer = run.topology === void 0 ? local : `${run.topology.targetPeer}:${portOf(local)}`;
|
|
683
683
|
return placeOf(run, run.targetNetns, (record) => record.dst === peer);
|
|
684
684
|
};
|
|
685
|
-
/**
|
|
685
|
+
/**
|
|
686
|
+
* This function gives the socket that a hop of the topology opens toward its target in the run. It is
|
|
687
|
+
* the first one that moves to SYN_SENT after the outset. A pooler connects to the server by itself,
|
|
688
|
+
* thus no line of the client names that socket. The last hop goes first, because it faces the target.
|
|
689
|
+
*/
|
|
690
|
+
const upstreamOf = (run) => {
|
|
691
|
+
if (run.topology === void 0) return void 0;
|
|
692
|
+
const outset = outsetOf(run);
|
|
693
|
+
for (const hop of Object.values(run.topology.hops).reverse()) {
|
|
694
|
+
const place = placeOf(run, hop.netns, (record) => record.ev === "state" && newState$1(record) === 2 && record.mono >= outset && record.dst === hop.target);
|
|
695
|
+
if (place !== void 0) return place;
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
/**
|
|
699
|
+
* This function gives the kernel place of a socket of a role at an instant. The role `server` is a
|
|
700
|
+
* socket of the target, and the role `upstream` is the socket that a hop opens toward the target.
|
|
701
|
+
*/
|
|
686
702
|
const kernelOf = (run, role, at) => {
|
|
703
|
+
if (role === "upstream") return {
|
|
704
|
+
socket: void 0,
|
|
705
|
+
place: upstreamOf(run)
|
|
706
|
+
};
|
|
687
707
|
if (role === "server") {
|
|
688
708
|
const pool = socketAt(run.events, "pool", at);
|
|
689
709
|
return {
|
|
@@ -728,6 +748,7 @@ const referenceOf = (run, from, role, data) => {
|
|
|
728
748
|
return place.records.filter((record) => record.mono <= before && counts(record)).at(-1)?.mono;
|
|
729
749
|
}
|
|
730
750
|
if (from === "first-sent") return place.records.find((record) => record.ev === "tx" && record.mono > before && (record.seg?.len.value ?? 0) > 0)?.mono;
|
|
751
|
+
if (from === "syn-sent") return place.records.find((record) => record.ev === "state" && newState$1(record) === 2)?.mono;
|
|
731
752
|
if (from === "first-retransmission") {
|
|
732
753
|
const request = run.events.filter((event) => event.ev === "sent")[1]?.t ?? before;
|
|
733
754
|
return place.records.find((record) => record.ev === "retrans" && record.why === "rto" && record.mono > request)?.mono;
|
|
@@ -755,10 +776,21 @@ const ipOf$1 = (address) => address.slice(0, address.lastIndexOf(":"));
|
|
|
755
776
|
const lineAfter = (events, match, after) => events.find((event) => event.t > after && matches(event, match));
|
|
756
777
|
/** This function gives the name of the error of a line: the field that the match names, or `name`. */
|
|
757
778
|
const nameOf = (line, match) => String(fieldOf(line, match.name ?? "name") ?? line.ev);
|
|
758
|
-
/**
|
|
779
|
+
/**
|
|
780
|
+
* This function gives the report of the kernel on a socket after an instant: an error, or the end of
|
|
781
|
+
* the file (CLOSE_WAIT). With neither, a close of the socket in SYN_SENT is the end. The program gave
|
|
782
|
+
* up on its connect, and the kernel reports no error and sends no FIN. A refused connect also leaves
|
|
783
|
+
* SYN_SENT, but it has its error.
|
|
784
|
+
*/
|
|
759
785
|
const reportOf = (place, after) => {
|
|
760
786
|
const report = place.records.find((record) => record.mono > after && (record.ev === "error" && (record.err ?? 0) !== 0 || record.ev === "state" && newState$1(record) === 8));
|
|
761
|
-
if (report === void 0)
|
|
787
|
+
if (report === void 0) {
|
|
788
|
+
const given = place.records.find((record) => record.mono > after && record.ev === "state" && oldState$1(record) === 2 && newState$1(record) === 7);
|
|
789
|
+
return given === void 0 ? void 0 : {
|
|
790
|
+
at: given.mono,
|
|
791
|
+
outcome: { kind: "closed" }
|
|
792
|
+
};
|
|
793
|
+
}
|
|
762
794
|
return report.ev === "error" ? {
|
|
763
795
|
at: report.mono,
|
|
764
796
|
outcome: {
|
|
@@ -972,7 +1004,7 @@ const measureDriver = (cell, run) => {
|
|
|
972
1004
|
finding: `it ended without its reference event (${prediction.from} on the ${driver.socket} socket)`
|
|
973
1005
|
};
|
|
974
1006
|
if (driver.ends === void 0 && prediction.from === "last-received" && place !== void 0) voided ??= delayed(place, reference, ended, run.hz, noiseOf(cell));
|
|
975
|
-
const name = outcome.kind === "error" ? outcome.errno : outcome.kind === "eof" ? "EOF" : "silent";
|
|
1007
|
+
const name = outcome.kind === "error" ? outcome.errno : outcome.kind === "eof" ? "EOF" : outcome.kind === "closed" ? "CLOSED" : "silent";
|
|
976
1008
|
if (prediction.errno !== "OK" && name !== prediction.errno) findings.unshift(`it ended with ${name}, not ${prediction.errno}`);
|
|
977
1009
|
const seen = report === void 0 ? void 0 : events.find((event) => event.t >= report.at && (event.ev === "error" || event.ev === "socket-error"));
|
|
978
1010
|
return {
|
|
@@ -1694,7 +1726,7 @@ const measureSocket = (cell, run) => {
|
|
|
1694
1726
|
if (from === "fault") return run.fault?.t0;
|
|
1695
1727
|
if (from === "client-start") return (events.find((event) => event.ev === "connecting") ?? events[0])?.t;
|
|
1696
1728
|
if (from === "ping-sent") return firstUnanswered(pings, socket, ended)?.at;
|
|
1697
|
-
const record = from === "last-received" ? socket.filter((each) => each.ev === "rx" && each.mono <= before).at(-1) : from === "first-retransmission" ? retransmitted.find((each) => each.why === "rto" && each.mono > before) : from === "first-sent" ? socket.find((each) => each.ev === "tx" && each.mono > before && (each.seg?.len.value ?? 0) > 0) : kernel.find((each) => each.netns === peerNetns && each.cookie === peerCookie && each.ev === "state" && oldState(each) === 1);
|
|
1729
|
+
const record = from === "last-received" ? socket.filter((each) => each.ev === "rx" && each.mono <= before).at(-1) : from === "first-retransmission" ? retransmitted.find((each) => each.why === "rto" && each.mono > before) : from === "first-sent" ? socket.find((each) => each.ev === "tx" && each.mono > before && (each.seg?.len.value ?? 0) > 0) : from === "syn-sent" ? socket.find((each) => each.ev === "state" && newState(each) === 2) : kernel.find((each) => each.netns === peerNetns && each.cookie === peerCookie && each.ev === "state" && oldState(each) === 1);
|
|
1698
1730
|
if (record === void 0 && from === "peer-closed" && peerCookie === void 0) return proxiedClose(run);
|
|
1699
1731
|
return record?.mono;
|
|
1700
1732
|
};
|
|
@@ -4220,7 +4252,8 @@ const beforeOnce = async (lab, cell, environment, index) => {
|
|
|
4220
4252
|
kernel: lab.kernel.slice(from),
|
|
4221
4253
|
netns: lab.netns.client,
|
|
4222
4254
|
targetNetns: lab.netns.target,
|
|
4223
|
-
lost: 0
|
|
4255
|
+
lost: 0,
|
|
4256
|
+
...lab.topology === null ? {} : { topology: lab.topology }
|
|
4224
4257
|
});
|
|
4225
4258
|
await driverOutcome(cell, current, driverWithin(cell));
|
|
4226
4259
|
await sleep(TAIL_MS);
|