@mark1russell7/harness 0.12.0 → 0.12.1

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
@@ -293,13 +293,15 @@ Each run starts from kernels that keep nothing from the run before it (`lab.forg
293
293
  - **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.
294
294
  - The program writes `ping` before each ping of its heartbeat. The kernel stamps the write of the ping (`tx`).
295
295
  - 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.
296
- - The program writes `drop` before it drops the connection itself. The detection is the kernel's stamp of that drop: the write of its close frame, or the change of its socket out of ESTABLISHED. Without such a record in δ_abs, it is the stamp of the line.
296
+ - The program writes `drop` before it drops the connection itself. The detection is the kernel's stamp of that drop: the write of its close frame, or the change of its socket out of ESTABLISHED. Without such a record in the handling time of the program (`DROP_HANDLING`, 1.5 ms), it is the stamp of the line. Where δ_abs is longer, the window is δ_abs.
297
+ - The handling time is not δ_abs. δ_abs is the noise of the pipeline, from a reset. The handling is the time of the code of the program, from the firing of its timer to its act.
298
+ - In 585 drops with a close frame in CI, the write came a median of 0.652 ms after the `drop` line, and 1.017 ms at the most. Two of them came more than the δ_abs of 1 ms after it. Each failed its cell, with its time in the band. These are the runs 39390222333 and 39903020657 of the client repository. The bound is that maximum and a margin of 0.48 ms.
297
299
  - A drop counts when it comes before each report of the kernel. A report of the kernel that comes first is the detection, and the drop after it is not.
298
300
  - The second view is the stamps of the program: from its `ping` line to its `drop` line. The steps are the later pings, each from the reference.
299
301
  - The lines of a client name the socket by its local address (`local`), and the lines of a server by its peer (`peer`). For the server, the lines are the lines of the target. A line whose address is null is about a try that did not open.
300
302
  - The harness reads the peer of a server from the records of its socket. Behind a router, that peer is the address of the router, not the address of the client.
301
303
  - A first ping without an answer can come late, for example at a beat of a server whose phase no document gives. Then the prediction gives its latest time after the reply (`startsBy`), and the run waits that much longer.
302
- - A prediction can say how the program drops (`drop`). A close frame (`frame`) is a write, and the socket stays ESTABLISHED after it. A close (`close`) closes the socket in δ_abs: a FIN or an abort. Another drop is a finding. A FIN of the peer that answers a close frame is no close by the program. The run gives the time from the `drop` line to the close by the program (`left`).
304
+ - A prediction can say how the program drops (`drop`). A close frame (`frame`) is a write, and the socket stays ESTABLISHED after it. A close (`close`) closes the socket at once, in the same window: a FIN or an abort. Another drop is a finding. A FIN of the peer that answers a close frame is no close by the program. The run gives the time from the `drop` line to the close by the program (`left`).
303
305
  - The client process ends at the end of each run, and its kernel then closes each socket that is still open. A prediction can say that the program is that client process (`exits`). Then a close in δ_abs of that end is no close by the program: `left` stays null, and `exited` gives the time.
304
306
  - The end of the process is the first change out of ESTABLISHED of another socket of the client after its last `dial` line (`exitOf`). The program dropped none of these sockets.
305
307
  - A heartbeat is a timer of the program. The retransmit timer of its ping fires in the same interval. Thus a run whose retransmit timer was two jiffies or more behind its wheel slot is void: the VM stopped a vCPU.
@@ -351,8 +353,9 @@ Each run starts from kernels that keep nothing from the run before it (`lab.forg
351
353
  `verdictOf(prediction, runs)` (`verdict.ts`) judges a cell:
352
354
 
353
355
  - **Containment.** Each run lands in [T_lo − δ_abs, T_hi + δ_abs]. `NOISE` (δ_abs) is 4 ms, from the calibration of the first environment: the worst reset took 1.141 ms, and δ_abs is one jiffy at the minimum.
354
- - **δ_abs of an environment.** A cell can give the δ_abs of its environment (`Cell.noise`). Stage 0 measures it in each environment. On a hosted runner of GitHub at HZ 1000, the worst reset took 0.147 ms, thus δ_abs is one jiffy, 1 ms. These read it (`noiseOf`): the bands, the pairing of a program line with its kernel record, and the drop of a program.
356
+ - **δ_abs of an environment.** A cell can give the δ_abs of its environment (`Cell.noise`). Stage 0 measures it in each environment. On a hosted runner of GitHub at HZ 1000, the worst reset took 0.147 ms, thus δ_abs is one jiffy, 1 ms. These read it (`noiseOf`): the bands, the pairing of a program line with its kernel record, and the drop of a program (with `DROP_HANDLING`).
355
357
  - **The injector has its own bound.** A fault that the injector commits or lifts late makes a run void. That bound is `INJECT` (4 ms), not δ_abs. Stage 0 measures the commit apart. On a hosted runner it took up to 2.75 ms at 4 environments.
358
+ - **The drop of a program has its own bound.** The pairing of a `drop` line with its act uses `DROP_HANDLING` (1.5 ms), or δ_abs when δ_abs is longer. The band of a drop in the cells adds `DROP_HANDLING` to its high bound.
356
359
  - **Median equivalence.** The order-statistic interval of the median must be in the band, made 5 % wider.
357
360
  - **Extension.** A median across the edge of the band extends the cell from 11 runs to 22, then 44. Then the verdict is inconclusive.
358
361
  - **Recovery.** The recovery after a stall gets the same test as a detection, by its band. A detection is then a finding.
package/build/index.d.ts CHANGED
@@ -2,10 +2,47 @@ import { $ as Subject, A as Prediction, B as RequestPrediction, C as KernelRecor
2
2
  import { Quantity } from "@mark1russell7/quantity";
3
3
  import "testcontainers";
4
4
  //#region src/application.d.ts
5
+ /**
6
+ * This module reads the acts of the program of the observer: its heartbeat, its drop of the
7
+ * connection, its reconnect and its call in flight. The kernel has no report of a detection by
8
+ * a program. Thus the program writes a line before each of its own acts, on CLOCK_MONOTONIC:
9
+ * - `ping` before each ping of its heartbeat, and `drop` before it closes the connection by itself.
10
+ * - `reconnecting` when it starts its reconnect timer, and `dial` before each new connection.
11
+ *
12
+ * The kernel then stamps each write of the program on the socket (`tx`) and each change of the
13
+ * state of the socket. A line of the client names its socket by its local address (`local`), and
14
+ * a line of a server names it by its peer (`peer`).
15
+ */
16
+ /**
17
+ * This time bounds the handling of a drop by the program of the observer. It starts when the timer
18
+ * of the program fires. It ends at the kernel's stamp of the act: the write of a close frame, or
19
+ * the close of the socket. The `drop` line comes in that time, before the act.
20
+ *
21
+ * This bound is not δ_abs. δ_abs is the noise of the pipeline, and stage 0 calibrates it from a
22
+ * reset. The handling is the time of the code of the program, and it is longer:
23
+ * - No source and no machine document bounds it (`http/timers.ts` of `@mark1russell7/machines`).
24
+ * - The handling time of the HTTP cells (`HANDLING` in `packages/cells/src/http/race.ts`) is
25
+ * another act. It is the first reply of a new process, up to 11.182 ms.
26
+ * - A drop comes from a timer, long after the start of the process.
27
+ *
28
+ * The bound comes from the CI records of the WS and WST cells, from the `drop` line to the act:
29
+ * - 585 drops with a close frame had a median of 0.652 ms, a 99th percentile of 0.87 ms and a
30
+ * maximum of 1.017 ms.
31
+ * - 559 drops with a close of the socket had a maximum of 0.914 ms.
32
+ * - Two drops took more than the δ_abs of 1 ms. Each failed its cell, and its time was in the band.
33
+ * These are the runs 39390222333 and 39903020657 of the client repository.
34
+ *
35
+ * The bound is 1.5 ms: the maximum and a margin of 0.48 ms. The pairing of a drop with its act
36
+ * uses it, or δ_abs when δ_abs is longer. The band of a drop adds it to its high bound (the WS
37
+ * catalog of the cells). Read the records again after a change to the subject, to Node or to
38
+ * the runners.
39
+ */
40
+ export declare const DROP_HANDLING: Quantity;
5
41
  /**
6
42
  * A program event is a line of the program of the observer, with the kernel's stamp of its act.
7
- * The act is a write, or a change of state of the socket. Without a record of the kernel in δ_abs
8
- * after the line, the instant is the stamp of the line.
43
+ * The act is a write, or a change of state of the socket. Without a record of the kernel in its
44
+ * window after the line, the instant is the stamp of the line. The window is δ_abs, and for a drop
45
+ * it is `DROP_HANDLING` when that is longer.
9
46
  */
10
47
  interface ProgramEvent {
11
48
  readonly line: ProbeEvent;
@@ -42,7 +79,8 @@ export declare const closeOrExit: (line: ProbeEvent, left: Quantity | null, exit
42
79
  };
43
80
  /**
44
81
  * This function tells how a drop differs from the way that its prediction gives, or gives null.
45
- * A close closes the socket in δ_abs. A close frame is a write, and the program does not close
82
+ * A close closes the socket at once: in the handling time of the program (`DROP_HANDLING`), or in
83
+ * δ_abs (`delta`) when δ_abs is longer. A close frame is a write, and the program does not close
46
84
  * the socket at the drop. A peer that answers the close frame can close it, and that is no finding.
47
85
  */
48
86
  export declare const dropFinding: (expected: "frame" | "close", drop: ProgramEvent, left: Quantity | null, delta?: Quantity, exited?: Quantity) => string | null;
@@ -56,7 +94,8 @@ export declare const firstUnanswered: (pings: readonly ProgramEvent[], socket: r
56
94
  /**
57
95
  * This function gives the first drop of the connection by its program. The kernel stamps it as the
58
96
  * write of a close frame. Or it stamps the change of the socket out of ESTABLISHED: a close or an
59
- * abort.
97
+ * abort. That stamp comes in the handling time of the program after the drop line
98
+ * (`DROP_HANDLING`), or in δ_abs (`delta`) when δ_abs is longer.
60
99
  */
61
100
  export declare const dropOf: (lines: readonly ProbeEvent[], socket: readonly KernelRecord[], local: unknown, delta?: Quantity) => ProgramEvent | undefined;
62
101
  /** A reconnect reading is what the client did after the detection, from its lines and from the records of the kernel. */
package/build/index.js CHANGED
@@ -463,6 +463,33 @@ const verdictOfBand = (prediction, runs, delta = NOISE) => {
463
463
  * state of the socket. A line of the client names its socket by its local address (`local`), and
464
464
  * a line of a server names it by its peer (`peer`).
465
465
  */
466
+ /**
467
+ * This time bounds the handling of a drop by the program of the observer. It starts when the timer
468
+ * of the program fires. It ends at the kernel's stamp of the act: the write of a close frame, or
469
+ * the close of the socket. The `drop` line comes in that time, before the act.
470
+ *
471
+ * This bound is not δ_abs. δ_abs is the noise of the pipeline, and stage 0 calibrates it from a
472
+ * reset. The handling is the time of the code of the program, and it is longer:
473
+ * - No source and no machine document bounds it (`http/timers.ts` of `@mark1russell7/machines`).
474
+ * - The handling time of the HTTP cells (`HANDLING` in `packages/cells/src/http/race.ts`) is
475
+ * another act. It is the first reply of a new process, up to 11.182 ms.
476
+ * - A drop comes from a timer, long after the start of the process.
477
+ *
478
+ * The bound comes from the CI records of the WS and WST cells, from the `drop` line to the act:
479
+ * - 585 drops with a close frame had a median of 0.652 ms, a 99th percentile of 0.87 ms and a
480
+ * maximum of 1.017 ms.
481
+ * - 559 drops with a close of the socket had a maximum of 0.914 ms.
482
+ * - Two drops took more than the δ_abs of 1 ms. Each failed its cell, and its time was in the band.
483
+ * These are the runs 39390222333 and 39903020657 of the client repository.
484
+ *
485
+ * 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 δ_abs when δ_abs is longer. The band of a drop adds it to its high bound (the WS
487
+ * catalog of the cells). Read the records again after a change to the subject, to Node or to
488
+ * the runners.
489
+ */
490
+ const DROP_HANDLING = quantity(1.5, "ms");
491
+ /** This function gives the window of the act of a drop after its line, in seconds: `DROP_HANDLING`, or δ_abs when δ_abs is longer. */
492
+ const dropWindow = (delta) => Math.max(valueIn(DROP_HANDLING, "s"), valueIn(delta, "s"));
466
493
  /** This function gives the interval between two instants on the one clock, in seconds to the microsecond. */
467
494
  const between$3 = (from, to) => quantity(Math.round((to - from) / 1e3) / 1e6, "s");
468
495
  /** This function gives the state of a state record after the change, and before it. TCP_ESTABLISHED is 1, TCP_SYN_SENT 2. */
@@ -485,7 +512,7 @@ const onConnection = (line, local) => {
485
512
  if (!("local" in line) && !("peer" in line)) return true;
486
513
  return (line["local"] ?? line["peer"]) === local;
487
514
  };
488
- /** This function gives the first record of a socket that matches, at the stamp of a line or in δ_abs after it. */
515
+ /** This function gives the first record of a socket that matches, at the stamp of a line or in a window (`delta`) after it. */
489
516
  const kernelAt = (socket, line, matches, delta) => {
490
517
  const noise = valueIn(delta, "s") * 1e9;
491
518
  return socket.find((record) => record.mono >= line.t && record.mono <= line.t + noise && matches(record));
@@ -536,11 +563,12 @@ const closeOrExit = (line, left, exit, delta = NOISE) => {
536
563
  };
537
564
  /**
538
565
  * This function tells how a drop differs from the way that its prediction gives, or gives null.
539
- * A close closes the socket in δ_abs. A close frame is a write, and the program does not close
566
+ * A close closes the socket at once: in the handling time of the program (`DROP_HANDLING`), or in
567
+ * δ_abs (`delta`) when δ_abs is longer. A close frame is a write, and the program does not close
540
568
  * the socket at the drop. A peer that answers the close frame can close it, and that is no finding.
541
569
  */
542
570
  const dropFinding = (expected, drop, left, delta = NOISE, exited) => {
543
- const noise = valueIn(delta, "s");
571
+ const noise = dropWindow(delta);
544
572
  const soon = left !== null && valueIn(left, "s") <= noise;
545
573
  if (expected === "close") {
546
574
  if (left === null) return `the program did not close its socket after the drop, where a close is at once${exited === void 0 ? "" : ": it stayed open until the client process ended"}`;
@@ -560,11 +588,12 @@ const firstUnanswered = (pings, socket, until = Number.POSITIVE_INFINITY) => pin
560
588
  /**
561
589
  * This function gives the first drop of the connection by its program. The kernel stamps it as the
562
590
  * write of a close frame. Or it stamps the change of the socket out of ESTABLISHED: a close or an
563
- * abort.
591
+ * abort. That stamp comes in the handling time of the program after the drop line
592
+ * (`DROP_HANDLING`), or in δ_abs (`delta`) when δ_abs is longer.
564
593
  */
565
594
  const dropOf = (lines, socket, local, delta = NOISE) => {
566
595
  const line = lines.find((each) => each.ev === "drop" && onConnection(each, local));
567
- return line === void 0 ? void 0 : eventOf(socket, line, (record) => isWrite(record) || record.ev === "state" && oldState$2(record) === 1, delta);
596
+ return line === void 0 ? void 0 : eventOf(socket, line, (record) => isWrite(record) || record.ev === "state" && oldState$2(record) === 1, quantity(dropWindow(delta), "s"));
568
597
  };
569
598
  /**
570
599
  * This function reads the reconnect of the client after the detection at `detected`. The socket of
@@ -5699,6 +5728,6 @@ const runCell = async (cell, say = () => {}) => {
5699
5728
  }
5700
5729
  };
5701
5730
  //#endregion
5702
- export { CLIENT_NAMES, CLUSTER_STAGES, CONVERGE_MS, 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 };
5731
+ 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 };
5703
5732
 
5704
5733
  //# sourceMappingURL=index.js.map