@mark1russell7/harness 0.11.2 → 0.11.4
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 +41 -7
- package/build/cell-Di_YHiuB.d.ts +999 -0
- package/build/image-BfuXg-5t.js +427 -0
- package/build/image-BfuXg-5t.js.map +1 -0
- package/build/index.d.ts +119 -945
- package/build/index.js +22 -193
- package/build/index.js.map +1 -1
- package/build/schema.d.ts +19 -0
- package/build/schema.js +56 -0
- package/build/schema.js.map +1 -0
- package/image/hikari/ClientHikari.java +424 -0
- package/image/hikari/Dockerfile +19 -0
- package/image/hikari/jars.sha256 +3 -0
- package/image/pg/client-pg.mjs +4 -0
- package/package.json +8 -1
|
@@ -0,0 +1,999 @@
|
|
|
1
|
+
import { Quantity } from "@mark1russell7/quantity";
|
|
2
|
+
import { KernelRecord } from "@mark1russell7/prober";
|
|
3
|
+
//#region src/cell.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* A fault is a failure that the harness injects, by the name of its manifestation. Each name is
|
|
6
|
+
* the last segment of the identifier of the manifestation in the corpus:
|
|
7
|
+
* - `blackhole` is two DROP rules in the network namespace of the target. Thus the measurement
|
|
8
|
+
* gets the kernel timers of the client.
|
|
9
|
+
* - `freeze-process` is the cgroup freezer on the target, while its kernel stays up.
|
|
10
|
+
* - `rst` answers the next segment of the client with a reset, from the namespace of the target.
|
|
11
|
+
* It is the reference for the noise of the harness itself.
|
|
12
|
+
* - `stall` is a black hole that stops by itself, `Cell.stall` after the client sends its
|
|
13
|
+
* request. The VM times it. It shows what recovers, and when.
|
|
14
|
+
* - `fin` stops the process of the peer with SIGKILL, while its kernel stays up. The kernel closes its sockets
|
|
15
|
+
* with a FIN, or with a reset when unread data is in the queue.
|
|
16
|
+
* - `unreachable` answers each segment from the observer with an ICMP unreachable (`Cell.icmp`).
|
|
17
|
+
* Linux keeps it as a soft error on an established socket, and it continues to retransmit.
|
|
18
|
+
* - `simplex` drops the segments in one direction only (`Cell.drops`).
|
|
19
|
+
* - `mtu-blackhole` drops each segment to the observer that is longer than `Cell.mtu` bytes.
|
|
20
|
+
* - `netem` is tc netem on the egress of the target (`Cell.netem`): loss, duplication,
|
|
21
|
+
* reordering or corruption. Its outcome is a distribution.
|
|
22
|
+
*
|
|
23
|
+
* These faults are of a topology (`Cell.topology`):
|
|
24
|
+
* - `middlebox-forget` injects nothing. The router of the topology forgets an idle flow at its own
|
|
25
|
+
* idle timeout, and its form tells what a late packet then meets.
|
|
26
|
+
* - `proxy-idle` injects nothing. The proxy of the topology closes an idle connection at its own
|
|
27
|
+
* timeout.
|
|
28
|
+
* - `toxic` adds a toxic of Toxiproxy (`Cell.toxic`) through its HTTP API.
|
|
29
|
+
* - `server-close` makes the server close the connection of its peer, with the command of the
|
|
30
|
+
* target (`Target.close`): `CLIENT KILL` in Redis.
|
|
31
|
+
* - `none` injects nothing. A calibration cell measures the path itself: for example the time of a
|
|
32
|
+
* proxy between its two sockets (`Cell.calibrates`).
|
|
33
|
+
*
|
|
34
|
+
* A fault at a router of the topology (`Cell.faultAt`) acts on what the router forwards toward
|
|
35
|
+
* one side. It is a black hole, a reset or an ICMP unreachable. It can also be a simplex drop, an
|
|
36
|
+
* MTU drop or netem.
|
|
37
|
+
*
|
|
38
|
+
* These faults are of a replicated group (`Cell.group` or `Cell.replicaSet`), on the part that `Cell.faultAt` names:
|
|
39
|
+
* - `blackhole` drops each segment between the part and each of its peers. `rst` answers each
|
|
40
|
+
* segment from a peer with a reset, thus the part refuses each connection.
|
|
41
|
+
* - `partition` is a black hole between the part and some of its peers only (`GroupPlace.cuts`).
|
|
42
|
+
* - `freeze-process` stops the server process of the part with SIGSTOP, and SIGCONT thaws it. Its
|
|
43
|
+
* kernel stays up. `fin` stops the process with SIGKILL.
|
|
44
|
+
* - `planned-failover` asks a Sentinel for a failover: `SENTINEL FAILOVER <group>`.
|
|
45
|
+
*
|
|
46
|
+
* This fault is of an HTTP server:
|
|
47
|
+
* - `app-stall` injects nothing. The server process holds the reply to the request, because the
|
|
48
|
+
* request asks for that (`HttpProbe.hold`), while its kernel stays up.
|
|
49
|
+
*
|
|
50
|
+
* This fault is of a replica set (`Cell.replicaSet`):
|
|
51
|
+
* - `step-down` sends `replSetStepDown` to the primary, as a client sends a command.
|
|
52
|
+
*/
|
|
53
|
+
type Fault = "blackhole" | "freeze-process" | "rst" | "stall" | "fin" | "unreachable" | "simplex" | "mtu-blackhole" | "netem" | "middlebox-forget" | "proxy-idle" | "toxic" | "server-close" | "partition" | "planned-failover" | "app-stall" | "step-down" | "none";
|
|
54
|
+
/**
|
|
55
|
+
* A middlebox form tells what a router does with a flow that it forgot, when a late packet comes:
|
|
56
|
+
* - `reset-both` sends a reset to the two ends when it forgets the flow.
|
|
57
|
+
* - `reset-next` answers the next packet from inside with a reset to its sender, and drops a late
|
|
58
|
+
* packet from outside.
|
|
59
|
+
* - `silent-drop` drops each late packet, in each direction.
|
|
60
|
+
* - `recreate` lets a late packet from inside through, and the flow starts again. It drops a late
|
|
61
|
+
* packet from outside.
|
|
62
|
+
* - `none` is a plain NAT router. A late packet from inside starts the flow again, and the stack of
|
|
63
|
+
* the router answers a late packet from outside with a reset.
|
|
64
|
+
*/
|
|
65
|
+
type MiddleboxForm = "reset-both" | "reset-next" | "silent-drop" | "recreate" | "none";
|
|
66
|
+
/**
|
|
67
|
+
* A router is a hop that forwards and translates the addresses of the side of the client (NAT),
|
|
68
|
+
* with conntrack. It is the router image of the harness.
|
|
69
|
+
*/
|
|
70
|
+
interface RouterHop {
|
|
71
|
+
readonly name: string;
|
|
72
|
+
readonly kind: "router";
|
|
73
|
+
readonly form: MiddleboxForm;
|
|
74
|
+
/** This time is the idle timeout of an established flow: nf_conntrack_tcp_timeout_established, in whole seconds. */
|
|
75
|
+
readonly idle: Quantity;
|
|
76
|
+
/**
|
|
77
|
+
* This time is the interval of the listing that evicts each expired flow. Without it, the
|
|
78
|
+
* interval is 0.1 s. The DESTROY event of an expired flow waits for that listing.
|
|
79
|
+
*/
|
|
80
|
+
readonly pump?: Quantity;
|
|
81
|
+
/**
|
|
82
|
+
* These are the sysctls of the namespace of the router, which the router sets itself: it is
|
|
83
|
+
* privileged. An example is `net.ipv4.icmp_ratelimit` for the ICMP errors of a fault at the router.
|
|
84
|
+
*/
|
|
85
|
+
readonly sysctls?: Readonly<Record<string, string>>;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A proxy is a hop that ends each TCP connection from the side of the client and opens its own to
|
|
89
|
+
* the next hop. It is a stock image, pinned by digest.
|
|
90
|
+
*/
|
|
91
|
+
interface ProxyHop {
|
|
92
|
+
readonly name: string;
|
|
93
|
+
readonly kind: "proxy";
|
|
94
|
+
readonly image: string;
|
|
95
|
+
/** This port is the port that the proxy listens on for the side of the client. */
|
|
96
|
+
readonly port: number;
|
|
97
|
+
readonly command?: readonly string[];
|
|
98
|
+
/** These files go into the proxy before it starts, by their path. In their content, {{next}} is the address and port of the next hop. */
|
|
99
|
+
readonly files?: Readonly<Record<string, string>>;
|
|
100
|
+
/** This text is the log line that tells that the proxy serves. */
|
|
101
|
+
readonly ready?: string;
|
|
102
|
+
/** This record is the HTTP API of Toxiproxy: its port, and the name of the proxy that gets the toxics. */
|
|
103
|
+
readonly api?: {
|
|
104
|
+
readonly port: number;
|
|
105
|
+
readonly proxy: string;
|
|
106
|
+
};
|
|
107
|
+
/** These are the sysctls of the namespace of the proxy. A privileged sidecar sets them before each run. */
|
|
108
|
+
readonly sysctls?: Readonly<Record<string, string>>;
|
|
109
|
+
/** These are the settings of the proxy, for the manifest: for example its idle timeouts. */
|
|
110
|
+
readonly settings?: Readonly<Record<string, string>>;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* A hop is one box between the client and the target. Each hop is on two networks: the network
|
|
114
|
+
* of the side of the client, and the network of the side of the target.
|
|
115
|
+
*/
|
|
116
|
+
type Hop = RouterHop | ProxyHop;
|
|
117
|
+
/**
|
|
118
|
+
* A topology is the chain of hops between the client and the target, in sequence from the client.
|
|
119
|
+
* Without hops, the client and the target are a direct pair.
|
|
120
|
+
*/
|
|
121
|
+
interface Topology {
|
|
122
|
+
readonly name: string;
|
|
123
|
+
readonly hops: readonly Hop[];
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* A group is a replicated group under an external failover authority, as data. It is a primary and
|
|
127
|
+
* its replicas, and the Sentinels that decide which member is the primary. Each member and each
|
|
128
|
+
* Sentinel is a container from the same stock image, pinned by digest. Each has its own network
|
|
129
|
+
* namespace, thus a fault can act on one part. The client finds the primary through the
|
|
130
|
+
* Sentinels, and the parts and the client share one network.
|
|
131
|
+
*/
|
|
132
|
+
interface Group {
|
|
133
|
+
/** This name is the name of the group that the Sentinels monitor, for example `mymaster`. */
|
|
134
|
+
readonly name: string;
|
|
135
|
+
/** This image is the stock image of each member and each Sentinel, pinned by digest. */
|
|
136
|
+
readonly image: string;
|
|
137
|
+
/** These are the programs of the image: the server, the Sentinel and the command line client. */
|
|
138
|
+
readonly programs: {
|
|
139
|
+
readonly server: string;
|
|
140
|
+
readonly sentinel: string;
|
|
141
|
+
readonly cli: string;
|
|
142
|
+
};
|
|
143
|
+
readonly port: number;
|
|
144
|
+
readonly sentinelPort: number;
|
|
145
|
+
/** These are the names of the members. The first one is the primary when the environment starts. */
|
|
146
|
+
readonly members: readonly string[];
|
|
147
|
+
readonly sentinels: readonly string[];
|
|
148
|
+
/** This count is how many Sentinels must agree that the primary is down. */
|
|
149
|
+
readonly quorum: number;
|
|
150
|
+
/** These are the settings of each member, as its configuration file spells them. The harness adds `replicaof` for each replica. */
|
|
151
|
+
readonly memberSettings: Readonly<Record<string, string>>;
|
|
152
|
+
/**
|
|
153
|
+
* These are the settings of each Sentinel for the group, as `sentinel <setting> <group> <value>`
|
|
154
|
+
* spells them: `down-after-milliseconds`, `failover-timeout` and `parallel-syncs`.
|
|
155
|
+
*/
|
|
156
|
+
readonly sentinelSettings: Readonly<Record<string, string>>;
|
|
157
|
+
/** These lines tell that a member and a Sentinel serve. */
|
|
158
|
+
readonly ready: {
|
|
159
|
+
readonly member: string;
|
|
160
|
+
readonly sentinel: string;
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* A replica set is a replicated group with no external authority, as data: its members elect their
|
|
165
|
+
* own primary. Each member is a container from the same stock image, pinned by digest, in its own
|
|
166
|
+
* network namespace. The client finds the primary by its own monitors. The harness starts the set
|
|
167
|
+
* with the address of each member, and it waits for a primary.
|
|
168
|
+
*/
|
|
169
|
+
interface ReplicaSet {
|
|
170
|
+
/** This name is the name of the set, for example `rs0`. */
|
|
171
|
+
readonly name: string;
|
|
172
|
+
/** This image is the stock image of each member, pinned by digest. */
|
|
173
|
+
readonly image: string;
|
|
174
|
+
/** These are the programs of the image: the server and its shell. */
|
|
175
|
+
readonly programs: {
|
|
176
|
+
readonly server: string;
|
|
177
|
+
readonly shell: string;
|
|
178
|
+
};
|
|
179
|
+
/** These are the options of the server of each member, after the name of the set: for example the size of its cache. */
|
|
180
|
+
readonly args?: readonly string[];
|
|
181
|
+
readonly port: number;
|
|
182
|
+
/** These are the names of the members. The first one starts the set. */
|
|
183
|
+
readonly members: readonly string[];
|
|
184
|
+
/** These are the settings of the configuration of the set, as `rs.initiate` takes them: for example `electionTimeoutMillis`. */
|
|
185
|
+
readonly settings: Readonly<Record<string, number>>;
|
|
186
|
+
/** This line tells that a member serves. */
|
|
187
|
+
readonly ready: string;
|
|
188
|
+
}
|
|
189
|
+
/** A group role is a part of a group by its role at the start of a run: the primary, a replica, or a Sentinel. */
|
|
190
|
+
type GroupRole = "primary" | "replica" | "sentinel";
|
|
191
|
+
/**
|
|
192
|
+
* A group place is the part of a group that a fault acts on. A network fault cuts the part from
|
|
193
|
+
* some of its peers:
|
|
194
|
+
* - `all`: each other part of the group, and each client. This is the default.
|
|
195
|
+
* - `group`: the other members and the Sentinels, but not the clients.
|
|
196
|
+
* - `clients`: the clients, but not the group.
|
|
197
|
+
* - `one`: one other member, in both directions.
|
|
198
|
+
* - `one-way`: one other member, for the segments from the part only.
|
|
199
|
+
*/
|
|
200
|
+
interface GroupPlace {
|
|
201
|
+
readonly role: GroupRole;
|
|
202
|
+
readonly cuts?: "all" | "group" | "clients" | "one" | "one-way";
|
|
203
|
+
}
|
|
204
|
+
/** A toxic is one toxic of Toxiproxy, as its API takes it. Its toxicity is 1. */
|
|
205
|
+
interface Toxic {
|
|
206
|
+
readonly type: "latency" | "timeout" | "reset_peer" | "slow_close" | "bandwidth" | "limit_data" | "slicer";
|
|
207
|
+
readonly stream: "downstream" | "upstream";
|
|
208
|
+
readonly attributes: Readonly<Record<string, number>>;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* A reference is the event that the time of a detector counts from: the event that arms the
|
|
212
|
+
* timer in its machine document. Keepalive counts from the last received segment. The give-up of
|
|
213
|
+
* the retransmissions counts from the first retransmission of the RTO timer, not from the tail
|
|
214
|
+
* loss probe one RTO before it. The request itself meets a reset, thus a reset counts from the
|
|
215
|
+
* send of the client. A FIN counts from the change of state of the socket of the peer when its
|
|
216
|
+
* process dies (`peer-closed`). A toxic of Toxiproxy counts from the start of its commit, as the
|
|
217
|
+
* injector stamps it (`fault`).
|
|
218
|
+
*
|
|
219
|
+
* A client that starts into a fault counts from its `connecting` line, or from its first line
|
|
220
|
+
* without one (`client-start`).
|
|
221
|
+
*
|
|
222
|
+
* A heartbeat of a program counts from its first ping that got no answer (`ping-sent`). The
|
|
223
|
+
* program writes a `ping` line before each ping, and the kernel stamps the write (`tx`). No
|
|
224
|
+
* segment with data reaches the socket after that write, up to the detection.
|
|
225
|
+
*/
|
|
226
|
+
type Reference = "last-received" | "first-retransmission" | "request-sent" | "peer-closed" | "fault" | "client-start" | "ping-sent";
|
|
227
|
+
/**
|
|
228
|
+
* This prediction tells when a connection moves again after a stall. That occurs at the first
|
|
229
|
+
* firing of its retransmission timer after the stall stops, and its reply comes back one round
|
|
230
|
+
* trip later.
|
|
231
|
+
*/
|
|
232
|
+
interface Recovers {
|
|
233
|
+
/** This count identifies the firing that gets through: the number of firings before it. */
|
|
234
|
+
readonly firing: number;
|
|
235
|
+
/** This time is the earliest return of the reply, from the send of the request. */
|
|
236
|
+
readonly low: Quantity;
|
|
237
|
+
/** This time is the latest return of the reply, from the send of the request. */
|
|
238
|
+
readonly high: Quantity;
|
|
239
|
+
/**
|
|
240
|
+
* This range is where the stall must stop, from the send, so that this firing is the first
|
|
241
|
+
* after it. The range starts after the latest time of the firing before, and it stops before
|
|
242
|
+
* the earliest time of this firing.
|
|
243
|
+
*/
|
|
244
|
+
readonly heal: {
|
|
245
|
+
readonly low: Quantity;
|
|
246
|
+
readonly high: Quantity;
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* This prediction tells when the reply to the request comes back, from the send of the request.
|
|
251
|
+
* For example, the reply comes after the latency of a toxic, or after a forgotten flow starts again.
|
|
252
|
+
*/
|
|
253
|
+
interface Replies {
|
|
254
|
+
readonly low: Quantity;
|
|
255
|
+
readonly high: Quantity;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* An RTT range is the range of the first round trip of the observer that a band assumes. The
|
|
259
|
+
* models read a round trip, for example 1 ms. The band at that value holds within the noise for
|
|
260
|
+
* each round trip in the range. A run whose first round trip is above the range is void.
|
|
261
|
+
*/
|
|
262
|
+
interface RttRange {
|
|
263
|
+
readonly low: Quantity;
|
|
264
|
+
readonly high: Quantity;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* A proxy time is the time of one proxy in one direction that a band includes. It is an upper
|
|
268
|
+
* quantile of the times that a calibration cell of the proxy measured. Each time goes from an
|
|
269
|
+
* arrival on one socket of the proxy to its write on the other. `up` goes toward the target, and
|
|
270
|
+
* `down` toward the client.
|
|
271
|
+
*/
|
|
272
|
+
interface ProxyTime {
|
|
273
|
+
readonly hop: string;
|
|
274
|
+
readonly direction: "up" | "down";
|
|
275
|
+
/** This fraction is the quantile of the calibration, for example 0.99. */
|
|
276
|
+
readonly quantile: number;
|
|
277
|
+
readonly time: Quantity;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* A stage is one step of the timeline of a group after a fault, by the event that a Sentinel
|
|
281
|
+
* publishes for it. The stages are the subjective down, the objective down, the start of a
|
|
282
|
+
* failover and the election. Then the selection of a replica, the promotion, the switch to the new
|
|
283
|
+
* primary, and the conversion of the old primary into a replica.
|
|
284
|
+
*/
|
|
285
|
+
type SentinelStage = "+sdown" | "+odown" | "+try-failover" | "+elected-leader" | "+selected-slave" | "+promoted-slave" | "+switch-master" | "+convert-to-slave";
|
|
286
|
+
/**
|
|
287
|
+
* A replica set stage is one step of the timeline of a replica set after a fault. A line of the log
|
|
288
|
+
* of a member marks it, or a line of the client. The stages are a member that marks the primary
|
|
289
|
+
* DOWN, the start of an election and its win, and the end of the catch-up. Then come the first
|
|
290
|
+
* write of the new primary and the step-down of the old one. The client's lines give its discovery
|
|
291
|
+
* of the new primary, the write-off of the old one, and the first write that a primary accepts.
|
|
292
|
+
*/
|
|
293
|
+
type ReplicaSetStage = "member-down" | "election-start" | "elected" | "caught-up" | "writable" | "old-primary-steps-down" | "discovered" | "written-off" | "first-write";
|
|
294
|
+
/** A stage is one step of the timeline of a group: of a group under Sentinels, or of a replica set. */
|
|
295
|
+
type Stage = SentinelStage | ReplicaSetStage;
|
|
296
|
+
/** A stage band is when the first part announces a stage, from the reference of the cell. */
|
|
297
|
+
interface StageBand {
|
|
298
|
+
readonly stage: Stage;
|
|
299
|
+
readonly low: Quantity;
|
|
300
|
+
readonly high: Quantity;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* A group prediction tells what a group does after the fault, beside the band of its cell:
|
|
304
|
+
* - `lands` is the primary that the first accepted write after the fault lands on: a new one, or the same one.
|
|
305
|
+
* - `failover` tells if a Sentinel announces a switch to a new primary in the window.
|
|
306
|
+
* - `stages` are the bands of the stages of the timeline. Each band includes the error of the
|
|
307
|
+
* stamps of the observer (`stamps`).
|
|
308
|
+
* - `errors` are the errors that the client must meet on the way, each with the band of its
|
|
309
|
+
* first occurrence. An example is the error of the offline queue when it gives up.
|
|
310
|
+
* - `quiet` are the stages that must not occur after the fault. Each one that a run shows is a finding.
|
|
311
|
+
*/
|
|
312
|
+
interface GroupPrediction {
|
|
313
|
+
readonly lands: "new" | "same";
|
|
314
|
+
readonly failover: boolean;
|
|
315
|
+
readonly stages: readonly StageBand[];
|
|
316
|
+
readonly stamps?: Quantity;
|
|
317
|
+
readonly errors?: ReadonlyArray<{
|
|
318
|
+
readonly name: string;
|
|
319
|
+
readonly low: Quantity;
|
|
320
|
+
readonly high: Quantity;
|
|
321
|
+
}>;
|
|
322
|
+
readonly quiet?: readonly Stage[];
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* A middlebox expectation tells what the router of a topology does with the flow in the window of
|
|
326
|
+
* a silent prediction. Without it, the router keeps the flow. With `forgets`, the router forgets
|
|
327
|
+
* the flow in that band after the last segment of the client, and nothing detects it.
|
|
328
|
+
*/
|
|
329
|
+
interface MiddleboxExpectation {
|
|
330
|
+
readonly forgets: {
|
|
331
|
+
readonly low: Quantity;
|
|
332
|
+
readonly high: Quantity;
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* A request prediction tells what the second request of an HTTP client meets, beside the band of
|
|
337
|
+
* its cell. The client writes it in its lines: the connection of each try, and the outcome.
|
|
338
|
+
* - `connection` is the connection of its first try: the one that the first request used
|
|
339
|
+
* (`reused`), or a new one.
|
|
340
|
+
* - `retried` tells that the client sent it again on a new connection by itself.
|
|
341
|
+
* - `error` is the error that reaches the caller, or null for a reply.
|
|
342
|
+
* - `pending` tells that nothing ends the request in the window of the cell.
|
|
343
|
+
*/
|
|
344
|
+
interface RequestPrediction {
|
|
345
|
+
readonly connection: "reused" | "new";
|
|
346
|
+
readonly retried: boolean;
|
|
347
|
+
readonly error: string | null;
|
|
348
|
+
readonly pending?: true;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* A line match is a line of the client that a driver band waits for. It has the `ev` of the line,
|
|
352
|
+
* and the value of each field that it names. A dotted name is a field in a field, for example
|
|
353
|
+
* `failure.name`. `name` is the field that names the error of the line, for its outcome.
|
|
354
|
+
*/
|
|
355
|
+
interface LineMatch {
|
|
356
|
+
readonly ev: string;
|
|
357
|
+
readonly where?: Readonly<Record<string, string | number | boolean>>;
|
|
358
|
+
readonly name?: string;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* A driver step is one more band of a driver after the band of its cell. An example is the error
|
|
362
|
+
* of the retry after the interruption. It has its own reference on a socket of the driver, its
|
|
363
|
+
* line, and its band. A run whose step is outside its band, or absent, has a finding.
|
|
364
|
+
*/
|
|
365
|
+
interface DriverStep {
|
|
366
|
+
readonly what: string;
|
|
367
|
+
/** This name is the name of the error of the line, or OK. */
|
|
368
|
+
readonly name: string;
|
|
369
|
+
/** This role is the socket of the reference. Without it, the socket is the socket of the band of the cell. */
|
|
370
|
+
readonly socket?: string;
|
|
371
|
+
readonly from: Reference;
|
|
372
|
+
readonly ends: LineMatch;
|
|
373
|
+
readonly low: Quantity;
|
|
374
|
+
readonly high: Quantity;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* A driver band is a band of a cell whose client is a driver with more than one socket, for
|
|
378
|
+
* example the MongoDB driver. It names the socket of the reference, and the line that ends the
|
|
379
|
+
* band:
|
|
380
|
+
* - `socket` is the role of the socket, as the client names it in its `socket` lines. The socket
|
|
381
|
+
* `server` is the socket of the target for the first connection of the pool.
|
|
382
|
+
* - `ends` is the line of the client that marks the detection. Without it, the detection is the
|
|
383
|
+
* report of the kernel on the socket: an error, or the end of the file.
|
|
384
|
+
* - `reply` is the line of a reply that a silent prediction times (`replies`), with its reference.
|
|
385
|
+
* - `quiet` are the lines that must not occur after the fault, in the window of the prediction.
|
|
386
|
+
* - `then` are the later bands, each one a test of its own.
|
|
387
|
+
*
|
|
388
|
+
* A band whose line ends it is a timer of the driver. Its `last-received` is the last segment with
|
|
389
|
+
* data that its socket received or sent. The idle timer of a Node socket starts again at each read
|
|
390
|
+
* and each write. A band of the kernel counts from the last segment of any kind that the socket
|
|
391
|
+
* received.
|
|
392
|
+
*/
|
|
393
|
+
interface DriverBand {
|
|
394
|
+
readonly socket: string;
|
|
395
|
+
readonly ends?: LineMatch;
|
|
396
|
+
readonly reply?: {
|
|
397
|
+
readonly from: Reference;
|
|
398
|
+
readonly ends: LineMatch;
|
|
399
|
+
};
|
|
400
|
+
readonly quiet?: readonly LineMatch[];
|
|
401
|
+
readonly then?: readonly DriverStep[];
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* A reconnect prediction tells when the program of the client tries a new connection after the
|
|
405
|
+
* detection. Each wait counts from the start of the reconnect timer of the program (a
|
|
406
|
+
* `reconnecting` line) to the try (a `dial` line). The first wait follows the detection, and each
|
|
407
|
+
* next wait follows the failure of the try before it.
|
|
408
|
+
*/
|
|
409
|
+
interface Reconnects {
|
|
410
|
+
readonly waits: ReadonlyArray<{
|
|
411
|
+
readonly low: Quantity;
|
|
412
|
+
readonly high: Quantity;
|
|
413
|
+
}>;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* A prediction is what a cell predicts. Either a detection occurs in an interval [T_lo, T_hi]
|
|
417
|
+
* after the reference event, or nothing detects the fault in a window. Nothing detects a stall
|
|
418
|
+
* that is shorter than the give-up, and the connection recovers from it. The prediction then also
|
|
419
|
+
* tells when. A silent prediction can also tell when the reply to the request comes back
|
|
420
|
+
* (`replies`), and what a router does with the flow (`middlebox`).
|
|
421
|
+
*
|
|
422
|
+
* A band can name the first round trip that it assumes (`rtt`), and the proxy times that it
|
|
423
|
+
* includes (`through`).
|
|
424
|
+
*
|
|
425
|
+
* A cell whose outcome is a distribution, for example under netem loss, has no band. Its
|
|
426
|
+
* prediction is `detects: null` with the reason, and its runs are measurements only. A
|
|
427
|
+
* measurement-only cell that names a reference (`from`) also records the time from it to the end
|
|
428
|
+
* of the connection, or to the last data. It can also give the waits of the reconnect after that
|
|
429
|
+
* end (`reconnects`).
|
|
430
|
+
*
|
|
431
|
+
* For a group cell, the band is the first write that a primary accepts after the fault, and its
|
|
432
|
+
* errno is `OK`. `group` tells which primary, and the stages of the group on the way.
|
|
433
|
+
*
|
|
434
|
+
* For an HTTP cell, `request` tells what the second request meets. The errno `CLOSED` is a close
|
|
435
|
+
* of the observer itself: its pool closes an idle connection, a FIN that it sends.
|
|
436
|
+
*
|
|
437
|
+
* A band of a driver (`driver`) counts from a socket of the driver to a line of the client.
|
|
438
|
+
*
|
|
439
|
+
* The errno `DROPPED` is a drop by the program of the observer itself. Its own timer gave up, and
|
|
440
|
+
* it closed its socket or wrote a close frame. A detection can also tell when the client tries a
|
|
441
|
+
* new connection (`reconnects`).
|
|
442
|
+
*/
|
|
443
|
+
type Prediction = {
|
|
444
|
+
readonly detects: true;
|
|
445
|
+
/** This name is the timer of the machine that fires first, or the event that detects the fault, with its errno. */
|
|
446
|
+
readonly timer: string;
|
|
447
|
+
/**
|
|
448
|
+
* This name is the errno of the detection, or EOF for an end of file without an error. It is
|
|
449
|
+
* OK for a write that a primary accepts, and CLOSED for a close of the observer itself. It is
|
|
450
|
+
* DROPPED for a drop by the program of the observer.
|
|
451
|
+
*/
|
|
452
|
+
readonly errno: string;
|
|
453
|
+
readonly from: Reference;
|
|
454
|
+
/** This time is the closed form, less the most that the timer can fire early. */
|
|
455
|
+
readonly low: Quantity;
|
|
456
|
+
/** This time is the closed form, plus the most that the timer can fire late, plus each proxy time. */
|
|
457
|
+
readonly high: Quantity;
|
|
458
|
+
/**
|
|
459
|
+
* This time is the latest reference of the band after the reply of the client. It is for a
|
|
460
|
+
* reference that can come late, for example the first ping without an answer of a server
|
|
461
|
+
* heartbeat. The run then waits that much longer for the detection.
|
|
462
|
+
*/
|
|
463
|
+
readonly startsBy?: Quantity;
|
|
464
|
+
readonly rtt?: RttRange;
|
|
465
|
+
readonly through?: readonly ProxyTime[];
|
|
466
|
+
readonly group?: GroupPrediction;
|
|
467
|
+
readonly request?: RequestPrediction;
|
|
468
|
+
readonly driver?: DriverBand;
|
|
469
|
+
readonly reconnects?: Reconnects;
|
|
470
|
+
/**
|
|
471
|
+
* This name tells how the program drops the connection, for the errno DROPPED. A close frame
|
|
472
|
+
* leaves its socket ESTABLISHED below (`frame`). A close of its socket takes it out of
|
|
473
|
+
* ESTABLISHED at once (`close`).
|
|
474
|
+
*/
|
|
475
|
+
readonly drop?: "frame" | "close";
|
|
476
|
+
/**
|
|
477
|
+
* This flag tells that the program of the observer is the client process, which ends at the
|
|
478
|
+
* end of the run. Its kernel then closes each socket that is still open. A close of the
|
|
479
|
+
* socket at that end is not a close by the program, thus `left` stays null for it (`exited`).
|
|
480
|
+
*/
|
|
481
|
+
readonly exits?: true;
|
|
482
|
+
} | {
|
|
483
|
+
readonly detects: false;
|
|
484
|
+
readonly window: Quantity;
|
|
485
|
+
readonly recovers?: Recovers;
|
|
486
|
+
readonly replies?: Replies;
|
|
487
|
+
readonly middlebox?: MiddleboxExpectation;
|
|
488
|
+
readonly rtt?: RttRange;
|
|
489
|
+
readonly through?: readonly ProxyTime[];
|
|
490
|
+
readonly group?: GroupPrediction;
|
|
491
|
+
readonly request?: RequestPrediction;
|
|
492
|
+
readonly driver?: DriverBand;
|
|
493
|
+
} | {
|
|
494
|
+
readonly detects: null;
|
|
495
|
+
readonly window: Quantity;
|
|
496
|
+
readonly why: string;
|
|
497
|
+
readonly from?: Reference;
|
|
498
|
+
/**
|
|
499
|
+
* This choice ends the measured time at the close of the socket by the observer itself, the
|
|
500
|
+
* change from ESTABLISHED to FIN_WAIT1. Without it, the time ends at a report of the kernel or
|
|
501
|
+
* at the last data. Then an idle pool that closes its own socket gives no end.
|
|
502
|
+
*/
|
|
503
|
+
readonly ends?: "own-close";
|
|
504
|
+
readonly group?: GroupPrediction;
|
|
505
|
+
readonly request?: RequestPrediction;
|
|
506
|
+
/**
|
|
507
|
+
* These are the waits of the reconnect after the end of the connection, from the document of
|
|
508
|
+
* the client. The end has no band, but each wait has one. A wait outside its band is a finding of its run.
|
|
509
|
+
*/
|
|
510
|
+
readonly reconnects?: Reconnects;
|
|
511
|
+
};
|
|
512
|
+
/** A target is the server that a cell connects to: a stock image. */
|
|
513
|
+
interface Target {
|
|
514
|
+
/** This image is a stock image, pinned by digest. */
|
|
515
|
+
readonly image: string;
|
|
516
|
+
readonly port: number;
|
|
517
|
+
/** This text is the log line that tells that the target serves. */
|
|
518
|
+
readonly ready: string;
|
|
519
|
+
/**
|
|
520
|
+
* These commands set and read one setting of the target, as argv in it. The name and the value
|
|
521
|
+
* come after them: `redis-cli CONFIG SET` and `CONFIG GET` for Redis. Without them, the target
|
|
522
|
+
* has no settings to set.
|
|
523
|
+
*/
|
|
524
|
+
readonly settings?: {
|
|
525
|
+
readonly set: readonly string[];
|
|
526
|
+
readonly get: readonly string[];
|
|
527
|
+
};
|
|
528
|
+
/**
|
|
529
|
+
* This command replaces the command of the image, for example a shell that holds the server
|
|
530
|
+
* process as its child. Then a `fin` fault can stop the server, and the container stays up.
|
|
531
|
+
*/
|
|
532
|
+
readonly command?: readonly string[];
|
|
533
|
+
/** This command stops the server process in the target with SIGKILL, as argv, for a `fin` fault. */
|
|
534
|
+
readonly kill?: readonly string[];
|
|
535
|
+
/** This command makes the server close the connection of each client, as argv, for a `server-close` fault. */
|
|
536
|
+
readonly close?: readonly string[];
|
|
537
|
+
/**
|
|
538
|
+
* These files go into the target before it starts, by their path, for example the script of a
|
|
539
|
+
* server on a stock Node image. The image stays stock.
|
|
540
|
+
*/
|
|
541
|
+
readonly files?: Readonly<Record<string, string>>;
|
|
542
|
+
/**
|
|
543
|
+
* This flag tells that the target writes JSON lines with an `ev` and a `t` on its standard
|
|
544
|
+
* output, on CLOCK_MONOTONIC. Each run then keeps its lines (`Run.server`).
|
|
545
|
+
*/
|
|
546
|
+
readonly lines?: true;
|
|
547
|
+
/**
|
|
548
|
+
* This name is the server process, as /proc/PID/comm holds it. With it, a freeze of the target
|
|
549
|
+
* stops this process with SIGSTOP from a sidecar in its process namespace, and the injector
|
|
550
|
+
* stamps it. SIGCONT then thaws it. Without it, the freeze is the cgroup freezer, with no stamps.
|
|
551
|
+
*/
|
|
552
|
+
readonly program?: string;
|
|
553
|
+
/**
|
|
554
|
+
* This source is the image of a subject that the target operates in place of `image`. It is an
|
|
555
|
+
* image pinned by digest, a build context, or an image that the harness ships. `image` is then
|
|
556
|
+
* the stock base of that image, for the record. An example is a subject that holds a client
|
|
557
|
+
* and the script of its server.
|
|
558
|
+
*/
|
|
559
|
+
readonly subject?: ImageSource;
|
|
560
|
+
/**
|
|
561
|
+
* This name is an image of the harness that the target operates in place of `image`. It is a
|
|
562
|
+
* short form: `harness: "procedures"` is `subject: { kind: "shipped", name: "procedures" }`.
|
|
563
|
+
* `subject` replaces it.
|
|
564
|
+
*/
|
|
565
|
+
readonly harness?: HarnessImage;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* A harness image is an image of the harness that a target can operate by its name (`Target.harness`).
|
|
569
|
+
* `procedures` is the image of `@procedures/client` on Node: its WebSocket client and its server script.
|
|
570
|
+
*/
|
|
571
|
+
type HarnessImage = "procedures";
|
|
572
|
+
/**
|
|
573
|
+
* A shipped image is an image that the harness ships, by its name. Its build context is in the
|
|
574
|
+
* package of the harness, and in the package of the prober for `harness`.
|
|
575
|
+
*/
|
|
576
|
+
type Shipped = "harness" | "node" | "go-http" | "node-http" | "mongo" | "pg" | "hikari" | "procedures" | "router";
|
|
577
|
+
/**
|
|
578
|
+
* An image source tells where an image comes from, as data. The harness resolves each kind to an
|
|
579
|
+
* image that it can start:
|
|
580
|
+
* - `pinned`: an image of a registry, pinned by its digest. The lab pulls it.
|
|
581
|
+
* - `build`: a build context that the caller gives. The harness builds it, with a tag from its content.
|
|
582
|
+
* - `shipped`: an image that the harness ships, by its name. The harness builds it from its package.
|
|
583
|
+
*/
|
|
584
|
+
type ImageSource = PinnedImage | BuildImage | ShippedImage;
|
|
585
|
+
/** A pinned image is an image of a registry, pinned by its digest: `name@sha256:<64 hex digits>`. */
|
|
586
|
+
interface PinnedImage {
|
|
587
|
+
readonly kind: "pinned";
|
|
588
|
+
readonly image: string;
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* A build image is a build context that the caller gives. The harness copies its files into a new
|
|
592
|
+
* context and builds it. Each `FROM` of its Dockerfile names a digest, and each `package.json` or
|
|
593
|
+
* `Cargo.toml` has a lockfile beside it. Thus a build gives the same programs each time.
|
|
594
|
+
*/
|
|
595
|
+
interface BuildImage {
|
|
596
|
+
readonly kind: "build";
|
|
597
|
+
/** This name is the repository of the tag. The tag is the name, then 12 digits of the sha256 of the context. */
|
|
598
|
+
readonly name: string;
|
|
599
|
+
/** This folder is the root of the context. A relative path starts at the working folder of the process. */
|
|
600
|
+
readonly context: string;
|
|
601
|
+
/** This path is the Dockerfile, in the context. Without it, the path is `Dockerfile`. */
|
|
602
|
+
readonly dockerfile?: string | undefined;
|
|
603
|
+
/** These paths are the files and the folders that the Dockerfile reads, in the context. Without them, the context is all of its folder. */
|
|
604
|
+
readonly files?: readonly string[] | undefined;
|
|
605
|
+
}
|
|
606
|
+
/** A shipped image source names an image that the harness ships (`Shipped`). */
|
|
607
|
+
interface ShippedImage {
|
|
608
|
+
readonly kind: "shipped";
|
|
609
|
+
readonly name: Shipped;
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* A subject is a program under test, as data: the image that holds its programs, and the command
|
|
613
|
+
* of each program. A catalog of cells takes a subject. Thus another repository can give its own
|
|
614
|
+
* subject, with its own release in it. The harness ships some (`SUBJECTS`).
|
|
615
|
+
*/
|
|
616
|
+
interface Subject {
|
|
617
|
+
/** This name is the name of the subject in a catalog and in the records: `procedures`. */
|
|
618
|
+
readonly name: string;
|
|
619
|
+
/** This source is the image that holds the programs of the subject. */
|
|
620
|
+
readonly image: ImageSource;
|
|
621
|
+
/** This image is the stock base of the image, pinned by digest. A target of the subject names it (`Target.image`). */
|
|
622
|
+
readonly base: string;
|
|
623
|
+
/**
|
|
624
|
+
* These are the commands of the programs of the image by their role, each as argv: for example
|
|
625
|
+
* `client` and `server`. A run adds its arguments after the command.
|
|
626
|
+
*/
|
|
627
|
+
readonly programs: Readonly<Record<string, readonly string[]>>;
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* A client is what the runs of a cell use: the TCP client of the harness, or a driver on its
|
|
631
|
+
* socket. The HTTP clients are the `http.Transport` of Go (`go-http`), the `http.Agent` of Node
|
|
632
|
+
* (`http-agent`) and an HTTP/1.1 `Client` of undici (`undici`). The MongoDB driver is `mongodb`, node-postgres is `pg`, HikariCP over pgjdbc is `hikari`, and
|
|
633
|
+
* the WebSocket client of `@procedures/client` is `procedures-ws`.
|
|
634
|
+
*/
|
|
635
|
+
type Client = "tcp" | "ioredis" | "go-http" | "http-agent" | "undici" | "mongodb" | "pg" | "hikari" | "procedures-ws";
|
|
636
|
+
/**
|
|
637
|
+
* A WebSocket probe is the workload and the settings of the WebSocket client of
|
|
638
|
+
* `@procedures/client` (`procedures-ws`). The cell gives each setting, thus the client takes
|
|
639
|
+
* nothing from a default.
|
|
640
|
+
*/
|
|
641
|
+
interface WsProbe {
|
|
642
|
+
/**
|
|
643
|
+
* This name is the class of the sockets of the client: the global `WebSocket` of Node (`global`),
|
|
644
|
+
* or the `WebSocket` of the `ws` package (`ws`, the option `webSocket`).
|
|
645
|
+
*/
|
|
646
|
+
readonly socket: "global" | "ws";
|
|
647
|
+
/**
|
|
648
|
+
* These are the settings of the heartbeat: a ping each interval, the wait for its pong, and the
|
|
649
|
+
* misses in sequence that drop the connection. Null turns the heartbeat off.
|
|
650
|
+
*/
|
|
651
|
+
readonly heartbeat: {
|
|
652
|
+
readonly interval: Quantity;
|
|
653
|
+
readonly timeout: Quantity;
|
|
654
|
+
readonly misses: number;
|
|
655
|
+
} | null;
|
|
656
|
+
/**
|
|
657
|
+
* These are the settings of the reconnect: the first delay, the multiplier of each next delay,
|
|
658
|
+
* the longest delay and the most tries. `jitter` is the random part of each delay, from 0 to 1.
|
|
659
|
+
* Null turns the reconnect off.
|
|
660
|
+
*/
|
|
661
|
+
readonly reconnect: {
|
|
662
|
+
readonly initialDelay: Quantity;
|
|
663
|
+
readonly multiplier: number;
|
|
664
|
+
readonly maxDelay: Quantity;
|
|
665
|
+
readonly attempts: number;
|
|
666
|
+
readonly jitter: number;
|
|
667
|
+
} | null;
|
|
668
|
+
/** This time is how long a call waits for its first frame. */
|
|
669
|
+
readonly requestTimeout: Quantity;
|
|
670
|
+
/** This time is how long a call waits for a connection. */
|
|
671
|
+
readonly connectionTimeout: Quantity;
|
|
672
|
+
/** This time is how long the server holds the reply to the call in flight. Without it, the server replies at once. */
|
|
673
|
+
readonly hold?: Quantity;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* An HTTP probe is the workload of an HTTP client. The first request is a GET of the root. The
|
|
677
|
+
* second request follows the mode of the probe: after the signal (`inflight`), or after a gap
|
|
678
|
+
* (`gap`).
|
|
679
|
+
*/
|
|
680
|
+
interface HttpProbe {
|
|
681
|
+
/** This method is the method of the second request. */
|
|
682
|
+
readonly method: "GET" | "POST";
|
|
683
|
+
/** This time is the gap of a `gap` workload: from the end of the first reply to the second request. */
|
|
684
|
+
readonly gap?: Quantity;
|
|
685
|
+
/** This time is how long the server holds the reply to the second request (`/hold?ms=`). */
|
|
686
|
+
readonly hold?: Quantity;
|
|
687
|
+
/** This length is the length of the body of the reply to the second request, in bytes (`/big?bytes=`). */
|
|
688
|
+
readonly bytes?: number;
|
|
689
|
+
/** These are settings of the client over its defaults, by the names of its flags: for example `idle-conn-timeout-ms`. */
|
|
690
|
+
readonly options?: Readonly<Record<string, number>>;
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* A client image is a process that a lab starts as the client of each run, in the network
|
|
694
|
+
* namespace of the client. An example is an agent of an application on Node. Its command gets the
|
|
695
|
+
* arguments of the TCP client of the harness. These are the address and the port of the target, then
|
|
696
|
+
* the options of the cell. It writes JSON lines with an `ev` and a `t` (CLOCK_MONOTONIC in
|
|
697
|
+
* nanoseconds) on its standard output, as the client of the harness does.
|
|
698
|
+
*/
|
|
699
|
+
interface ClientImage {
|
|
700
|
+
/** This image is a stock image by its name, pinned by digest, or the source of the image of a subject. */
|
|
701
|
+
readonly image: string | ImageSource;
|
|
702
|
+
readonly command: readonly string[];
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* An observer is the side whose detection a cell measures. The client is one observer. The
|
|
706
|
+
* server is another observer. It is the hold of the target on the connection of the client, at
|
|
707
|
+
* its server socket in its namespace. The fault is on the peer of the observer. Thus
|
|
708
|
+
* freeze-process freezes the target for the client, and the client for the server.
|
|
709
|
+
*
|
|
710
|
+
* A proxy of a topology is the third observer: its socket toward the client, or its socket toward
|
|
711
|
+
* the target.
|
|
712
|
+
*/
|
|
713
|
+
type Observer = "client" | "server" | {
|
|
714
|
+
readonly hop: string;
|
|
715
|
+
readonly toward: "client" | "target";
|
|
716
|
+
};
|
|
717
|
+
/** A cell is one cell of the matrix: a topology, its settings, a workload, a fault and the prediction. */
|
|
718
|
+
interface Cell {
|
|
719
|
+
readonly name: string;
|
|
720
|
+
readonly target: Target;
|
|
721
|
+
/** These are the sysctls of the network namespace of the client, as the kernel spells them. The harness sets them before the client connects. */
|
|
722
|
+
readonly sysctls: Readonly<Record<string, string>>;
|
|
723
|
+
readonly probe: {
|
|
724
|
+
/**
|
|
725
|
+
* This mode tells if the client is idle after its first reply, or sends a request into the
|
|
726
|
+
* fault. In a stream, it sends `count` requests into it, each `interval` after the reply before.
|
|
727
|
+
* An HTTP client in a `gap` sends its second request a gap after its first reply, by itself.
|
|
728
|
+
*/
|
|
729
|
+
readonly mode: "idle" | "inflight" | "stream" | "gap";
|
|
730
|
+
/** This count is the number of requests of a stream. */
|
|
731
|
+
readonly count?: number;
|
|
732
|
+
/** This time is the pause after each reply of a stream, before the next request. */
|
|
733
|
+
readonly interval?: Quantity;
|
|
734
|
+
/** This flag sets SO_KEEPALIVE without overrides for the socket: the keepalive sysctls of the namespace apply. */
|
|
735
|
+
readonly keepalive: boolean;
|
|
736
|
+
/** This time sets TCP_USER_TIMEOUT. Without it, the default of the kernel (off) applies. */
|
|
737
|
+
readonly userTimeout?: Quantity;
|
|
738
|
+
/**
|
|
739
|
+
* This text is the request that an in-flight run sends, as a Redis inline command. Without it,
|
|
740
|
+
* the request is PING. BLPOP with a timeout makes the server answer only at the timeout. Thus
|
|
741
|
+
* a cell on the server side has a reply in flight when the fault occurs.
|
|
742
|
+
*/
|
|
743
|
+
readonly request?: string;
|
|
744
|
+
/**
|
|
745
|
+
* This driver replaces the TCP client of the harness, with its own options. The driver then
|
|
746
|
+
* ignores `keepalive` and `userTimeout`:
|
|
747
|
+
* - ioredis 6 on Node, whose keepAlive is the keepalive delay of the socket.
|
|
748
|
+
* - the MongoDB driver on Node, against the replica set `set`. Its operation is a write, or
|
|
749
|
+
* the read of a long document (`read-long`). `Cell.driverOptions` are its options.
|
|
750
|
+
* - node-postgres on Node, as a `pg.Pool` against one server. Its operation is `query`, or
|
|
751
|
+
* `SELECT 1`. `Cell.driverOptions` are the options of its pool.
|
|
752
|
+
* - HikariCP over pgjdbc on Java, as a `HikariDataSource` against one server. Its operation is
|
|
753
|
+
* `query`, or `SELECT 1`. `Cell.driverOptions` are the properties of HikariConfig, and a name
|
|
754
|
+
* with the prefix `dataSource.` is a property of pgjdbc.
|
|
755
|
+
*/
|
|
756
|
+
readonly driver?: {
|
|
757
|
+
readonly name: "ioredis";
|
|
758
|
+
readonly keepAlive: Quantity;
|
|
759
|
+
} | {
|
|
760
|
+
readonly name: "mongodb";
|
|
761
|
+
readonly set: string;
|
|
762
|
+
readonly op?: "write" | "read-long";
|
|
763
|
+
} | {
|
|
764
|
+
readonly name: "pg";
|
|
765
|
+
readonly query?: string;
|
|
766
|
+
} | {
|
|
767
|
+
readonly name: "hikari";
|
|
768
|
+
readonly query?: string;
|
|
769
|
+
};
|
|
770
|
+
/** This workload is the workload of an HTTP client (`Cell.client` is an HTTP client). The client then ignores `keepalive` and `userTimeout`. */
|
|
771
|
+
readonly http?: HttpProbe;
|
|
772
|
+
/** These are the settings of the WebSocket client (`Cell.client` is `procedures-ws`). The client then ignores `keepalive` and `userTimeout`. */
|
|
773
|
+
readonly ws?: WsProbe;
|
|
774
|
+
};
|
|
775
|
+
readonly fault: Fault;
|
|
776
|
+
/** This time is the length of a stall, from the send of the request. */
|
|
777
|
+
readonly stall?: Quantity;
|
|
778
|
+
/** This code is the ICMP unreachable of an `unreachable` fault. */
|
|
779
|
+
readonly icmp?: "host" | "net" | "port" | "admin";
|
|
780
|
+
/** This direction is the one that a `simplex` fault drops: the segments to the server, or to the client. */
|
|
781
|
+
readonly drops?: "to-server" | "to-client";
|
|
782
|
+
/** This length is the longest segment, in bytes, that an `mtu-blackhole` fault lets through to the observer. */
|
|
783
|
+
readonly mtu?: number;
|
|
784
|
+
/**
|
|
785
|
+
* This specification is the tc netem of a `netem` fault, for example "loss 5%". It is on the
|
|
786
|
+
* egress of the target, or at a hop (`faultAt`) on the egress of its device toward one side.
|
|
787
|
+
*/
|
|
788
|
+
readonly netem?: string;
|
|
789
|
+
/**
|
|
790
|
+
* This delay goes on the egress of the target before the client connects, with tc netem. Thus
|
|
791
|
+
* each round trip is longer by the delay, and so is the RTO.
|
|
792
|
+
*/
|
|
793
|
+
readonly latency?: Quantity;
|
|
794
|
+
/** These commands run in the target before a client connects, each as argv: for example, a large value to read. */
|
|
795
|
+
readonly targetSetup?: readonly (readonly string[])[];
|
|
796
|
+
readonly prediction: Prediction;
|
|
797
|
+
/** This side is the side whose detection the cell measures. Without it, the side is the client. */
|
|
798
|
+
readonly observer?: Observer;
|
|
799
|
+
/** These are the settings of the target. The harness sets them in each environment before a client connects. */
|
|
800
|
+
readonly targetSettings?: Readonly<Record<string, string>>;
|
|
801
|
+
/** These are the sysctls of the network namespace of the target, for a cell on the server side: its tcp_retries2. */
|
|
802
|
+
readonly targetSysctls?: Readonly<Record<string, string>>;
|
|
803
|
+
/** This topology puts hops between the client and the target. Without it, the client and the target are a direct pair. */
|
|
804
|
+
readonly topology?: Topology;
|
|
805
|
+
/** This place is where the fault goes, when it is not the peer of the observer: for example one side of a hop. */
|
|
806
|
+
readonly faultAt?: FaultPlace;
|
|
807
|
+
/** This time is how long an in-flight client stays idle after the fault holds, before it sends its request. */
|
|
808
|
+
readonly idleBefore?: Quantity;
|
|
809
|
+
/** This toxic is the toxic of a `toxic` fault, which the Toxiproxy hop gets. */
|
|
810
|
+
readonly toxic?: Toxic;
|
|
811
|
+
/** This image, or this client of the harness, replaces the TCP client of the harness for each run. An HTTP client is one. */
|
|
812
|
+
readonly client?: ClientImage | Client;
|
|
813
|
+
/**
|
|
814
|
+
* This name is the proxy hop whose own time a calibration cell measures. The time of a request
|
|
815
|
+
* (`up`) starts at its arrival on the socket of the proxy toward the client. It stops at the
|
|
816
|
+
* write on the socket toward the target. The time of its reply (`down`) goes the other way.
|
|
817
|
+
*
|
|
818
|
+
* For a group cell, `sentinels` makes the prober watch the namespace of each Sentinel too. Each
|
|
819
|
+
* stamp of the observer then gets the write of its Sentinel that it read (`lags`).
|
|
820
|
+
*/
|
|
821
|
+
readonly calibrates?: string;
|
|
822
|
+
/**
|
|
823
|
+
* This group replaces the target: a replicated group under its Sentinels. The client is then
|
|
824
|
+
* ioredis in Sentinel mode, and it writes a stream of sequence numbers. `target` stays for the
|
|
825
|
+
* record, and the group does not read it.
|
|
826
|
+
*/
|
|
827
|
+
readonly group?: Group;
|
|
828
|
+
/**
|
|
829
|
+
* This replica set replaces the target: a replicated group whose members elect their own
|
|
830
|
+
* primary. The client is then the MongoDB driver, and it writes a stream of sequence numbers.
|
|
831
|
+
* `target` stays for the record, and the set does not read it.
|
|
832
|
+
*/
|
|
833
|
+
readonly replicaSet?: ReplicaSet;
|
|
834
|
+
/**
|
|
835
|
+
* This time is how long a fault on a group holds after its commit. The injector then lifts it at
|
|
836
|
+
* that instant, on the clock of the VM. On a direct pair, a frozen target thaws after it.
|
|
837
|
+
*/
|
|
838
|
+
readonly hold?: Quantity;
|
|
839
|
+
/** This flag makes a planned failover coordinated: `SENTINEL FAILOVER <group> COORDINATED`. */
|
|
840
|
+
readonly coordinated?: boolean;
|
|
841
|
+
/**
|
|
842
|
+
* These are options of the driver over its defaults: of ioredis for the client of a group, or of
|
|
843
|
+
* the MongoDB driver for its client. A cell at the defaults has none.
|
|
844
|
+
*/
|
|
845
|
+
readonly driverOptions?: Readonly<Record<string, unknown>>;
|
|
846
|
+
/** This write concern is the w of each write of the MongoDB client. Without it, it is majority. */
|
|
847
|
+
readonly writeConcern?: "majority" | 1;
|
|
848
|
+
/** This flag makes the fault hold before the client starts. The client then meets it at its first selection. */
|
|
849
|
+
readonly before?: boolean;
|
|
850
|
+
/** This count is the number of runs of the cell (11), across new environments (two at least). */
|
|
851
|
+
readonly runs: number;
|
|
852
|
+
readonly environments: number;
|
|
853
|
+
/**
|
|
854
|
+
* This count is the number of environments at the same time, each with its own prober. Without
|
|
855
|
+
* it, the count is one. The calibration does its reference cells at 1, 4 and 8, to find how
|
|
856
|
+
* many environments the machine holds before its noise increases.
|
|
857
|
+
*/
|
|
858
|
+
readonly concurrency?: number;
|
|
859
|
+
/**
|
|
860
|
+
* This time is δ_abs of the environment of the cell: the noise of the pipeline. Each band includes
|
|
861
|
+
* it, and a timer must be at least that late to make a run void. Stage 0 measures it in each
|
|
862
|
+
* environment. Without it, the cell gets `NOISE`, the δ_abs of the first environment (4 ms).
|
|
863
|
+
*/
|
|
864
|
+
readonly noise?: Quantity;
|
|
865
|
+
}
|
|
866
|
+
/** A hop place is a hop of a topology, with the side that the rules of a fault face. */
|
|
867
|
+
interface HopPlace {
|
|
868
|
+
readonly hop: string;
|
|
869
|
+
readonly toward: "client" | "target";
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* A fault place is the namespace that gets the rules of a fault. "target" and "client" are the two
|
|
873
|
+
* ends. A hop place is a hop, with the side that the rules face. That side is the next hop toward
|
|
874
|
+
* the client, or the next hop toward the target. The rules of a proxy act on its sockets. The
|
|
875
|
+
* rules of a router act on what it forwards, by its device toward that side: the FORWARD chain.
|
|
876
|
+
*
|
|
877
|
+
* A group place is a part of a group, by its role.
|
|
878
|
+
*/
|
|
879
|
+
type FaultPlace = "target" | "client" | HopPlace | GroupPlace;
|
|
880
|
+
/** This function tells if a fault place is a hop of a topology. */
|
|
881
|
+
declare const isHopPlace: (place: FaultPlace | undefined) => place is HopPlace;
|
|
882
|
+
/**
|
|
883
|
+
* This function gives the latest end of a band in seconds, from the reply of the client. It is
|
|
884
|
+
* the high bound, after the latest reference of the band (`startsBy`).
|
|
885
|
+
*/
|
|
886
|
+
declare const latestEndOf: (prediction: Extract<Prediction, {
|
|
887
|
+
readonly detects: true;
|
|
888
|
+
}>) => number;
|
|
889
|
+
/** A middlebox event is one line of the router: a change of a conntrack entry, or a reset that it sent. `t` is CLOCK_MONOTONIC in nanoseconds. */
|
|
890
|
+
interface MiddleboxEvent {
|
|
891
|
+
readonly ev: string;
|
|
892
|
+
readonly t: number;
|
|
893
|
+
readonly [field: string]: unknown;
|
|
894
|
+
}
|
|
895
|
+
/** A probe event is one line that the client wrote. `t` is CLOCK_MONOTONIC in nanoseconds: an instant, not an amount. */
|
|
896
|
+
interface ProbeEvent {
|
|
897
|
+
readonly ev: string;
|
|
898
|
+
readonly t: number;
|
|
899
|
+
readonly [field: string]: unknown;
|
|
900
|
+
}
|
|
901
|
+
/** A run is one run of a cell, as the harness records it. */
|
|
902
|
+
interface Run {
|
|
903
|
+
readonly environment: number;
|
|
904
|
+
readonly index: number;
|
|
905
|
+
/**
|
|
906
|
+
* This flag marks the warm-up of an environment. It occurs before the counted runs, and the
|
|
907
|
+
* verdict does not count it. On a loaded machine, a new environment is sometimes slow at first.
|
|
908
|
+
*/
|
|
909
|
+
readonly warmup?: true;
|
|
910
|
+
readonly events: readonly ProbeEvent[];
|
|
911
|
+
/** This bracket is the time of the injector around the commit of the fault, on the same clock. It is null for a freeze. */
|
|
912
|
+
readonly fault: {
|
|
913
|
+
readonly t0: number;
|
|
914
|
+
readonly t1: number;
|
|
915
|
+
} | null;
|
|
916
|
+
/** This bracket is the time around the commit that stopped a stall. */
|
|
917
|
+
readonly heal?: {
|
|
918
|
+
readonly t0: number;
|
|
919
|
+
readonly t1: number;
|
|
920
|
+
} | null;
|
|
921
|
+
/** These are the records of the prober from the start to the end of the run, in the two namespaces. */
|
|
922
|
+
readonly kernel: readonly KernelRecord[];
|
|
923
|
+
/** This inode identifies the network namespace of the client, thus the records of the client. */
|
|
924
|
+
readonly netns: number;
|
|
925
|
+
/** This inode identifies the namespace of the target, where the records of its server socket are. */
|
|
926
|
+
readonly targetNetns: number;
|
|
927
|
+
/**
|
|
928
|
+
* This count is the number of records that the prober lost in the run. One lost record makes
|
|
929
|
+
* the run void. Null also makes the run void: no clock line came after the run to tell the count.
|
|
930
|
+
*/
|
|
931
|
+
readonly lost: number | null;
|
|
932
|
+
/**
|
|
933
|
+
* This rate is the HZ of the kernel of the environment, from its manifest. With it, the rule of a
|
|
934
|
+
* late timer is in time. A run without it keeps the rule in jiffies, as the runs before 0.9.0.
|
|
935
|
+
*/
|
|
936
|
+
readonly hz?: number;
|
|
937
|
+
/** These are the addresses and the namespaces of a topology, which the measurement of a run reads. */
|
|
938
|
+
readonly topology?: RunTopology;
|
|
939
|
+
/** These are the lines of the routers of a topology from the start to the end of the run. */
|
|
940
|
+
readonly middlebox?: readonly MiddleboxEvent[];
|
|
941
|
+
/** This record is the group of a group cell: its parts, and what it did in the run. */
|
|
942
|
+
readonly group?: RunGroup;
|
|
943
|
+
/** These are the lines of a target that writes them (`Target.lines`), from the start to the end of the run. */
|
|
944
|
+
readonly server?: readonly ProbeEvent[];
|
|
945
|
+
}
|
|
946
|
+
/** A Sentinel event is one line of the observer of a group: an event that a Sentinel published, on the clock of the VM. */
|
|
947
|
+
interface SentinelEvent {
|
|
948
|
+
readonly ev: string;
|
|
949
|
+
readonly t: number;
|
|
950
|
+
/** This text is the address and port of the Sentinel. */
|
|
951
|
+
readonly sentinel?: string;
|
|
952
|
+
/** This name is the event, for example `+switch-master`. */
|
|
953
|
+
readonly event?: string;
|
|
954
|
+
/** This text is the detail of the event, as the Sentinel wrote it. */
|
|
955
|
+
readonly detail?: string;
|
|
956
|
+
readonly [field: string]: unknown;
|
|
957
|
+
}
|
|
958
|
+
/** A part is one member or Sentinel of a group, as a run found it: its address and its network namespace. */
|
|
959
|
+
interface RunPart {
|
|
960
|
+
readonly ip: string;
|
|
961
|
+
readonly netns: number;
|
|
962
|
+
}
|
|
963
|
+
/** A run group is the group of a run: its parts, the primary before and after, the timeline, and the writes that it kept. */
|
|
964
|
+
interface RunGroup {
|
|
965
|
+
readonly members: Readonly<Record<string, RunPart>>;
|
|
966
|
+
readonly sentinels: Readonly<Record<string, RunPart>>;
|
|
967
|
+
/** This name is the member that was the primary at the start of the run. */
|
|
968
|
+
readonly primary: string;
|
|
969
|
+
/** This name is the part that got the fault, or null for a fault on the whole group. */
|
|
970
|
+
readonly at: string | null;
|
|
971
|
+
/**
|
|
972
|
+
* These are the lines of the timeline from the start to the end of the run. For a group under
|
|
973
|
+
* Sentinels, they are the lines of the observer of the Sentinels. For a replica set, they are
|
|
974
|
+
* the log lines of the members (`ev` "mongod"), with their times on the monotonic clock.
|
|
975
|
+
*/
|
|
976
|
+
readonly timeline: readonly SentinelEvent[];
|
|
977
|
+
/** This name is the member that was the primary when the group converged after the run, or null when it did not converge. */
|
|
978
|
+
readonly after: string | null;
|
|
979
|
+
/** These are the sequence numbers that the group holds after the run, when it converged, or null. */
|
|
980
|
+
readonly holds: readonly number[] | null;
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* A run topology tells where each socket of a run is, in a topology:
|
|
984
|
+
* - `targetPeer` is the address of the peer of the target, as the target sees it: the address of
|
|
985
|
+
* the last hop.
|
|
986
|
+
* - `hops` are the network namespaces of the hops, by their names, with the address of the peer of
|
|
987
|
+
* each hop on each side.
|
|
988
|
+
*/
|
|
989
|
+
interface RunTopology {
|
|
990
|
+
readonly targetPeer: string;
|
|
991
|
+
readonly hops: Readonly<Record<string, {
|
|
992
|
+
readonly netns: number;
|
|
993
|
+
readonly client: string;
|
|
994
|
+
readonly target: string;
|
|
995
|
+
}>>;
|
|
996
|
+
}
|
|
997
|
+
//#endregion
|
|
998
|
+
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-Di_YHiuB.d.ts.map
|