@mark1russell7/harness 0.4.1 → 0.6.0
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 +74 -5
- package/build/index.d.ts +595 -13
- package/build/index.js +1249 -25
- package/build/index.js.map +1 -1
- package/image/go-http/Dockerfile +14 -0
- package/image/go-http/go.mod +3 -0
- package/image/go-http/main.go +324 -0
- package/image/native/src/bin/inject.rs +182 -4
- package/image/node/Dockerfile +3 -2
- package/image/node/client-sentinel.mjs +106 -0
- package/image/node/observer.mjs +39 -0
- package/image/node-http/Dockerfile +12 -0
- package/image/node-http/client-agent.mjs +163 -0
- package/image/node-http/client-undici.mjs +141 -0
- package/image/node-http/lines.mjs +59 -0
- package/image/node-http/npm-lock.json +22 -0
- package/image/node-http/package.json +8 -0
- package/package.json +13 -2
package/build/index.d.ts
CHANGED
|
@@ -35,8 +35,20 @@ import "testcontainers";
|
|
|
35
35
|
* A fault at a router of the topology (`Cell.faultAt`) acts on what the router forwards toward
|
|
36
36
|
* one side. It is a black hole, a reset or an ICMP unreachable. It can also be a simplex drop, an
|
|
37
37
|
* MTU drop or netem.
|
|
38
|
+
*
|
|
39
|
+
* These faults are of a replicated group (`Cell.group`), on the part that `Cell.faultAt` names:
|
|
40
|
+
* - `blackhole` drops each segment between the part and each of its peers. `rst` answers each
|
|
41
|
+
* segment from a peer with a reset, thus the part refuses each connection.
|
|
42
|
+
* - `partition` is a black hole between the part and some of its peers only (`GroupPlace.cuts`).
|
|
43
|
+
* - `freeze-process` stops the server process of the part with SIGSTOP, and SIGCONT thaws it. Its
|
|
44
|
+
* kernel stays up. `fin` stops the process with SIGKILL.
|
|
45
|
+
* - `planned-failover` asks a Sentinel for a failover: `SENTINEL FAILOVER <group>`.
|
|
46
|
+
*
|
|
47
|
+
* This fault is of an HTTP server:
|
|
48
|
+
* - `app-stall` injects nothing. The server process holds the reply to the request, because the
|
|
49
|
+
* request asks for that (`HttpProbe.hold`), while its kernel stays up.
|
|
38
50
|
*/
|
|
39
|
-
type Fault = "blackhole" | "freeze-process" | "rst" | "stall" | "fin" | "unreachable" | "simplex" | "mtu-blackhole" | "netem" | "middlebox-forget" | "proxy-idle" | "toxic" | "server-close" | "none";
|
|
51
|
+
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" | "none";
|
|
40
52
|
/**
|
|
41
53
|
* A middlebox form tells what a router does with a flow that it forgot, when a late packet comes:
|
|
42
54
|
* - `reset-both` sends a reset to the two ends when it forgets the flow.
|
|
@@ -108,6 +120,57 @@ interface Topology {
|
|
|
108
120
|
readonly name: string;
|
|
109
121
|
readonly hops: readonly Hop[];
|
|
110
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* A group is a replicated group under an external failover authority, as data. It is a primary and
|
|
125
|
+
* its replicas, and the Sentinels that decide which member is the primary. Each member and each
|
|
126
|
+
* Sentinel is a container from the same stock image, pinned by digest. Each has its own network
|
|
127
|
+
* namespace, thus a fault can act on one part. The client finds the primary through the
|
|
128
|
+
* Sentinels, and the parts and the client share one network.
|
|
129
|
+
*/
|
|
130
|
+
interface Group {
|
|
131
|
+
/** This name is the name of the group that the Sentinels monitor, for example `mymaster`. */
|
|
132
|
+
readonly name: string;
|
|
133
|
+
/** This image is the stock image of each member and each Sentinel, pinned by digest. */
|
|
134
|
+
readonly image: string;
|
|
135
|
+
/** These are the programs of the image: the server, the Sentinel and the command line client. */
|
|
136
|
+
readonly programs: {
|
|
137
|
+
readonly server: string;
|
|
138
|
+
readonly sentinel: string;
|
|
139
|
+
readonly cli: string;
|
|
140
|
+
};
|
|
141
|
+
readonly port: number;
|
|
142
|
+
readonly sentinelPort: number;
|
|
143
|
+
/** These are the names of the members. The first one is the primary when the environment starts. */
|
|
144
|
+
readonly members: readonly string[];
|
|
145
|
+
readonly sentinels: readonly string[];
|
|
146
|
+
/** This count is how many Sentinels must agree that the primary is down. */
|
|
147
|
+
readonly quorum: number;
|
|
148
|
+
/** These are the settings of each member, as its configuration file spells them. The harness adds `replicaof` for each replica. */
|
|
149
|
+
readonly memberSettings: Readonly<Record<string, string>>;
|
|
150
|
+
/**
|
|
151
|
+
* These are the settings of each Sentinel for the group, as `sentinel <setting> <group> <value>`
|
|
152
|
+
* spells them: `down-after-milliseconds`, `failover-timeout` and `parallel-syncs`.
|
|
153
|
+
*/
|
|
154
|
+
readonly sentinelSettings: Readonly<Record<string, string>>;
|
|
155
|
+
/** These lines tell that a member and a Sentinel serve. */
|
|
156
|
+
readonly ready: {
|
|
157
|
+
readonly member: string;
|
|
158
|
+
readonly sentinel: string;
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/** 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. */
|
|
162
|
+
type GroupRole = "primary" | "replica" | "sentinel";
|
|
163
|
+
/**
|
|
164
|
+
* A group place is the part of a group that a fault acts on. A network fault cuts the part from
|
|
165
|
+
* some of its peers:
|
|
166
|
+
* - `all`: each other part of the group, and each client. This is the default.
|
|
167
|
+
* - `group`: the other members and the Sentinels, but not the clients.
|
|
168
|
+
* - `clients`: the clients, but not the group.
|
|
169
|
+
*/
|
|
170
|
+
interface GroupPlace {
|
|
171
|
+
readonly role: GroupRole;
|
|
172
|
+
readonly cuts?: "all" | "group" | "clients";
|
|
173
|
+
}
|
|
111
174
|
/** A toxic is one toxic of Toxiproxy, as its API takes it. Its toxicity is 1. */
|
|
112
175
|
interface Toxic {
|
|
113
176
|
readonly type: "latency" | "timeout" | "reset_peer" | "slow_close" | "bandwidth" | "limit_data" | "slicer";
|
|
@@ -176,12 +239,71 @@ interface ProxyTime {
|
|
|
176
239
|
readonly quantile: number;
|
|
177
240
|
readonly time: Quantity;
|
|
178
241
|
}
|
|
242
|
+
/**
|
|
243
|
+
* A stage is one step of the timeline of a group after a fault, by the event that a Sentinel
|
|
244
|
+
* publishes for it. The stages are the subjective down, the objective down, the start of a
|
|
245
|
+
* failover and the election. Then the selection of a replica, the promotion, the switch to the new
|
|
246
|
+
* primary, and the conversion of the old primary into a replica.
|
|
247
|
+
*/
|
|
248
|
+
type Stage = "+sdown" | "+odown" | "+try-failover" | "+elected-leader" | "+selected-slave" | "+promoted-slave" | "+switch-master" | "+convert-to-slave";
|
|
249
|
+
/** A stage band is when the first Sentinel announces a stage, from the reference of the cell. */
|
|
250
|
+
interface StageBand {
|
|
251
|
+
readonly stage: Stage;
|
|
252
|
+
readonly low: Quantity;
|
|
253
|
+
readonly high: Quantity;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* A group prediction tells what a group does after the fault, beside the band of its cell:
|
|
257
|
+
* - `lands` is the primary that the first accepted write after the fault lands on: a new one, or the same one.
|
|
258
|
+
* - `failover` tells if a Sentinel announces a switch to a new primary in the window.
|
|
259
|
+
* - `stages` are the bands of the stages of the timeline. Each band includes the error of the
|
|
260
|
+
* stamps of the observer (`stamps`).
|
|
261
|
+
* - `errors` are the errors that the client must meet on the way, each with the band of its
|
|
262
|
+
* first occurrence. An example is the error of the offline queue when it gives up.
|
|
263
|
+
*/
|
|
264
|
+
interface GroupPrediction {
|
|
265
|
+
readonly lands: "new" | "same";
|
|
266
|
+
readonly failover: boolean;
|
|
267
|
+
readonly stages: readonly StageBand[];
|
|
268
|
+
readonly stamps?: Quantity;
|
|
269
|
+
readonly errors?: ReadonlyArray<{
|
|
270
|
+
readonly name: string;
|
|
271
|
+
readonly low: Quantity;
|
|
272
|
+
readonly high: Quantity;
|
|
273
|
+
}>;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* A middlebox expectation tells what the router of a topology does with the flow in the window of
|
|
277
|
+
* a silent prediction. Without it, the router keeps the flow. With `forgets`, the router forgets
|
|
278
|
+
* the flow in that band after the last segment of the client, and nothing detects it.
|
|
279
|
+
*/
|
|
280
|
+
interface MiddleboxExpectation {
|
|
281
|
+
readonly forgets: {
|
|
282
|
+
readonly low: Quantity;
|
|
283
|
+
readonly high: Quantity;
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* A request prediction tells what the second request of an HTTP client meets, beside the band of
|
|
288
|
+
* its cell. The client writes it in its lines: the connection of each try, and the outcome.
|
|
289
|
+
* - `connection` is the connection of its first try: the one that the first request used
|
|
290
|
+
* (`reused`), or a new one.
|
|
291
|
+
* - `retried` tells that the client sent it again on a new connection by itself.
|
|
292
|
+
* - `error` is the error that reaches the caller, or null for a reply.
|
|
293
|
+
* - `pending` tells that nothing ends the request in the window of the cell.
|
|
294
|
+
*/
|
|
295
|
+
interface RequestPrediction {
|
|
296
|
+
readonly connection: "reused" | "new";
|
|
297
|
+
readonly retried: boolean;
|
|
298
|
+
readonly error: string | null;
|
|
299
|
+
readonly pending?: true;
|
|
300
|
+
}
|
|
179
301
|
/**
|
|
180
302
|
* A prediction is what a cell predicts. Either a detection occurs in an interval [T_lo, T_hi]
|
|
181
303
|
* after the reference event, or nothing detects the fault in a window. Nothing detects a stall
|
|
182
304
|
* that is shorter than the give-up, and the connection recovers from it. The prediction then also
|
|
183
305
|
* tells when. A silent prediction can also tell when the reply to the request comes back
|
|
184
|
-
* (`replies`).
|
|
306
|
+
* (`replies`), and what a router does with the flow (`middlebox`).
|
|
185
307
|
*
|
|
186
308
|
* A band can name the first round trip that it assumes (`rtt`), and the proxy times that it
|
|
187
309
|
* includes (`through`).
|
|
@@ -190,12 +312,21 @@ interface ProxyTime {
|
|
|
190
312
|
* prediction is `detects: null` with the reason, and its runs are measurements only. A
|
|
191
313
|
* measurement-only cell that names a reference (`from`) also records the time from it to the end
|
|
192
314
|
* of the connection, or to the last data.
|
|
315
|
+
*
|
|
316
|
+
* For a group cell, the band is the first write that a primary accepts after the fault, and its
|
|
317
|
+
* errno is `OK`. `group` tells which primary, and the stages of the group on the way.
|
|
318
|
+
*
|
|
319
|
+
* For an HTTP cell, `request` tells what the second request meets. The errno `CLOSED` is a close
|
|
320
|
+
* of the observer itself: its pool closes an idle connection, a FIN that it sends.
|
|
193
321
|
*/
|
|
194
322
|
type Prediction = {
|
|
195
323
|
readonly detects: true;
|
|
196
324
|
/** This name is the timer of the machine that fires first, or the event that detects the fault, with its errno. */
|
|
197
325
|
readonly timer: string;
|
|
198
|
-
/**
|
|
326
|
+
/**
|
|
327
|
+
* This name is the errno of the detection, or EOF for an end of file without an error. It is
|
|
328
|
+
* OK for a write that a primary accepts, and CLOSED for a close of the observer itself.
|
|
329
|
+
*/
|
|
199
330
|
readonly errno: string;
|
|
200
331
|
readonly from: Reference;
|
|
201
332
|
/** This time is the closed form, less the most that the timer can fire early. */
|
|
@@ -204,18 +335,25 @@ type Prediction = {
|
|
|
204
335
|
readonly high: Quantity;
|
|
205
336
|
readonly rtt?: RttRange;
|
|
206
337
|
readonly through?: readonly ProxyTime[];
|
|
338
|
+
readonly group?: GroupPrediction;
|
|
339
|
+
readonly request?: RequestPrediction;
|
|
207
340
|
} | {
|
|
208
341
|
readonly detects: false;
|
|
209
342
|
readonly window: Quantity;
|
|
210
343
|
readonly recovers?: Recovers;
|
|
211
344
|
readonly replies?: Replies;
|
|
345
|
+
readonly middlebox?: MiddleboxExpectation;
|
|
212
346
|
readonly rtt?: RttRange;
|
|
213
347
|
readonly through?: readonly ProxyTime[];
|
|
348
|
+
readonly group?: GroupPrediction;
|
|
349
|
+
readonly request?: RequestPrediction;
|
|
214
350
|
} | {
|
|
215
351
|
readonly detects: null;
|
|
216
352
|
readonly window: Quantity;
|
|
217
353
|
readonly why: string;
|
|
218
354
|
readonly from?: Reference;
|
|
355
|
+
readonly group?: GroupPrediction;
|
|
356
|
+
readonly request?: RequestPrediction;
|
|
219
357
|
};
|
|
220
358
|
/** A target is the server that a cell connects to: a stock image. */
|
|
221
359
|
interface Target {
|
|
@@ -242,9 +380,40 @@ interface Target {
|
|
|
242
380
|
readonly kill?: readonly string[];
|
|
243
381
|
/** This command makes the server close the connection of each client, as argv, for a `server-close` fault. */
|
|
244
382
|
readonly close?: readonly string[];
|
|
383
|
+
/**
|
|
384
|
+
* These files go into the target before it starts, by their path, for example the script of a
|
|
385
|
+
* server on a stock Node image. The image stays stock.
|
|
386
|
+
*/
|
|
387
|
+
readonly files?: Readonly<Record<string, string>>;
|
|
388
|
+
/**
|
|
389
|
+
* This flag tells that the target writes JSON lines with an `ev` and a `t` on its standard
|
|
390
|
+
* output, on CLOCK_MONOTONIC. Each run then keeps its lines (`Run.server`).
|
|
391
|
+
*/
|
|
392
|
+
readonly lines?: true;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* A client is what the runs of a cell use: the TCP client of the harness, or a driver on its
|
|
396
|
+
* socket. The HTTP clients are the `http.Transport` of Go (`go-http`), the `http.Agent` of Node
|
|
397
|
+
* (`http-agent`) and an HTTP/1.1 `Client` of undici (`undici`).
|
|
398
|
+
*/
|
|
399
|
+
type Client = "tcp" | "ioredis" | "go-http" | "http-agent" | "undici";
|
|
400
|
+
/**
|
|
401
|
+
* An HTTP probe is the workload of an HTTP client. The first request is a GET of the root. The
|
|
402
|
+
* second request follows the mode of the probe: after the signal (`inflight`), or after a gap
|
|
403
|
+
* (`gap`).
|
|
404
|
+
*/
|
|
405
|
+
interface HttpProbe {
|
|
406
|
+
/** This method is the method of the second request. */
|
|
407
|
+
readonly method: "GET" | "POST";
|
|
408
|
+
/** This time is the gap of a `gap` workload: from the end of the first reply to the second request. */
|
|
409
|
+
readonly gap?: Quantity;
|
|
410
|
+
/** This time is how long the server holds the reply to the second request (`/hold?ms=`). */
|
|
411
|
+
readonly hold?: Quantity;
|
|
412
|
+
/** This length is the length of the body of the reply to the second request, in bytes (`/big?bytes=`). */
|
|
413
|
+
readonly bytes?: number;
|
|
414
|
+
/** These are settings of the client over its defaults, by the names of its flags: for example `idle-conn-timeout-ms`. */
|
|
415
|
+
readonly options?: Readonly<Record<string, number>>;
|
|
245
416
|
}
|
|
246
|
-
/** A client is what the runs of a cell use: the TCP client of the harness, or a driver on its socket. */
|
|
247
|
-
type Client = "tcp" | "ioredis";
|
|
248
417
|
/**
|
|
249
418
|
* A client image is a process that a lab starts as the client of each run, in the network
|
|
250
419
|
* namespace of the client. An example is an agent of an application on Node. Its command gets the
|
|
@@ -279,8 +448,9 @@ interface Cell {
|
|
|
279
448
|
/**
|
|
280
449
|
* This mode tells if the client is idle after its first reply, or sends a request into the
|
|
281
450
|
* fault. In a stream, it sends `count` requests into it, each `interval` after the reply before.
|
|
451
|
+
* An HTTP client in a `gap` sends its second request a gap after its first reply, by itself.
|
|
282
452
|
*/
|
|
283
|
-
readonly mode: "idle" | "inflight" | "stream";
|
|
453
|
+
readonly mode: "idle" | "inflight" | "stream" | "gap";
|
|
284
454
|
/** This count is the number of requests of a stream. */
|
|
285
455
|
readonly count?: number;
|
|
286
456
|
/** This time is the pause after each reply of a stream, before the next request. */
|
|
@@ -304,6 +474,8 @@ interface Cell {
|
|
|
304
474
|
readonly name: "ioredis";
|
|
305
475
|
readonly keepAlive: Quantity;
|
|
306
476
|
};
|
|
477
|
+
/** This workload is the workload of an HTTP client (`Cell.client` is an HTTP client). The client then ignores `keepalive` and `userTimeout`. */
|
|
478
|
+
readonly http?: HttpProbe;
|
|
307
479
|
};
|
|
308
480
|
readonly fault: Fault;
|
|
309
481
|
/** This time is the length of a stall, from the send of the request. */
|
|
@@ -341,14 +513,29 @@ interface Cell {
|
|
|
341
513
|
readonly idleBefore?: Quantity;
|
|
342
514
|
/** This toxic is the toxic of a `toxic` fault, which the Toxiproxy hop gets. */
|
|
343
515
|
readonly toxic?: Toxic;
|
|
344
|
-
/** This image replaces the TCP client of the harness for each run. */
|
|
345
|
-
readonly client?: ClientImage;
|
|
516
|
+
/** This image, or this client of the harness, replaces the TCP client of the harness for each run. An HTTP client is one. */
|
|
517
|
+
readonly client?: ClientImage | Client;
|
|
346
518
|
/**
|
|
347
519
|
* This name is the proxy hop whose own time a calibration cell measures. The time of a request
|
|
348
520
|
* (`up`) starts at its arrival on the socket of the proxy toward the client. It stops at the
|
|
349
521
|
* write on the socket toward the target. The time of its reply (`down`) goes the other way.
|
|
522
|
+
*
|
|
523
|
+
* For a group cell, `sentinels` makes the prober watch the namespace of each Sentinel too. Each
|
|
524
|
+
* stamp of the observer then gets the write of its Sentinel that it read (`lags`).
|
|
350
525
|
*/
|
|
351
526
|
readonly calibrates?: string;
|
|
527
|
+
/**
|
|
528
|
+
* This group replaces the target: a replicated group under its Sentinels. The client is then
|
|
529
|
+
* ioredis in Sentinel mode, and it writes a stream of sequence numbers. `target` stays for the
|
|
530
|
+
* record, and the group does not read it.
|
|
531
|
+
*/
|
|
532
|
+
readonly group?: Group;
|
|
533
|
+
/** This time is how long a fault on a group holds after its commit. The injector then lifts it at that instant, on the clock of the VM. */
|
|
534
|
+
readonly hold?: Quantity;
|
|
535
|
+
/** This flag makes a planned failover coordinated: `SENTINEL FAILOVER <group> COORDINATED`. */
|
|
536
|
+
readonly coordinated?: boolean;
|
|
537
|
+
/** These are options of ioredis over its defaults, for the client of a group. A cell at the defaults has none. */
|
|
538
|
+
readonly driverOptions?: Readonly<Record<string, unknown>>;
|
|
352
539
|
/** This count is the number of runs of the cell (11), across new environments (two at least). */
|
|
353
540
|
readonly runs: number;
|
|
354
541
|
readonly environments: number;
|
|
@@ -359,16 +546,22 @@ interface Cell {
|
|
|
359
546
|
*/
|
|
360
547
|
readonly concurrency?: number;
|
|
361
548
|
}
|
|
549
|
+
/** A hop place is a hop of a topology, with the side that the rules of a fault face. */
|
|
550
|
+
interface HopPlace {
|
|
551
|
+
readonly hop: string;
|
|
552
|
+
readonly toward: "client" | "target";
|
|
553
|
+
}
|
|
362
554
|
/**
|
|
363
555
|
* A fault place is the namespace that gets the rules of a fault. "target" and "client" are the two
|
|
364
556
|
* ends. A hop place is a hop, with the side that the rules face. That side is the next hop toward
|
|
365
557
|
* the client, or the next hop toward the target. The rules of a proxy act on its sockets. The
|
|
366
558
|
* rules of a router act on what it forwards, by its device toward that side: the FORWARD chain.
|
|
559
|
+
*
|
|
560
|
+
* A group place is a part of a group, by its role.
|
|
367
561
|
*/
|
|
368
|
-
type FaultPlace = "target" | "client" |
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
};
|
|
562
|
+
type FaultPlace = "target" | "client" | HopPlace | GroupPlace;
|
|
563
|
+
/** This function tells if a fault place is a hop of a topology. */
|
|
564
|
+
export declare const isHopPlace: (place: FaultPlace | undefined) => place is HopPlace;
|
|
372
565
|
/** 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. */
|
|
373
566
|
interface MiddleboxEvent {
|
|
374
567
|
readonly ev: string;
|
|
@@ -416,6 +609,42 @@ interface Run {
|
|
|
416
609
|
readonly topology?: RunTopology;
|
|
417
610
|
/** These are the lines of the routers of a topology from the start to the end of the run. */
|
|
418
611
|
readonly middlebox?: readonly MiddleboxEvent[];
|
|
612
|
+
/** This record is the group of a group cell: its parts, and what it did in the run. */
|
|
613
|
+
readonly group?: RunGroup;
|
|
614
|
+
/** These are the lines of a target that writes them (`Target.lines`), from the start to the end of the run. */
|
|
615
|
+
readonly server?: readonly ProbeEvent[];
|
|
616
|
+
}
|
|
617
|
+
/** A Sentinel event is one line of the observer of a group: an event that a Sentinel published, on the clock of the VM. */
|
|
618
|
+
interface SentinelEvent {
|
|
619
|
+
readonly ev: string;
|
|
620
|
+
readonly t: number;
|
|
621
|
+
/** This text is the address and port of the Sentinel. */
|
|
622
|
+
readonly sentinel?: string;
|
|
623
|
+
/** This name is the event, for example `+switch-master`. */
|
|
624
|
+
readonly event?: string;
|
|
625
|
+
/** This text is the detail of the event, as the Sentinel wrote it. */
|
|
626
|
+
readonly detail?: string;
|
|
627
|
+
readonly [field: string]: unknown;
|
|
628
|
+
}
|
|
629
|
+
/** A part is one member or Sentinel of a group, as a run found it: its address and its network namespace. */
|
|
630
|
+
interface RunPart {
|
|
631
|
+
readonly ip: string;
|
|
632
|
+
readonly netns: number;
|
|
633
|
+
}
|
|
634
|
+
/** A run group is the group of a run: its parts, the primary before and after, the timeline, and the writes that it kept. */
|
|
635
|
+
interface RunGroup {
|
|
636
|
+
readonly members: Readonly<Record<string, RunPart>>;
|
|
637
|
+
readonly sentinels: Readonly<Record<string, RunPart>>;
|
|
638
|
+
/** This name is the member that was the primary at the start of the run. */
|
|
639
|
+
readonly primary: string;
|
|
640
|
+
/** This name is the part that got the fault, or null for a fault on the whole group. */
|
|
641
|
+
readonly at: string | null;
|
|
642
|
+
/** These are the lines of the observer of the Sentinels from the start to the end of the run. */
|
|
643
|
+
readonly timeline: readonly SentinelEvent[];
|
|
644
|
+
/** This name is the member that was the primary when the group converged after the run, or null when it did not converge. */
|
|
645
|
+
readonly after: string | null;
|
|
646
|
+
/** These are the sequence numbers that the group holds after the run, when it converged, or null. */
|
|
647
|
+
readonly holds: readonly number[] | null;
|
|
419
648
|
}
|
|
420
649
|
/**
|
|
421
650
|
* A run topology tells where each socket of a run is, in a topology:
|
|
@@ -433,6 +662,91 @@ interface RunTopology {
|
|
|
433
662
|
}>>;
|
|
434
663
|
}
|
|
435
664
|
//#endregion
|
|
665
|
+
//#region src/timeline.d.ts
|
|
666
|
+
/**
|
|
667
|
+
* This module measures a run of a group cell. It gives the first write that a primary accepted
|
|
668
|
+
* after the fault, and the timeline of the group as its Sentinels announced it. It also gives what
|
|
669
|
+
* became of each write.
|
|
670
|
+
*/
|
|
671
|
+
/** These are the stages of a timeline, in their sequence after a fault. */
|
|
672
|
+
export declare const STAGES: readonly Stage[];
|
|
673
|
+
/** An error on the way is one kind of error that the client met after the fault. It has its first time from the fault, and its count. */
|
|
674
|
+
interface ErrorOnTheWay {
|
|
675
|
+
readonly name: string;
|
|
676
|
+
readonly first: Quantity;
|
|
677
|
+
readonly count: number;
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* A writes record tells what became of the writes of a run, by their sequence numbers:
|
|
681
|
+
* - `old` counts the writes that the primary of the start of the run accepted after the fault.
|
|
682
|
+
* - `lost` are the writes that a primary accepted and the group did not keep. They are the cost
|
|
683
|
+
* of a split brain. It is null when the group did not converge after the run.
|
|
684
|
+
* - `unknown` are the writes that the client sent and did not see accepted: an error, or no answer.
|
|
685
|
+
* `held` tells if the group kept each one, or null when it did not converge.
|
|
686
|
+
*/
|
|
687
|
+
interface Writes {
|
|
688
|
+
readonly sent: number;
|
|
689
|
+
readonly acked: number;
|
|
690
|
+
readonly old: number;
|
|
691
|
+
readonly lost: readonly number[] | null;
|
|
692
|
+
readonly unknown: ReadonlyArray<{
|
|
693
|
+
readonly n: number;
|
|
694
|
+
readonly held: boolean | null;
|
|
695
|
+
}>;
|
|
696
|
+
}
|
|
697
|
+
/** A group measurement is what one run of a group cell measured, beside its time. */
|
|
698
|
+
interface GroupMeasured {
|
|
699
|
+
/** These are the member that was the primary at the start, and the member of the first accepted write after the fault. */
|
|
700
|
+
readonly from: string;
|
|
701
|
+
readonly to: string | null;
|
|
702
|
+
/** These are the times of each stage from the fault: the first announcement by any Sentinel. A stage that no Sentinel announced is absent. */
|
|
703
|
+
readonly stages: Partial<Record<Stage, Quantity>>;
|
|
704
|
+
readonly writes: Writes;
|
|
705
|
+
readonly errors: readonly ErrorOnTheWay[];
|
|
706
|
+
/** These are the delays of the stamps of the observer after the writes of the Sentinels, for a calibration. */
|
|
707
|
+
readonly lags?: readonly Quantity[];
|
|
708
|
+
}
|
|
709
|
+
/** This function gives the time of each stage of a timeline from an instant: the first announcement of each, after the instant. */
|
|
710
|
+
export declare const stagesOf: (timeline: readonly SentinelEvent[], from: number) => Partial<Record<Stage, Quantity>>;
|
|
711
|
+
/** This function gives what became of each write of a run, from the lines of the client and the keys that the group kept. */
|
|
712
|
+
export declare const writesOf: (run: Run, after: number, primary: string) => Writes;
|
|
713
|
+
/** This function gives the errors that the client met after an instant: each kind, its first time, and its count. */
|
|
714
|
+
export declare const errorsOf: (events: readonly ProbeEvent[], after: number) => ErrorOnTheWay[];
|
|
715
|
+
/**
|
|
716
|
+
* This function gives the delay of each stamp of the observer after the write of its Sentinel that
|
|
717
|
+
* the observer read. That write is the latest write of the Sentinel's socket toward the observer,
|
|
718
|
+
* at the stamp or before it. The prober records each write (`tx`) on the clock of the stamps.
|
|
719
|
+
*/
|
|
720
|
+
export declare const lagsOf: (run: Run, kernel: readonly KernelRecord[]) => Quantity[];
|
|
721
|
+
/** This type is the measurement of observe.ts, which a group run fills. */
|
|
722
|
+
interface GroupReading {
|
|
723
|
+
readonly outcome: {
|
|
724
|
+
readonly kind: "answered";
|
|
725
|
+
} | {
|
|
726
|
+
readonly kind: "silent";
|
|
727
|
+
};
|
|
728
|
+
readonly elapsed: Quantity | null;
|
|
729
|
+
readonly socket: Quantity | null;
|
|
730
|
+
readonly noticed: Quantity | null;
|
|
731
|
+
readonly void: string | null;
|
|
732
|
+
readonly finding: string | null;
|
|
733
|
+
readonly group: GroupMeasured;
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* This function reads one run of a group cell.
|
|
737
|
+
* - The reference is the start of the commit of the fault, as the injector stamped it. For a
|
|
738
|
+
* stall, it is the first write into the fault, as for the stall of a direct pair.
|
|
739
|
+
* - The outcome is the first write that a primary accepted after the fault. The prediction says
|
|
740
|
+
* which primary: a new one, or the same one after the lift.
|
|
741
|
+
* - Its time is the last segment with data that the client's socket to that primary received
|
|
742
|
+
* before the client saw the acceptance. The stamp of the client is the fallback.
|
|
743
|
+
* - A run is void when the prober lost records, or when the client did not become ready. It is
|
|
744
|
+
* also void when a Sentinel entered its TILT mode, or when the election split its votes. A band
|
|
745
|
+
* from the fault whose commit took longer than δ_abs is void too. So is a band whose hold lifted
|
|
746
|
+
* more than δ_abs late.
|
|
747
|
+
*/
|
|
748
|
+
export declare const measureGroup: (cell: Cell, run: Run) => GroupReading;
|
|
749
|
+
//#endregion
|
|
436
750
|
//#region src/observe.d.ts
|
|
437
751
|
/**
|
|
438
752
|
* An outcome tells how the wait of a run ended. The socket failed with an errno, or it read the
|
|
@@ -447,7 +761,21 @@ type Outcome = {
|
|
|
447
761
|
readonly kind: "silent";
|
|
448
762
|
} | {
|
|
449
763
|
readonly kind: "answered";
|
|
764
|
+
} | {
|
|
765
|
+
readonly kind: "closed";
|
|
450
766
|
};
|
|
767
|
+
/**
|
|
768
|
+
* A request reading is what the second request of an HTTP client met, from the lines of the
|
|
769
|
+
* client. It holds the connection of its first try, a new try, and its outcome. `gap` is the time
|
|
770
|
+
* from the end of the first reply to the send of the second request.
|
|
771
|
+
*/
|
|
772
|
+
interface RequestReading {
|
|
773
|
+
readonly connection: "reused" | "new";
|
|
774
|
+
readonly retried: boolean;
|
|
775
|
+
readonly error: string | null;
|
|
776
|
+
readonly pending: boolean;
|
|
777
|
+
readonly gap: Quantity | null;
|
|
778
|
+
}
|
|
451
779
|
/** A measurement is what one run measured, against the prediction of its cell. */
|
|
452
780
|
interface Measured {
|
|
453
781
|
readonly environment: number;
|
|
@@ -494,6 +822,10 @@ interface Measured {
|
|
|
494
822
|
readonly reordering?: Reordering;
|
|
495
823
|
/** These are the times of the proxy of a calibration cell, one for each request and its reply. */
|
|
496
824
|
readonly crossings?: Crossings;
|
|
825
|
+
/** This record is what a run of a group cell measured: the stages of its timeline, and what became of each write. */
|
|
826
|
+
readonly group?: GroupMeasured;
|
|
827
|
+
/** This record is what the second request of an HTTP client met, for a cell whose prediction says it. */
|
|
828
|
+
readonly request?: RequestReading | null;
|
|
497
829
|
/** This text is the reason that the run cannot count, or null. A void run is not a pass and not a finding. */
|
|
498
830
|
readonly void: string | null;
|
|
499
831
|
/** This text tells what in the run disagrees with the prediction, other than its timing, or null. */
|
|
@@ -566,10 +898,28 @@ export declare const crossingsOf: (run: Run, hop: string, toClient: SocketPlace
|
|
|
566
898
|
* it, and before the first keepalive probe. A live peer answers that probe, and the answer
|
|
567
899
|
* starts the idle time again. A run where the fault was late is void. A run whose records the
|
|
568
900
|
* prober lost is also void.
|
|
901
|
+
* - For an HTTP client, it also reads what the second request met (`requestOf`). An outcome other
|
|
902
|
+
* than the one that the prediction gives is a finding.
|
|
569
903
|
*/
|
|
570
904
|
export declare const measure: (cell: Cell, run: Run) => Measured;
|
|
905
|
+
/**
|
|
906
|
+
* This function reads the second request of an HTTP client from its lines. Its first try is its
|
|
907
|
+
* first `request` line, and each `retry` line is a new try. Its end is its `error` line, or its
|
|
908
|
+
* `replied` line. A request with neither is pending. It gives null when the client wrote no try.
|
|
909
|
+
*
|
|
910
|
+
* A new try that gets no connection writes no `retry` line. Its dial writes a `dial-error` line.
|
|
911
|
+
* Thus a `dial-error` line after the first try and before the end is also a new try.
|
|
912
|
+
*/
|
|
913
|
+
export declare const requestOf: (events: readonly ProbeEvent[]) => RequestReading | null;
|
|
571
914
|
//#endregion
|
|
572
915
|
//#region src/verdict.d.ts
|
|
916
|
+
/** This function gives the words of the outcome of a second request: its connection, a retry, and its end. */
|
|
917
|
+
export declare const requestWords: (outcome: {
|
|
918
|
+
readonly connection: "reused" | "new";
|
|
919
|
+
readonly retried: boolean;
|
|
920
|
+
readonly error: string | null;
|
|
921
|
+
readonly pending?: boolean | undefined;
|
|
922
|
+
}) => string;
|
|
573
923
|
/**
|
|
574
924
|
* This amount is the noise of the pipeline itself, δ_abs, as the calibration measured it. It is
|
|
575
925
|
* the 99.9th percentile of the whole latency of a reset, at the concurrency cap or less. Its
|
|
@@ -623,8 +973,65 @@ interface Verdict {
|
|
|
623
973
|
readonly up: Spread | null;
|
|
624
974
|
readonly down: Spread | null;
|
|
625
975
|
};
|
|
976
|
+
/** This record is what the group of a group cell did over the counted runs: its stages, and its writes. */
|
|
977
|
+
readonly group?: GroupVerdict;
|
|
978
|
+
/**
|
|
979
|
+
* These are the outcomes of the second request of an HTTP client over the counted runs, each
|
|
980
|
+
* with its count: for example "reused, a retry, a reply". An outcome other than the predicted
|
|
981
|
+
* one is a finding of its run.
|
|
982
|
+
*/
|
|
983
|
+
readonly requests?: Readonly<Record<string, number>>;
|
|
626
984
|
readonly why: string;
|
|
627
985
|
}
|
|
986
|
+
/**
|
|
987
|
+
* A stage verdict is the test of one stage of the timeline of a group against its band. The band
|
|
988
|
+
* is [T_lo − δ_abs, T_hi + the error of the stamps + δ_abs]. A run that did not announce the stage
|
|
989
|
+
* is outside too.
|
|
990
|
+
*/
|
|
991
|
+
interface StageVerdict {
|
|
992
|
+
readonly stage: Stage;
|
|
993
|
+
readonly band: Interval;
|
|
994
|
+
readonly median: Quantity | null;
|
|
995
|
+
readonly outside: ReadonlyArray<{
|
|
996
|
+
readonly run: string;
|
|
997
|
+
readonly why: string;
|
|
998
|
+
}>;
|
|
999
|
+
readonly decision: "holds" | "fails";
|
|
1000
|
+
}
|
|
1001
|
+
/**
|
|
1002
|
+
* A group verdict sums what the group of a group cell did in its counted runs:
|
|
1003
|
+
* - `stages` tests each stage that the prediction gives a band.
|
|
1004
|
+
* - `medians` is the median of each stage that a run announced, from the fault.
|
|
1005
|
+
* - `lost` counts the writes that a primary accepted and the group did not keep, in each run.
|
|
1006
|
+
* - `old` counts the writes that the old primary accepted after the fault, in each run.
|
|
1007
|
+
* - `unknown` counts the writes whose outcome the client did not see, and how many the group kept.
|
|
1008
|
+
* - `errors` are the errors on the way: the runs that met each, and the median of its first time.
|
|
1009
|
+
* - `lags` is the spread of the delays of the stamps, for a calibration.
|
|
1010
|
+
*/
|
|
1011
|
+
interface GroupVerdict {
|
|
1012
|
+
readonly stages: readonly StageVerdict[];
|
|
1013
|
+
readonly medians: Partial<Record<Stage, Quantity>>;
|
|
1014
|
+
readonly lost: {
|
|
1015
|
+
readonly runs: number;
|
|
1016
|
+
readonly total: number;
|
|
1017
|
+
readonly median: number | null;
|
|
1018
|
+
readonly max: number | null;
|
|
1019
|
+
};
|
|
1020
|
+
readonly old: {
|
|
1021
|
+
readonly median: number | null;
|
|
1022
|
+
readonly max: number | null;
|
|
1023
|
+
};
|
|
1024
|
+
readonly unknown: {
|
|
1025
|
+
readonly total: number;
|
|
1026
|
+
readonly held: number;
|
|
1027
|
+
};
|
|
1028
|
+
readonly errors: ReadonlyArray<{
|
|
1029
|
+
readonly name: string;
|
|
1030
|
+
readonly runs: number;
|
|
1031
|
+
readonly first: Quantity;
|
|
1032
|
+
}>;
|
|
1033
|
+
readonly lags?: Spread | null;
|
|
1034
|
+
}
|
|
628
1035
|
/** This function gives the value at quantile p of sorted values, by nearest rank: x_(⌈p·n⌉). */
|
|
629
1036
|
export declare const quantileOf: (sorted: readonly number[], p: number) => number;
|
|
630
1037
|
/** This function gives the spread of a set of times, or null for none. */
|
|
@@ -648,6 +1055,8 @@ export declare const medianInterval: (sorted: readonly number[]) => [number, num
|
|
|
648
1055
|
* which does not exist at this time.
|
|
649
1056
|
*/
|
|
650
1057
|
export declare const verdictOf: (prediction: Prediction, runs: readonly Measured[]) => Verdict;
|
|
1058
|
+
/** This function sums what the group of a group cell did in its counted runs, and tests each stage that has a band. */
|
|
1059
|
+
export declare const groupVerdictOf: (prediction: Prediction, counted: readonly Measured[]) => GroupVerdict;
|
|
651
1060
|
//#endregion
|
|
652
1061
|
//#region src/lab.d.ts
|
|
653
1062
|
/** This function gives the image of the harness. */
|
|
@@ -656,6 +1065,10 @@ export declare const harnessImage: () => Promise<string>;
|
|
|
656
1065
|
export declare const nodeClientImage: () => Promise<string>;
|
|
657
1066
|
/** This function gives the image of the router. */
|
|
658
1067
|
export declare const routerImage: () => Promise<string>;
|
|
1068
|
+
/** This function gives the image of the Go HTTP client. */
|
|
1069
|
+
export declare const goHttpImage: () => Promise<string>;
|
|
1070
|
+
/** This function gives the image of the Node HTTP clients. */
|
|
1071
|
+
export declare const nodeHttpImage: () => Promise<string>;
|
|
659
1072
|
/**
|
|
660
1073
|
* This time is the interval of the listing of a router, when its hop does not set one. A listing
|
|
661
1074
|
* evicts each expired flow that it walks past, and the DESTROY event of that flow follows.
|
|
@@ -717,6 +1130,10 @@ interface Manifest {
|
|
|
717
1130
|
readonly settings: Readonly<Record<string, string>>;
|
|
718
1131
|
/** These are the sysctls of its namespace, as read back after the harness set them. */
|
|
719
1132
|
readonly sysctls: Readonly<Record<string, string>>;
|
|
1133
|
+
/** These are the files that went into the target, by their path, each with the sha256 of its content. */
|
|
1134
|
+
readonly files?: Readonly<Record<string, string>>;
|
|
1135
|
+
/** This line is the first line of a target that writes them: a server that tells its settings as it reads them. */
|
|
1136
|
+
readonly first?: ProbeEvent;
|
|
720
1137
|
};
|
|
721
1138
|
readonly harness: {
|
|
722
1139
|
readonly image: string;
|
|
@@ -738,6 +1155,24 @@ interface Manifest {
|
|
|
738
1155
|
readonly sysctls: Readonly<Record<string, string>>;
|
|
739
1156
|
/** These are the hops of a topology, in sequence from the client. */
|
|
740
1157
|
readonly hops?: readonly ManifestHop[];
|
|
1158
|
+
/** These are the parts of a group, with their settings as each part read them back. */
|
|
1159
|
+
readonly group?: {
|
|
1160
|
+
readonly members: ReadonlyArray<{
|
|
1161
|
+
readonly name: string;
|
|
1162
|
+
readonly ip: string;
|
|
1163
|
+
readonly id: string;
|
|
1164
|
+
readonly settings: Readonly<Record<string, string>>;
|
|
1165
|
+
}>;
|
|
1166
|
+
readonly sentinels: ReadonlyArray<{
|
|
1167
|
+
readonly name: string;
|
|
1168
|
+
readonly ip: string;
|
|
1169
|
+
readonly id: string;
|
|
1170
|
+
readonly settings: Readonly<Record<string, string>>;
|
|
1171
|
+
}>;
|
|
1172
|
+
readonly observer: {
|
|
1173
|
+
readonly image: string;
|
|
1174
|
+
};
|
|
1175
|
+
};
|
|
741
1176
|
}
|
|
742
1177
|
/** These are the JSON lines of a program, as they arrive. */
|
|
743
1178
|
interface Lines<T extends {
|
|
@@ -790,6 +1225,8 @@ interface Lab {
|
|
|
790
1225
|
readonly topology: RunTopology | null;
|
|
791
1226
|
/** These are the lines of the routers of a topology, in sequence, each with the name of its hop. A direct pair has none. */
|
|
792
1227
|
readonly middlebox: readonly MiddleboxEvent[];
|
|
1228
|
+
/** These are the lines of a target that writes them (`Target.lines`), in sequence. Another target has none. */
|
|
1229
|
+
readonly server: readonly ProbeEvent[];
|
|
793
1230
|
/** This method adds a toxic to the Toxiproxy hop of a topology, or removes it with null. The stamps of the injector bracket it. */
|
|
794
1231
|
toxic(toxic: Toxic | null): Promise<{
|
|
795
1232
|
t0: number;
|
|
@@ -919,6 +1356,141 @@ export declare const deviceOf: (route: string) => string;
|
|
|
919
1356
|
*/
|
|
920
1357
|
export declare const openLab: (target: Target, kind?: Client | ClientImage, topology?: Topology) => Promise<Lab>;
|
|
921
1358
|
//#endregion
|
|
1359
|
+
//#region src/group.d.ts
|
|
1360
|
+
/**
|
|
1361
|
+
* This module is the lab of a replicated group: a primary and its replicas, and the Sentinels
|
|
1362
|
+
* that decide which member is the primary. It opens one environment for a group cell, and it does
|
|
1363
|
+
* the runs of the cell in it. Each member and each Sentinel is a container from the stock image of
|
|
1364
|
+
* the group, in its own network namespace. An injector sidecar shares its network and process
|
|
1365
|
+
* namespaces. The client of each run is ioredis in Sentinel mode. An observer subscribes to the
|
|
1366
|
+
* events of each Sentinel, and the prober watches the namespace of the client.
|
|
1367
|
+
*/
|
|
1368
|
+
/** A stamp is the time of the injector around one commit, on CLOCK_MONOTONIC in nanoseconds. */
|
|
1369
|
+
interface Stamp {
|
|
1370
|
+
readonly t0: number;
|
|
1371
|
+
readonly t1: number;
|
|
1372
|
+
}
|
|
1373
|
+
/** A group network fault is a black hole between a part and its peers, or a reset of each segment from them. */
|
|
1374
|
+
type GroupNetworkFault = "blackhole" | "rst";
|
|
1375
|
+
/** A group client is the client container of one run of a group cell. */
|
|
1376
|
+
interface GroupClient {
|
|
1377
|
+
readonly events: readonly ProbeEvent[];
|
|
1378
|
+
until(kinds: readonly string[], within: number): Promise<ProbeEvent>;
|
|
1379
|
+
stop(): Promise<void>;
|
|
1380
|
+
}
|
|
1381
|
+
/** A group lab is one environment of a group cell. */
|
|
1382
|
+
interface GroupLab {
|
|
1383
|
+
readonly group: Group;
|
|
1384
|
+
readonly clientIp: string;
|
|
1385
|
+
readonly observerIp: string;
|
|
1386
|
+
readonly members: Readonly<Record<string, RunPart>>;
|
|
1387
|
+
readonly sentinels: Readonly<Record<string, RunPart>>;
|
|
1388
|
+
/** These are the namespaces that the prober watches: the client, and the Sentinels for a calibration. */
|
|
1389
|
+
readonly netns: {
|
|
1390
|
+
readonly client: number;
|
|
1391
|
+
readonly watched: readonly number[];
|
|
1392
|
+
};
|
|
1393
|
+
/** These are all the records that the prober wrote, in sequence. */
|
|
1394
|
+
readonly kernel: readonly KernelRecord[];
|
|
1395
|
+
/** These are all the lines of the observer of the Sentinels, in sequence. */
|
|
1396
|
+
readonly timeline: readonly SentinelEvent[];
|
|
1397
|
+
/** This method sets the sysctls of the client namespace through its privileged sidecar, and reads them back. */
|
|
1398
|
+
sysctl(values: Readonly<Record<string, string>>): Promise<Record<string, string>>;
|
|
1399
|
+
/** This method waits until the group is whole and calm, and gives the name of its primary. */
|
|
1400
|
+
converge(within?: number): Promise<string>;
|
|
1401
|
+
/** This method removes each key from the group, and waits until each replica has the removal. */
|
|
1402
|
+
flush(primary: string): Promise<void>;
|
|
1403
|
+
/** This method makes each Sentinel forget the state of the group (`SENTINEL RESET`): an aborted failover then holds off no later failover. */
|
|
1404
|
+
reset(): Promise<void>;
|
|
1405
|
+
/** This method gives the sequence numbers that the group holds, from its primary. */
|
|
1406
|
+
holds(primary: string): Promise<number[]>;
|
|
1407
|
+
/** This method gives the part that has a role in the group, when `primary` is the primary. */
|
|
1408
|
+
partOf(role: GroupRole, primary: string): string;
|
|
1409
|
+
/** This method starts the client of a run, with the arguments of `client-sentinel.mjs`. */
|
|
1410
|
+
client(args: readonly string[]): Promise<GroupClient>;
|
|
1411
|
+
/** This method applies a network fault between a part and some of its peers, at once or at an instant of the VM. */
|
|
1412
|
+
fault(kind: GroupNetworkFault, part: string, cuts: NonNullable<GroupPlace["cuts"]>, at?: number): Promise<Stamp>;
|
|
1413
|
+
/** This method removes a network fault, at once or at an instant of the VM. */
|
|
1414
|
+
lift(kind: GroupNetworkFault, part: string, cuts: NonNullable<GroupPlace["cuts"]>, at?: number): Promise<Stamp>;
|
|
1415
|
+
/** This method sends a signal to the server process of a part, at once or at an instant of the VM. */
|
|
1416
|
+
signal(part: string, signal: "KILL" | "STOP" | "CONT", at?: number): Promise<Stamp>;
|
|
1417
|
+
/** This method starts the server of a member again, after a fin. */
|
|
1418
|
+
restart(member: string): Promise<void>;
|
|
1419
|
+
/** This method asks the first Sentinel for a failover of the group. */
|
|
1420
|
+
failover(coordinated: boolean): Promise<Stamp>;
|
|
1421
|
+
/** This method removes the TCP metrics of the client namespace: each run starts from a kernel that keeps nothing. */
|
|
1422
|
+
forget(): Promise<void>;
|
|
1423
|
+
/** This method waits for the next clock line of the prober, which gives the count of lost records. */
|
|
1424
|
+
settle(): Promise<number | null>;
|
|
1425
|
+
manifest(sysctls: Readonly<Record<string, string>>): Promise<Manifest>;
|
|
1426
|
+
close(): Promise<void>;
|
|
1427
|
+
}
|
|
1428
|
+
/** This function gives the configuration file of a member: its port, its settings, and the primary that a replica follows. */
|
|
1429
|
+
export declare const memberConfig: (group: Group, primary: string | null) => string;
|
|
1430
|
+
/** This function gives the configuration file of a Sentinel: its port, the group that it monitors, and the settings of the group. */
|
|
1431
|
+
export declare const sentinelConfig: (group: Group, primary: string) => string;
|
|
1432
|
+
/**
|
|
1433
|
+
* This function gives the peers that a fault on a part cuts it from, by their addresses. `all` is
|
|
1434
|
+
* each other part and the client, `group` is the other parts, and `clients` is the client. The
|
|
1435
|
+
* observer is not a peer, thus the timeline of the group stays whole.
|
|
1436
|
+
*/
|
|
1437
|
+
export declare const peersOf: (parts: {
|
|
1438
|
+
readonly members: Readonly<Record<string, RunPart>>;
|
|
1439
|
+
readonly sentinels: Readonly<Record<string, RunPart>>;
|
|
1440
|
+
}, client: string, part: string, cuts: NonNullable<GroupPlace["cuts"]>) => string[];
|
|
1441
|
+
/** This function reads the flat reply of a command line client into its fields: name, value, name, value. */
|
|
1442
|
+
export declare const fieldsOf: (text: string) => Array<Record<string, string>>;
|
|
1443
|
+
/** This function reads the INFO of a server into its fields. */
|
|
1444
|
+
export declare const infoOf: (text: string) => Record<string, string>;
|
|
1445
|
+
/**
|
|
1446
|
+
* A view of the group is what its parts tell at one time. `healthy` tells if each Sentinel agrees
|
|
1447
|
+
* on one primary with no flag but `master`, and knows each replica and each other Sentinel. Each
|
|
1448
|
+
* replica must follow that primary with its link up, and the primary must have each replica online,
|
|
1449
|
+
* with no failover in progress.
|
|
1450
|
+
*/
|
|
1451
|
+
interface GroupView {
|
|
1452
|
+
readonly primary: string | null;
|
|
1453
|
+
readonly healthy: boolean;
|
|
1454
|
+
readonly why: string;
|
|
1455
|
+
}
|
|
1456
|
+
/** This function judges the views of the Sentinels and of the members: the primary that they agree on, if the group is healthy. */
|
|
1457
|
+
export declare const viewOf: (group: Group, ips: Readonly<Record<string, string>>, sentinels: ReadonlyArray<{
|
|
1458
|
+
readonly master: Record<string, string>;
|
|
1459
|
+
readonly replicas: ReadonlyArray<Record<string, string>>;
|
|
1460
|
+
}>, members: Readonly<Record<string, Record<string, string>>>) => GroupView;
|
|
1461
|
+
/** This time is the longest that a group takes to converge before a run, or after it. */
|
|
1462
|
+
export declare const CONVERGE_MS = 24e4;
|
|
1463
|
+
/**
|
|
1464
|
+
* This function opens one environment of a group cell:
|
|
1465
|
+
* - one new network, with each member, each Sentinel, the client and the observer on it.
|
|
1466
|
+
* - each member: the stock image, its server as the child of a shell, thus a fin can stop the
|
|
1467
|
+
* server and the container stays up. The first member is the primary, and the others follow it.
|
|
1468
|
+
* - each Sentinel: the stock image, its Sentinel as the child of a shell, which monitors the first member.
|
|
1469
|
+
* - an injector sidecar for each part, in its network and process namespaces.
|
|
1470
|
+
* - a client that holds its own network namespace, with a privileged sidecar for its sysctls.
|
|
1471
|
+
* - the observer of the Sentinels, in a namespace of its own.
|
|
1472
|
+
* - the prober, which watches the namespace of the client, and of each Sentinel for a calibration.
|
|
1473
|
+
*/
|
|
1474
|
+
export declare const openGroupLab: (group: Group, options?: {
|
|
1475
|
+
readonly watchSentinels?: boolean;
|
|
1476
|
+
}) => Promise<GroupLab>;
|
|
1477
|
+
/** This function gives the latest time that a group cell waits for its outcome, in ms from the fault. */
|
|
1478
|
+
export declare const deadlineOf: (cell: Cell) => number;
|
|
1479
|
+
/** This function gives the latest subscription of the observer to each Sentinel, in some lines of the observer. */
|
|
1480
|
+
export declare const subscriptionsOf: (timeline: readonly SentinelEvent[]) => SentinelEvent[];
|
|
1481
|
+
/**
|
|
1482
|
+
* This function does one run of a group cell:
|
|
1483
|
+
* - The group converges, and its keys go. The client connects through the Sentinels, and its
|
|
1484
|
+
* stream of writes gets steady.
|
|
1485
|
+
* - The fault occurs on its part, as the primary of this run makes the roles. A fault with a
|
|
1486
|
+
* hold lifts at its instant in the VM. A stall lifts at its length after the first write into it.
|
|
1487
|
+
* - The run waits for its outcome: the first write that a new primary accepts, or the first one
|
|
1488
|
+
* after the lift on the same primary. Then it continues for a moment.
|
|
1489
|
+
* - Each fault goes, the client stops, and the group converges again. The keys that it then holds
|
|
1490
|
+
* tell which writes it kept.
|
|
1491
|
+
*/
|
|
1492
|
+
export declare const groupOnce: (lab: GroupLab, cell: Cell, environment: number, index: number) => Promise<Run>;
|
|
1493
|
+
//#endregion
|
|
922
1494
|
//#region src/run.d.ts
|
|
923
1495
|
/** A cell result is a cell with its manifests, its runs, their measurements and its verdict. */
|
|
924
1496
|
interface CellResult {
|
|
@@ -944,6 +1516,16 @@ export declare const judge: (cell: Cell, runs: readonly Run[]) => {
|
|
|
944
1516
|
measured: Measured[];
|
|
945
1517
|
verdict: Verdict;
|
|
946
1518
|
};
|
|
1519
|
+
/**
|
|
1520
|
+
* This time is the pause between the client's first reply and the fault. It is more than Linux's
|
|
1521
|
+
* TCP_DELACK_MAX of 200 ms. Thus the delayed ACK of the reply is out before the fault.
|
|
1522
|
+
*/
|
|
1523
|
+
export declare const QUIET_MS = 250;
|
|
1524
|
+
/**
|
|
1525
|
+
* This time is how long an HTTP client waits after its second request, before it exits. The exit
|
|
1526
|
+
* closes its sockets, thus that close comes after the window of the cell.
|
|
1527
|
+
*/
|
|
1528
|
+
export declare const LINGER_MS = 1e3;
|
|
947
1529
|
/** This function divides a count of runs across environments, as equally as possible. */
|
|
948
1530
|
export declare const spread: (runs: number, environments: number) => number[];
|
|
949
1531
|
/**
|
|
@@ -957,5 +1539,5 @@ export declare const spread: (runs: number, environments: number) => number[];
|
|
|
957
1539
|
*/
|
|
958
1540
|
export declare const runCell: (cell: Cell, say?: (line: string) => void) => Promise<CellResult>;
|
|
959
1541
|
//#endregion
|
|
960
|
-
export type { Agent, Cell, CellResult, Client, ClientImage, Crossings, Decision, Fault, FaultPlace, FaultSide, Hop, Interval, KernelRecord, Lab, Manifest, ManifestHop, Measured, MiddleboxEvent, MiddleboxForm, NetworkFault, Observer, Outcome, Prediction, Probe, ProbeEvent, ProxyHop, ProxyTime, Recovers, Reference, Reordering, Replies, RouterHop, RttRange, Run, RunTopology, SocketPlace, Spread, Target, Topology, Toxic, Verdict };
|
|
1542
|
+
export type { Agent, Cell, CellResult, Client, ClientImage, Crossings, Decision, ErrorOnTheWay, Fault, FaultPlace, FaultSide, Group, GroupClient, GroupLab, GroupMeasured, GroupNetworkFault, GroupPlace, GroupPrediction, GroupReading, GroupRole, GroupVerdict, GroupView, Hop, HopPlace, HttpProbe, Interval, KernelRecord, Lab, Manifest, ManifestHop, Measured, MiddleboxEvent, MiddleboxExpectation, MiddleboxForm, NetworkFault, Observer, Outcome, Prediction, Probe, ProbeEvent, ProxyHop, ProxyTime, Recovers, Reference, Reordering, Replies, RequestPrediction, RequestReading, RouterHop, RttRange, Run, RunGroup, RunPart, RunTopology, SentinelEvent, SocketPlace, Spread, Stage, StageBand, StageVerdict, Stamp, Target, Topology, Toxic, Verdict, Writes };
|
|
961
1543
|
//# sourceMappingURL=index.d.ts.map
|