@mark1russell7/kind 0.11.1 → 0.11.3
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/build/index.d.ts +5 -3
- package/build/index.js +37 -18
- package/build/index.js.map +1 -1
- package/build/{judge-Bb4ebE9V.js → judge-BHygFh4Z.js} +8 -3
- package/build/{judge-Bb4ebE9V.js.map → judge-BHygFh4Z.js.map} +1 -1
- package/build/{judge-C3mbgYxY.d.ts → judge-yWlioigZ.d.ts} +16 -1
- package/build/judge.d.ts +1 -1
- package/build/judge.js +1 -1
- package/image/client.mjs +38 -4
- package/package.json +2 -2
|
@@ -2,6 +2,7 @@ import { Extent, Quantity } from "@mark1russell7/quantity";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { Coupling, Gate, Poll, Stage, Timing } from "@mark1russell7/service";
|
|
4
4
|
import { RedisKnobs } from "@mark1russell7/service/redis";
|
|
5
|
+
import { SessionCheckKnobs } from "@mark1russell7/service/http-client";
|
|
5
6
|
//#region src/scenario.d.ts
|
|
6
7
|
/** A kube-proxy mode is the dataplane of each node: iptables (the default of kind), IPVS or nftables. */
|
|
7
8
|
type KubeProxyMode = "iptables" | "ipvs" | "nftables";
|
|
@@ -121,6 +122,7 @@ type Stack = "service" | "grpc";
|
|
|
121
122
|
* - `rst` and `blackhole` are the rules of the injector of the harness in the namespace of Redis. In
|
|
122
123
|
* T15 they are in the namespace of each replica. A black hole of T15 can stop the calls of the
|
|
123
124
|
* clients before the fault (`quiet`). It can also set `tcp_retries2` of each client pod (`retries`).
|
|
125
|
+
* A black hole with `partition` is in the namespace of the target replica only, with the client pods as peers.
|
|
124
126
|
* - `peer-gone-without-close` drops the segments of Redis, and then Redis goes away.
|
|
125
127
|
* - `app-stall` blocks the event loop of one replica.
|
|
126
128
|
* - `rollout` is a rolling update while Redis is down.
|
|
@@ -182,6 +184,13 @@ interface Trigger<A = Quantity> {
|
|
|
182
184
|
* last use is at the fault. The heal opens a new channel again.
|
|
183
185
|
*/
|
|
184
186
|
readonly close?: boolean | undefined;
|
|
187
|
+
/**
|
|
188
|
+
* This flag puts a black hole between the clients and the target replica (T07 `blackhole` of S2).
|
|
189
|
+
* The rules go in the namespace of the target only, with each client pod as a peer. The kubelet
|
|
190
|
+
* still reaches the replica from its node, thus its readiness and its endpoint stay. The prepare
|
|
191
|
+
* gives each client new connections first, as `cannot-serve` does.
|
|
192
|
+
*/
|
|
193
|
+
readonly partition?: boolean | undefined;
|
|
185
194
|
}
|
|
186
195
|
/** A kubelet probe is the period, the failure threshold and the timeout of one probe of the pod. */
|
|
187
196
|
interface KubeletProbe {
|
|
@@ -266,6 +275,12 @@ interface Workload {
|
|
|
266
275
|
* of HTTP/2 keeps this count of sessions, and it needs the count.
|
|
267
276
|
*/
|
|
268
277
|
readonly connections?: number | undefined;
|
|
278
|
+
/**
|
|
279
|
+
* These knobs give each session of a client of HTTP/2 the session check of the service
|
|
280
|
+
* (`sessionCheck` of `@mark1russell7/service/http-client`). A stream timeout or a PING with no ACK
|
|
281
|
+
* then closes the session, and the next stream opens a new one. Without them, a session has no check.
|
|
282
|
+
*/
|
|
283
|
+
readonly sessionCheck?: SessionCheckKnobs | undefined;
|
|
269
284
|
}
|
|
270
285
|
/**
|
|
271
286
|
* A band is a range of times after a reference event of the run. The format `/1` gives each end
|
|
@@ -1042,4 +1057,4 @@ declare const quantileOf: (sorted: readonly number[], p: number) => number;
|
|
|
1042
1057
|
declare const medianInterval: (sorted: readonly number[]) => [number, number];
|
|
1043
1058
|
//#endregion
|
|
1044
1059
|
export { updatesOf as $, Declaration as $t, TriggerV1 as A, nodeNames as An, rulesOf as At, RunCheck as B, ztunnelPodsOf as Bt, KindCellResult as C, NODE_IMAGES as Cn, outcomesOf as Ct, PredictionV1 as D, goDuration as Dn, requestsOf as Dt, LoadSample as E, cidrRange as En, recordsOf as Et, KIND_NOISE as F, slicesOf as Ft, judgeKind as G, PORT as Gt, checkRun as H, CLIENT as Ht, KindDecision as I, socketsOf as It, propagationOf as J, bandOf as Jt, observationAfter as K, REDIS as Kt, KindVerdict as L, stoppingOf as Lt, upgrade as M, scenarioProblems as Mn, signalsOf as Mt, upgradeCell as N, sliceDropOf as Nt, RunCheckV1 as O, kindConfig as On, restartOf as Ot, Deleted as P, sliceEmptyOf as Pt, unitOf as Q, Band as Qt, LAST_SLACK as R, transitionOf as Rt, KindCellRecordV1 as S, KubeProxyMode as Sn, kernelCounts as St, KindVerdictV1 as T, cidrOverlap as Tn, podsOf as Tt, deletionsOf as U, HEALTH_PORT as Ut, RunFacts as V, ztunnelReplaced as Vt, factsOf as W, LOG_LABEL as Wt, referenceOf as X, secondsOf as Xt, propagationSource as Y, seconds as Yt, reusesReset as Z, showBand as Zt, ClusterManifest as _, WindowPrediction as _n, dropOf as _t, STAGES as a, MeshFlavor as an, RecordLine as at, FORMAT_V1 as b, KindConfig as bn, intakeOf as bt, readRecord as c, Prediction as cn, SliceLine as ct, calibrationOf as d, Replica as dn, TunnelLine as dt, EdgeProtocol as en, Endpoint as et, cellsTable as f, ResetReuse as fn, ZtunnelPodLine as ft, BandV1 as g, TriggerKind as gn, deletionOf as gt, timeSpread as h, Trigger as hn, byNode as ht, quantileOf as i, Mesh as in, PropagationSource as it, judge as j, scenario as jn, signalOf as jt, RunFactsV1 as k, kubeProxyPatch as kn, restartsAt as kt, Judged as l, RedisDeclaration as ln, SocketLine as lt, predictionText as m, Template as mn, byClients as mt, medianInterval as n, KindRun as nn, Line as nt, kindCellRecordSchema as o, MeshMode as on, Request as ot, medianText as p, Stack as pn, backendsAt as pt, observationEnd as q, SERVER as qt, middle as r, KubeletProbe as rn, PodLine as rt, kindCellRecordV1Schema as s, PodSettings as sn, RulesLine as st, RELATIVE as t, KindCell as tn, HBONE_PORT as tt, TimeSpread as u, Reference as un, TCP_STATE as ut, EnvironmentManifest as v, Workload as vn, emptyOf as vt, KindCellV1 as w, NodeImage as wn, podsAt as wt, KindCellRecord as x, KindScenario as xn, isTunnelState as xt, FORMAT as y, KUBE_PROXY_MODES as yn, failuresOf as yt, Propagated as z, tunnelsOf as zt };
|
|
1045
|
-
//# sourceMappingURL=judge-
|
|
1060
|
+
//# sourceMappingURL=judge-yWlioigZ.d.ts.map
|
package/build/judge.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as updatesOf, $t as Declaration, A as TriggerV1, At as rulesOf, B as RunCheck, Bt as ztunnelPodsOf, C as KindCellResult, Ct as outcomesOf, D as PredictionV1, Dt as requestsOf, E as LoadSample, Et as recordsOf, F as KIND_NOISE, Ft as slicesOf, G as judgeKind, Gt as PORT, H as checkRun, Ht as CLIENT, I as KindDecision, It as socketsOf, J as propagationOf, Jt as bandOf, K as observationAfter, Kt as REDIS, L as KindVerdict, Lt as stoppingOf, M as upgrade, Mt as signalsOf, N as upgradeCell, Nt as sliceDropOf, O as RunCheckV1, Ot as restartOf, P as Deleted, Pt as sliceEmptyOf, Q as unitOf, Qt as Band, R as LAST_SLACK, Rt as transitionOf, S as KindCellRecordV1, Sn as KubeProxyMode, St as kernelCounts, T as KindVerdictV1, Tt as podsOf, U as deletionsOf, Ut as HEALTH_PORT, V as RunFacts, Vt as ztunnelReplaced, W as factsOf, Wt as LOG_LABEL, X as referenceOf, Xt as secondsOf, Y as propagationSource, Yt as seconds, Z as reusesReset, Zt as showBand, _ as ClusterManifest, _n as WindowPrediction, _t as dropOf, a as STAGES, an as MeshFlavor, at as RecordLine, b as FORMAT_V1, bt as intakeOf, c as readRecord, cn as Prediction, ct as SliceLine, d as calibrationOf, dn as Replica, dt as TunnelLine, en as EdgeProtocol, et as Endpoint, f as cellsTable, fn as ResetReuse, ft as ZtunnelPodLine, g as BandV1, gn as TriggerKind, gt as deletionOf, h as timeSpread, hn as Trigger, ht as byNode, i as quantileOf, in as Mesh, it as PropagationSource, j as judge, jt as signalOf, k as RunFactsV1, kt as restartsAt, l as Judged, ln as RedisDeclaration, lt as SocketLine, m as predictionText, mn as Template, mt as byClients, n as medianInterval, nn as KindRun, nt as Line, o as kindCellRecordSchema, on as MeshMode, ot as Request, p as medianText, pn as Stack, pt as backendsAt, q as observationEnd, qt as SERVER, r as middle, rn as KubeletProbe, rt as PodLine, s as kindCellRecordV1Schema, sn as PodSettings, st as RulesLine, t as RELATIVE, tn as KindCell, tt as HBONE_PORT, u as TimeSpread, un as Reference, ut as TCP_STATE, v as EnvironmentManifest, vn as Workload, vt as emptyOf, w as KindCellV1, wt as podsAt, x as KindCellRecord, xt as isTunnelState, y as FORMAT, yt as failuresOf, z as Propagated, zt as tunnelsOf } from "./judge-
|
|
1
|
+
import { $ as updatesOf, $t as Declaration, A as TriggerV1, At as rulesOf, B as RunCheck, Bt as ztunnelPodsOf, C as KindCellResult, Ct as outcomesOf, D as PredictionV1, Dt as requestsOf, E as LoadSample, Et as recordsOf, F as KIND_NOISE, Ft as slicesOf, G as judgeKind, Gt as PORT, H as checkRun, Ht as CLIENT, I as KindDecision, It as socketsOf, J as propagationOf, Jt as bandOf, K as observationAfter, Kt as REDIS, L as KindVerdict, Lt as stoppingOf, M as upgrade, Mt as signalsOf, N as upgradeCell, Nt as sliceDropOf, O as RunCheckV1, Ot as restartOf, P as Deleted, Pt as sliceEmptyOf, Q as unitOf, Qt as Band, R as LAST_SLACK, Rt as transitionOf, S as KindCellRecordV1, Sn as KubeProxyMode, St as kernelCounts, T as KindVerdictV1, Tt as podsOf, U as deletionsOf, Ut as HEALTH_PORT, V as RunFacts, Vt as ztunnelReplaced, W as factsOf, Wt as LOG_LABEL, X as referenceOf, Xt as secondsOf, Y as propagationSource, Yt as seconds, Z as reusesReset, Zt as showBand, _ as ClusterManifest, _n as WindowPrediction, _t as dropOf, a as STAGES, an as MeshFlavor, at as RecordLine, b as FORMAT_V1, bt as intakeOf, c as readRecord, cn as Prediction, ct as SliceLine, d as calibrationOf, dn as Replica, dt as TunnelLine, en as EdgeProtocol, et as Endpoint, f as cellsTable, fn as ResetReuse, ft as ZtunnelPodLine, g as BandV1, gn as TriggerKind, gt as deletionOf, h as timeSpread, hn as Trigger, ht as byNode, i as quantileOf, in as Mesh, it as PropagationSource, j as judge, jt as signalOf, k as RunFactsV1, kt as restartsAt, l as Judged, ln as RedisDeclaration, lt as SocketLine, m as predictionText, mn as Template, mt as byClients, n as medianInterval, nn as KindRun, nt as Line, o as kindCellRecordSchema, on as MeshMode, ot as Request, p as medianText, pn as Stack, pt as backendsAt, q as observationEnd, qt as SERVER, r as middle, rn as KubeletProbe, rt as PodLine, s as kindCellRecordV1Schema, sn as PodSettings, st as RulesLine, t as RELATIVE, tn as KindCell, tt as HBONE_PORT, u as TimeSpread, un as Reference, ut as TCP_STATE, v as EnvironmentManifest, vn as Workload, vt as emptyOf, w as KindCellV1, wt as podsAt, x as KindCellRecord, xt as isTunnelState, y as FORMAT, yt as failuresOf, z as Propagated, zt as tunnelsOf } from "./judge-yWlioigZ.js";
|
|
2
2
|
export { type Band, type BandV1, CLIENT, type ClusterManifest, type Declaration, type Deleted, type EdgeProtocol, Endpoint, type EnvironmentManifest, FORMAT, FORMAT_V1, HBONE_PORT, HEALTH_PORT, type Judged, KIND_NOISE, type KindCell, type KindCellRecord, type KindCellRecordV1, type KindCellResult, type KindCellV1, type KindDecision, type KindRun, type KindVerdict, type KindVerdictV1, type KubeProxyMode, type KubeletProbe, LAST_SLACK, LOG_LABEL, Line, type LoadSample, type Mesh, type MeshFlavor, type MeshMode, PORT, PodLine, type PodSettings, type Prediction, type PredictionV1, type Propagated, PropagationSource, REDIS, RELATIVE, RecordLine, type RedisDeclaration, type Reference, type Replica, Request, type ResetReuse, RulesLine, type RunCheck, type RunCheckV1, type RunFacts, type RunFactsV1, SERVER, STAGES, SliceLine, SocketLine, type Stack, TCP_STATE, type Template, type TimeSpread, type Trigger, type TriggerKind, type TriggerV1, TunnelLine, type WindowPrediction, type Workload, ZtunnelPodLine, backendsAt, bandOf, byClients, byNode, calibrationOf, cellsTable, checkRun, deletionOf, deletionsOf, dropOf, emptyOf, factsOf, failuresOf, intakeOf, isTunnelState, judge, judgeKind, kernelCounts, kindCellRecordSchema, kindCellRecordV1Schema, medianInterval, medianText, middle, observationAfter, observationEnd, outcomesOf, podsAt, podsOf, predictionText, propagationOf, propagationSource, quantileOf, readRecord, recordsOf, referenceOf, requestsOf, restartOf, restartsAt, reusesReset, rulesOf, seconds, secondsOf, showBand, signalOf, signalsOf, sliceDropOf, sliceEmptyOf, slicesOf, socketsOf, stoppingOf, timeSpread, transitionOf, tunnelsOf, unitOf, updatesOf, upgrade, upgradeCell, ztunnelPodsOf, ztunnelReplaced };
|
package/build/judge.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ut as CLIENT, u as FORMAT, d as FORMAT_V1, N as HBONE_PORT, dt as HEALTH_PORT, h as KIND_NOISE, g as LAST_SLACK, ft as LOG_LABEL, pt as PORT, mt as REDIS, k as RELATIVE, ht as SERVER, t as STAGES, P as TCP_STATE, F as backendsAt, gt as bandOf, I as byClients, L as byNode, a as calibrationOf, o as cellsTable, _ as checkRun, R as deletionOf, v as deletionsOf, z as dropOf, B as emptyOf, y as factsOf, V as failuresOf, H as intakeOf, U as isTunnelState, f as judge, b as judgeKind, W as kernelCounts, n as kindCellRecordSchema, r as kindCellRecordV1Schema, A as medianInterval, s as medianText, j as middle, x as observationAfter, S as observationEnd, G as outcomesOf, K as podsAt, q as podsOf, c as predictionText, C as propagationOf, w as propagationSource, M as quantileOf, i as readRecord, J as recordsOf, T as referenceOf, Y as requestsOf, X as restartOf, Z as restartsAt, E as reusesReset, Q as rulesOf, _t as seconds, vt as secondsOf, yt as showBand, $ as signalOf, et as signalsOf, tt as sliceDropOf, nt as sliceEmptyOf, rt as slicesOf, it as socketsOf, at as stoppingOf, l as timeSpread, ot as transitionOf, st as tunnelsOf, D as unitOf, O as updatesOf, p as upgrade, m as upgradeCell, ct as ztunnelPodsOf, lt as ztunnelReplaced } from "./judge-
|
|
1
|
+
export { ut as CLIENT, u as FORMAT, d as FORMAT_V1, N as HBONE_PORT, dt as HEALTH_PORT, h as KIND_NOISE, g as LAST_SLACK, ft as LOG_LABEL, pt as PORT, mt as REDIS, k as RELATIVE, ht as SERVER, t as STAGES, P as TCP_STATE, F as backendsAt, gt as bandOf, I as byClients, L as byNode, a as calibrationOf, o as cellsTable, _ as checkRun, R as deletionOf, v as deletionsOf, z as dropOf, B as emptyOf, y as factsOf, V as failuresOf, H as intakeOf, U as isTunnelState, f as judge, b as judgeKind, W as kernelCounts, n as kindCellRecordSchema, r as kindCellRecordV1Schema, A as medianInterval, s as medianText, j as middle, x as observationAfter, S as observationEnd, G as outcomesOf, K as podsAt, q as podsOf, c as predictionText, C as propagationOf, w as propagationSource, M as quantileOf, i as readRecord, J as recordsOf, T as referenceOf, Y as requestsOf, X as restartOf, Z as restartsAt, E as reusesReset, Q as rulesOf, _t as seconds, vt as secondsOf, yt as showBand, $ as signalOf, et as signalsOf, tt as sliceDropOf, nt as sliceEmptyOf, rt as slicesOf, it as socketsOf, at as stoppingOf, l as timeSpread, ot as transitionOf, st as tunnelsOf, D as unitOf, O as updatesOf, p as upgrade, m as upgradeCell, ct as ztunnelPodsOf, lt as ztunnelReplaced } from "./judge-BHygFh4Z.js";
|
package/image/client.mjs
CHANGED
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
// backend only for a new connection. SIGHUP opens new connections. Each request is one JSON line with
|
|
5
5
|
// its start on CLOCK_MONOTONIC, its duration, its outcome (ok, 503, refused, reset, timeout,
|
|
6
6
|
// unreachable, or another error) and its local port (`lp`). With PROTOCOL h2c, each connection is a
|
|
7
|
-
// session of HTTP/2, and each request is a stream on the next session in turn.
|
|
7
|
+
// session of HTTP/2, and each request is a stream on the next session in turn. With SESSION_CHECK,
|
|
8
|
+
// each session has the session check of the service: a stream timeout or a PING with no ACK closes it.
|
|
8
9
|
import http from "node:http";
|
|
9
10
|
import http2 from "node:http2";
|
|
10
11
|
import net from "node:net";
|
|
12
|
+
import { sessionCheck } from "@mark1russell7/service/http-client";
|
|
11
13
|
|
|
12
14
|
const [host, port] = (process.env.TARGET ?? "").split(":");
|
|
13
15
|
const every = Number(process.env.EVERY_MS ?? 20);
|
|
@@ -18,6 +20,8 @@ const now = () => Number(process.hrtime.bigint()) / 1e6;
|
|
|
18
20
|
const h2 = process.env.PROTOCOL === "h2c";
|
|
19
21
|
// a client of HTTP/2 needs at least one session
|
|
20
22
|
const connections = process.env.CONNECTIONS === undefined ? (h2 ? 1 : 0) : Number(process.env.CONNECTIONS);
|
|
23
|
+
// the knobs of the session check, or null for a session with no check
|
|
24
|
+
const checkKnobs = h2 && process.env.SESSION_CHECK !== undefined ? JSON.parse(process.env.SESSION_CHECK) : null;
|
|
21
25
|
|
|
22
26
|
// each agent holds one keep-alive connection. A `Connection: close` of the server ends it after its
|
|
23
27
|
// answer, and the next request on the agent opens a new connection
|
|
@@ -27,14 +31,27 @@ let turn = 0;
|
|
|
27
31
|
|
|
28
32
|
// each slot of HTTP/2 holds one session on its own socket, thus the client knows its local port. A
|
|
29
33
|
// GOAWAY, a close or an error of the session makes the slot open a new session at its next stream.
|
|
30
|
-
// kube-proxy picks a backend for that new connection. The old session ends the streams that it has
|
|
34
|
+
// kube-proxy picks a backend for that new connection. The old session ends the streams that it has.
|
|
35
|
+
// The check of a session hears each frame of the peer: its SETTINGS, its PINGs, and each response
|
|
31
36
|
const sessionOf = () => {
|
|
32
37
|
const socket = net.connect({ host, port: Number(port) });
|
|
33
38
|
const session = http2.connect(`http://${host}:${port}`, { createConnection: () => socket });
|
|
34
|
-
const held = { session, socket, usable: true };
|
|
39
|
+
const held = { session, socket, usable: true, check: null };
|
|
35
40
|
const drop = () => {
|
|
36
41
|
held.usable = false;
|
|
42
|
+
held.check?.stop();
|
|
37
43
|
};
|
|
44
|
+
if (checkKnobs !== null) {
|
|
45
|
+
held.check = sessionCheck(session, {
|
|
46
|
+
knobs: checkKnobs,
|
|
47
|
+
onClose: (cause) => {
|
|
48
|
+
held.usable = false;
|
|
49
|
+
say({ ev: "client", what: "session-check", t: now(), why: cause, lp: portOf(socket) });
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
session.on("remoteSettings", () => held.check.heard());
|
|
53
|
+
session.on("ping", () => held.check.heard());
|
|
54
|
+
}
|
|
38
55
|
session.on("goaway", drop);
|
|
39
56
|
session.on("close", drop);
|
|
40
57
|
session.on("error", drop);
|
|
@@ -157,10 +174,13 @@ const fireH2 = () => {
|
|
|
157
174
|
let held = null;
|
|
158
175
|
let stream = null;
|
|
159
176
|
let again = false;
|
|
177
|
+
// the end of the current stream for the check of its session: one time, at its timeout or otherwise
|
|
178
|
+
let endStream = null;
|
|
160
179
|
const finish = (o, extra = {}) => {
|
|
161
180
|
if (done) return;
|
|
162
181
|
done = true;
|
|
163
182
|
clearTimeout(timer);
|
|
183
|
+
endStream?.(false);
|
|
164
184
|
lp ??= portOf(held?.socket);
|
|
165
185
|
say({ ev: "req", t, d: Math.round((now() - t) * 1000) / 1000, o, ...extra, lp, ...(again ? { r: 1 } : {}) });
|
|
166
186
|
};
|
|
@@ -169,6 +189,7 @@ const fireH2 = () => {
|
|
|
169
189
|
if (!again && untaken(error, stream)) {
|
|
170
190
|
again = true;
|
|
171
191
|
held.usable = false;
|
|
192
|
+
endStream?.(false);
|
|
172
193
|
send();
|
|
173
194
|
return;
|
|
174
195
|
}
|
|
@@ -188,13 +209,24 @@ const fireH2 = () => {
|
|
|
188
209
|
return;
|
|
189
210
|
}
|
|
190
211
|
const mine = stream;
|
|
212
|
+
const check = held.check;
|
|
213
|
+
let counted = false;
|
|
214
|
+
check?.opened();
|
|
215
|
+
endStream = (timedOut) => {
|
|
216
|
+
if (counted) return;
|
|
217
|
+
counted = true;
|
|
218
|
+
if (timedOut) check?.timedOut();
|
|
219
|
+
else check?.ended();
|
|
220
|
+
};
|
|
191
221
|
let status = 0;
|
|
192
222
|
let body = "";
|
|
193
223
|
mine.setEncoding("utf8");
|
|
194
224
|
mine.on("response", (headers) => {
|
|
225
|
+
check?.heard();
|
|
195
226
|
status = Number(headers[":status"]);
|
|
196
227
|
});
|
|
197
228
|
mine.on("data", (chunk) => {
|
|
229
|
+
check?.heard();
|
|
198
230
|
body += chunk;
|
|
199
231
|
});
|
|
200
232
|
mine.on("end", () => {
|
|
@@ -213,10 +245,12 @@ const fireH2 = () => {
|
|
|
213
245
|
const timer = setTimeout(() => {
|
|
214
246
|
lp ??= portOf(held?.socket);
|
|
215
247
|
stream?.close(http2.constants.NGHTTP2_CANCEL);
|
|
248
|
+
// a stream that times out closes its session, when the session has a check
|
|
249
|
+
endStream?.(true);
|
|
216
250
|
finish("timeout", { e: "LAB_TIMEOUT" });
|
|
217
251
|
}, timeout);
|
|
218
252
|
send();
|
|
219
253
|
};
|
|
220
254
|
|
|
221
|
-
say({ ev: "client", what: "start", t: now(), target: `${host}:${port}`, every, timeout, connections, protocol: h2 ? "h2c" : "http/1.1" });
|
|
255
|
+
say({ ev: "client", what: "start", t: now(), target: `${host}:${port}`, every, timeout, connections, protocol: h2 ? "h2c" : "http/1.1", ...(checkKnobs !== null ? { sessionCheck: checkKnobs } : {}) });
|
|
222
256
|
setInterval(h2 ? fireH2 : fire, every);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@mark1russell7/kind",
|
|
4
|
-
"version": "0.11.
|
|
4
|
+
"version": "0.11.3",
|
|
5
5
|
"description": "Kubernetes in Docker as a lab for connection timers: a kind cluster from a scenario, faults in the namespaces of its pods, observations on the one monotonic clock of the VM, and predictions from the ordering law. Its judge entry reads and judges a raw record without Docker.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"kubernetes",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"@mark1russell7/harness": "^0.12.4",
|
|
69
69
|
"@mark1russell7/quantity": "^0.2.0",
|
|
70
|
-
"@mark1russell7/service": "^0.5.
|
|
70
|
+
"@mark1russell7/service": "^0.5.20",
|
|
71
71
|
"testcontainers": "12.2.0"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|