@mark1russell7/harness 0.11.4 → 0.11.6
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
CHANGED
|
@@ -162,6 +162,7 @@ The harness ships eight images, each as a shipped source (`ImageSource`). The ta
|
|
|
162
162
|
- **The HikariCP client image** (`image/hikari`) is HikariCP 7.1.0 over pgjdbc 42.7.13 on Temurin 21.0.12.1. The digests of the two stages and the SHA-256 of each jar pin them. The probe is `{ driver: { name: "hikari", query } }`.
|
|
163
163
|
- `ClientHikari.java` makes one `HikariDataSource` with the properties of the cell (`Cell.driverOptions`). A name with the prefix `dataSource.` is a property of pgjdbc.
|
|
164
164
|
- It prints the lines of the pg client on the same clock. Each socket comes from the `PGStream` of its connection, and a `pool` line gives each change of the counts of the pool. The errno of a failure is the SQLState of pgjdbc.
|
|
165
|
+
- Before its first line, it loads the classes of a connect and of a pool on the loopback of its namespace. It also starts the SecureRandom that HikariCP reads for the UUID of each new connection. A new JVM loads each class at its first use. Thus a cell that starts into a fault does not time that load.
|
|
165
166
|
- **The MongoDB client image** (`image/mongo`) is the driver mongodb 7.7.0 on Node 24.21.0. The digest of the image and an npm lockfile pin them. `client-mongo.mjs` prints the lines of the TCP client on the same clock:
|
|
166
167
|
- Each socket of the driver is a `socket` line with its role: `monitor`, `rtt` or `pool`. The stack of the call that makes the socket gives the role.
|
|
167
168
|
- The events of the driver are `sdam` lines (the heartbeats and the changes of each server), `cmap` lines (the pools) and `command` lines (each try of an operation).
|
|
@@ -229,6 +230,7 @@ Each run starts from kernels that keep nothing from the run before it (`lab.forg
|
|
|
229
230
|
- **A topology.** A run in a topology also gives the bytes that the client read after its request, and when a router forgot its flow (`forgot`).
|
|
230
231
|
- **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.
|
|
231
232
|
- **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.
|
|
233
|
+
- **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.
|
|
232
234
|
- **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.
|
|
233
235
|
- The program writes `ping` before each ping of its heartbeat. The kernel stamps the write of the ping (`tx`).
|
|
234
236
|
- 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.
|
|
@@ -222,8 +222,12 @@ interface Toxic {
|
|
|
222
222
|
* A heartbeat of a program counts from its first ping that got no answer (`ping-sent`). The
|
|
223
223
|
* program writes a `ping` line before each ping, and the kernel stamps the write (`tx`). No
|
|
224
224
|
* segment with data reaches the socket after that write, up to the detection.
|
|
225
|
+
*
|
|
226
|
+
* A check of a pool on an idle connection counts from the first segment with data that the socket
|
|
227
|
+
* sends after the fault (`first-sent`). The keepalive of HikariCP comes at a phase from the
|
|
228
|
+
* creation of its connection, thus no line of the client gives its time. The kernel stamps it.
|
|
225
229
|
*/
|
|
226
|
-
type Reference = "last-received" | "first-retransmission" | "request-sent" | "peer-closed" | "fault" | "client-start" | "ping-sent";
|
|
230
|
+
type Reference = "last-received" | "first-retransmission" | "request-sent" | "peer-closed" | "fault" | "client-start" | "ping-sent" | "first-sent";
|
|
227
231
|
/**
|
|
228
232
|
* This prediction tells when a connection moves again after a stall. That occurs at the first
|
|
229
233
|
* firing of its retransmission timer after the stall stops, and its reply comes back one round
|
|
@@ -996,4 +1000,4 @@ interface RunTopology {
|
|
|
996
1000
|
}
|
|
997
1001
|
//#endregion
|
|
998
1002
|
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 };
|
|
999
|
-
//# sourceMappingURL=cell-
|
|
1003
|
+
//# sourceMappingURL=cell-lSCgFB54.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-lSCgFB54.js";
|
|
2
2
|
import { Quantity } from "@mark1russell7/quantity";
|
|
3
3
|
import "testcontainers";
|
|
4
4
|
//#region src/application.d.ts
|
|
@@ -132,6 +132,7 @@ export declare const socketAt: (events: readonly ProbeEvent[], role: string, at:
|
|
|
132
132
|
* - `first-retransmission`: the first retransmission of the RTO timer on the socket.
|
|
133
133
|
* - `peer-closed`: the change of state of the socket of the target, when its process dies.
|
|
134
134
|
* - `fault`: the start of the commit of the fault. `client-start`: the `connecting` line.
|
|
135
|
+
* - `first-sent`: the first segment with data that the socket sends after the fault.
|
|
135
136
|
*/
|
|
136
137
|
export declare const referenceOf: (run: Run, from: Reference, role: string, data: boolean) => number | undefined;
|
|
137
138
|
/**
|
package/build/index.js
CHANGED
|
@@ -713,6 +713,7 @@ const outsetOf = (run) => {
|
|
|
713
713
|
* - `first-retransmission`: the first retransmission of the RTO timer on the socket.
|
|
714
714
|
* - `peer-closed`: the change of state of the socket of the target, when its process dies.
|
|
715
715
|
* - `fault`: the start of the commit of the fault. `client-start`: the `connecting` line.
|
|
716
|
+
* - `first-sent`: the first segment with data that the socket sends after the fault.
|
|
716
717
|
*/
|
|
717
718
|
const referenceOf = (run, from, role, data) => {
|
|
718
719
|
const ready = run.events.find((event) => event.ev === "ready");
|
|
@@ -726,6 +727,7 @@ const referenceOf = (run, from, role, data) => {
|
|
|
726
727
|
const counts = (record) => data ? (record.ev === "rx" || record.ev === "tx") && (record.seg?.len.value ?? 0) > 0 : record.ev === "rx";
|
|
727
728
|
return place.records.filter((record) => record.mono <= before && counts(record)).at(-1)?.mono;
|
|
728
729
|
}
|
|
730
|
+
if (from === "first-sent") return place.records.find((record) => record.ev === "tx" && record.mono > before && (record.seg?.len.value ?? 0) > 0)?.mono;
|
|
729
731
|
if (from === "first-retransmission") {
|
|
730
732
|
const request = run.events.filter((event) => event.ev === "sent")[1]?.t ?? before;
|
|
731
733
|
return place.records.find((record) => record.ev === "retrans" && record.why === "rto" && record.mono > request)?.mono;
|
|
@@ -1352,7 +1354,7 @@ const count = (event, field) => event === void 0 ? 0 : Number(event[field] ?? 0)
|
|
|
1352
1354
|
/** This function gives the view of the client on the same interval: TCP_INFO, with a sample each 2 ms. */
|
|
1353
1355
|
const socketVantage = (cell, events, ready, request) => {
|
|
1354
1356
|
const { from } = cell.prediction.detects === true ? cell.prediction : { from: void 0 };
|
|
1355
|
-
if (from === void 0 || from === "peer-closed" || from === "fault" || from === "ping-sent") return null;
|
|
1357
|
+
if (from === void 0 || from === "peer-closed" || from === "fault" || from === "ping-sent" || from === "first-sent") return null;
|
|
1356
1358
|
const ended = events.find((event) => event.ev === "error" || event.ev === "eof");
|
|
1357
1359
|
const reference = from === "last-received" ? ready : from === "request-sent" ? request : events.find((event) => event.ev === "kernel" && event.t >= request.t && count(event, "retransmits") > 0);
|
|
1358
1360
|
return ended === void 0 || reference === void 0 ? null : between(reference.t, ended.t);
|
|
@@ -1675,7 +1677,7 @@ const measureSocket = (cell, run) => {
|
|
|
1675
1677
|
if (from === "fault") return run.fault?.t0;
|
|
1676
1678
|
if (from === "client-start") return (events.find((event) => event.ev === "connecting") ?? events[0])?.t;
|
|
1677
1679
|
if (from === "ping-sent") return firstUnanswered(pings, socket, ended)?.at;
|
|
1678
|
-
return (from === "last-received" ? socket.filter((each) => each.ev === "rx" && each.mono <= before).at(-1) : from === "first-retransmission" ? retransmitted.find((each) => each.why === "rto") : kernel.find((each) => each.netns === peerNetns && each.cookie === peerCookie && each.ev === "state" && oldState(each) === 1))?.mono;
|
|
1680
|
+
return (from === "last-received" ? socket.filter((each) => each.ev === "rx" && each.mono <= before).at(-1) : from === "first-retransmission" ? retransmitted.find((each) => each.why === "rto") : 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))?.mono;
|
|
1679
1681
|
};
|
|
1680
1682
|
const lastRx = kernel.filter((each) => each.netns === run.netns && each.src === local && each.ev === "rx" && each.mono <= before).at(-1)?.mono ?? ready.t;
|
|
1681
1683
|
const chain = run.topology === void 0 ? {} : {
|