@mark1russell7/harness 0.14.3 → 0.15.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 +21 -5
- package/build/{cell-B3-BSTit.d.ts → cell-biffSiEJ.d.ts} +415 -10
- package/build/{image-BMdV7yWD.js → image-BxVTFZ1o.js} +30 -2
- package/build/image-BxVTFZ1o.js.map +1 -0
- package/build/index.d.ts +509 -5
- package/build/index.js +2208 -245
- package/build/index.js.map +1 -1
- package/build/schema.d.ts +5 -2
- package/build/schema.js +7 -3
- package/build/schema.js.map +1 -1
- package/image/Dockerfile +3 -3
- package/image/amqp/client-cluster.mjs +68 -31
- package/image/hikari/ClientHikari.java +81 -6
- package/image/kafka/AdminKafka.java +152 -0
- package/image/kafka/ClientKafka.java +234 -0
- package/image/kafka/ConsumerKafka.java +359 -0
- package/image/kafka/Dockerfile +23 -0
- package/image/kafka/jars.sha256 +5 -0
- package/image/native/Cargo.toml +1 -1
- package/image/native/src/bin/client.rs +164 -28
- package/image/native/src/bin/ctfull.rs +633 -0
- package/image/native/src/bin/inject.rs +16 -0
- package/image/native/src/bin/load.rs +481 -0
- package/image/native/src/bin/ports.rs +367 -0
- package/image/native/src/bin/queue.rs +542 -0
- package/image/native/src/lib.rs +51 -0
- package/image/node/client-sentinel.mjs +28 -12
- package/image/pg/client-pg.mjs +31 -4
- package/package.json +9 -2
- package/build/image-BMdV7yWD.js.map +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Quantity } from "@mark1russell7/quantity";
|
|
2
|
+
import { Profile, Schedule, ScheduleOptions } from "@mark1russell7/rigor-chaos";
|
|
2
3
|
import { KernelRecord } from "@mark1russell7/prober";
|
|
3
4
|
//#region src/cell.d.ts
|
|
4
5
|
/**
|
|
@@ -331,6 +332,87 @@ interface Cluster {
|
|
|
331
332
|
readonly start: string;
|
|
332
333
|
};
|
|
333
334
|
}
|
|
335
|
+
/**
|
|
336
|
+
* A Kafka group is a group of brokers of Apache Kafka in KRaft mode with one controller, as data.
|
|
337
|
+
* Each node is a container from the same stock image, pinned by digest, in its own network namespace.
|
|
338
|
+
* Each run makes one new topic with one partition, with a replica on each broker. The client is the
|
|
339
|
+
* producer of kafka-clients, and it writes a stream of sequence numbers to that partition.
|
|
340
|
+
* The one controller keeps a Raft election out of each run. A fault on a broker cuts it from the
|
|
341
|
+
* controller too, and no fault acts on the controller.
|
|
342
|
+
*/
|
|
343
|
+
interface Kafka {
|
|
344
|
+
/** This image is the stock image of each node, pinned by digest. */
|
|
345
|
+
readonly image: string;
|
|
346
|
+
/** These are the names of the brokers. A broker's node id is its place in this list, from 1. The first broker is the first leader. */
|
|
347
|
+
readonly brokers: readonly string[];
|
|
348
|
+
/** This name is the name of the controller. Its node id comes after the ids of the brokers. */
|
|
349
|
+
readonly controller: string;
|
|
350
|
+
readonly port: number;
|
|
351
|
+
readonly controllerPort: number;
|
|
352
|
+
/** This text is the id of the cluster: 16 bytes in base64url without padding. */
|
|
353
|
+
readonly clusterId: string;
|
|
354
|
+
/** This text is the value of KAFKA_HEAP_OPTS of each node. */
|
|
355
|
+
readonly heap: string;
|
|
356
|
+
/** These are server properties of each node, by their names in Kafka: for example `broker.session.timeout.ms`. */
|
|
357
|
+
readonly settings: Readonly<Record<string, string>>;
|
|
358
|
+
/** This line tells that a node serves. */
|
|
359
|
+
readonly ready: string;
|
|
360
|
+
/** This count is the setting `min.insync.replicas` of the topic of each run. */
|
|
361
|
+
readonly minInsync: number;
|
|
362
|
+
/** This count is the number of writers of the client, each with one write at a time. */
|
|
363
|
+
readonly writers: number;
|
|
364
|
+
/** This record makes each run a run of two members of a consumer group, with one member stopped. Without it, the client is a producer. */
|
|
365
|
+
readonly pause?: KafkaPause;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* A Kafka pause is one run of two members of a consumer group, on a topic with two partitions. The
|
|
369
|
+
* fault stops the process of the first member while it holds a batch, and the hold of the cell ends
|
|
370
|
+
* that stop. Each setting of a member comes from `Cell.driverOptions`.
|
|
371
|
+
*/
|
|
372
|
+
interface KafkaPause {
|
|
373
|
+
/** This name is the protocol of the group: the broker keeps the session under `consumer`, and the client sets it under `classic`. */
|
|
374
|
+
readonly protocol: "consumer" | "classic";
|
|
375
|
+
/** This time is how long the first member holds each batch before it commits. */
|
|
376
|
+
readonly process: Quantity;
|
|
377
|
+
/** This choice is what the first member does after the stop. It commits at once, or it polls until it has a new epoch and then commits. */
|
|
378
|
+
readonly afterPause: "commit" | "rejoin";
|
|
379
|
+
/** This count is the number of records in each partition before the members start. */
|
|
380
|
+
readonly fill: number;
|
|
381
|
+
/** This time is from the start of the processing of a batch to the stop. */
|
|
382
|
+
readonly stopAfter: Quantity;
|
|
383
|
+
}
|
|
384
|
+
/** A pause band is the band of one time of a paused consumer, from the stop. */
|
|
385
|
+
interface PauseBand {
|
|
386
|
+
readonly low: Quantity;
|
|
387
|
+
readonly high: Quantity;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* A pause prediction is the law of a paused consumer. A null fence tells that the stop is too short.
|
|
391
|
+
* The group then does not fence the member, and the other member does not get its partition.
|
|
392
|
+
*/
|
|
393
|
+
interface PausePrediction {
|
|
394
|
+
readonly fence: PauseBand | null;
|
|
395
|
+
/** This band is the first report of the partition by the other member. Null tells that this cell has no band for it. */
|
|
396
|
+
readonly takeover: PauseBand | null;
|
|
397
|
+
/**
|
|
398
|
+
* This choice is the result of the commit after the stop:
|
|
399
|
+
* - `fails`: a commit before any poll fails with `CommitFailedException`.
|
|
400
|
+
* - `acknowledged`: the commit succeeds, and the epoch of the member does not change.
|
|
401
|
+
* - `rejoin`: the member gets a new epoch, the same commit succeeds, and the committed offset moves back.
|
|
402
|
+
*/
|
|
403
|
+
readonly thaw: "fails" | "acknowledged" | "rejoin";
|
|
404
|
+
/** This time bounds the new epoch of `rejoin`, from the end of the stop. */
|
|
405
|
+
readonly rejoinWithin?: Quantity;
|
|
406
|
+
}
|
|
407
|
+
/** A run pause is what a run of a paused consumer records beyond the lines of the stopped member. */
|
|
408
|
+
interface RunPause {
|
|
409
|
+
/** These are the lines of the other member. */
|
|
410
|
+
readonly other: readonly ProbeEvent[];
|
|
411
|
+
/** These are the log lines of the brokers that tell that a member left this group. */
|
|
412
|
+
readonly fences: readonly string[];
|
|
413
|
+
/** This name is the group of the run. */
|
|
414
|
+
readonly group: string;
|
|
415
|
+
}
|
|
334
416
|
/**
|
|
335
417
|
* A cluster stage is one step of the timeline of a cluster after a fault. A line of the log of a
|
|
336
418
|
* node marks it, or a line of the client. These are the stages:
|
|
@@ -352,10 +434,12 @@ type GroupRole = "primary" | "replica" | "sentinel";
|
|
|
352
434
|
* - `clients`: the clients, but not the group.
|
|
353
435
|
* - `one`: one other member, in both directions.
|
|
354
436
|
* - `one-way`: one other member, for the segments from the part only.
|
|
437
|
+
* - `to-clients`: the clients, for the segments from the part only. Each write of a client reaches
|
|
438
|
+
* the part, and no reply reaches the client.
|
|
355
439
|
*/
|
|
356
440
|
interface GroupPlace {
|
|
357
441
|
readonly role: GroupRole;
|
|
358
|
-
readonly cuts?: "all" | "group" | "clients" | "one" | "one-way";
|
|
442
|
+
readonly cuts?: "all" | "group" | "clients" | "one" | "one-way" | "to-clients";
|
|
359
443
|
}
|
|
360
444
|
/** A toxic is one toxic of Toxiproxy, as its API takes it. Its toxicity is 1. */
|
|
361
445
|
interface Toxic {
|
|
@@ -479,6 +563,9 @@ interface StageBand {
|
|
|
479
563
|
* - `lost` is the band of the count of accepted writes that the group did not keep, in each run. A
|
|
480
564
|
* count outside it is a finding. A measurement-only cell with this band gets its decision from
|
|
481
565
|
* the findings of its runs, thus the law of the count judges the cell.
|
|
566
|
+
* - `duplicates` is the band of the count of extra copies that the group holds, in each run. It
|
|
567
|
+
* judges a cell as `lost` does. Only a list or a log can show a copy, thus a Redis cell needs
|
|
568
|
+
* `op: "rpush"`.
|
|
482
569
|
*/
|
|
483
570
|
interface GroupPrediction {
|
|
484
571
|
readonly lands: "new" | "same";
|
|
@@ -495,6 +582,51 @@ interface GroupPrediction {
|
|
|
495
582
|
readonly low: number;
|
|
496
583
|
readonly high: number;
|
|
497
584
|
};
|
|
585
|
+
readonly duplicates?: {
|
|
586
|
+
readonly low: number;
|
|
587
|
+
readonly high: number;
|
|
588
|
+
};
|
|
589
|
+
/** These are the bands of the commits of a pair (`Cell.pair`), each by its set. A set with no band is a measurement. */
|
|
590
|
+
readonly outcomes?: Outcomes;
|
|
591
|
+
}
|
|
592
|
+
/** A count band is the least and the most of a count, both included. */
|
|
593
|
+
interface CountBand {
|
|
594
|
+
readonly low: number;
|
|
595
|
+
readonly high: number;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* These are the bands of the sets of a pair. A commit with no reply is in one set, by the two final reads:
|
|
599
|
+
* - `kept`: the new primary holds it.
|
|
600
|
+
* - `stranded`: only the old primary holds it, after its crash recovery.
|
|
601
|
+
* - `absent`: no server holds it.
|
|
602
|
+
*/
|
|
603
|
+
interface Outcomes {
|
|
604
|
+
/** This band is the count of the writes with no reply, of each set. */
|
|
605
|
+
readonly unknown?: CountBand;
|
|
606
|
+
readonly kept?: CountBand;
|
|
607
|
+
readonly stranded?: CountBand;
|
|
608
|
+
readonly absent?: CountBand;
|
|
609
|
+
/** This band is the count of the acknowledged writes that the old primary does not hold after its crash recovery. */
|
|
610
|
+
readonly missing?: CountBand;
|
|
611
|
+
/** This band is the count of the WARNING notices that the client reads. */
|
|
612
|
+
readonly warnings?: CountBand;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* A pair is a PostgreSQL primary, the target of a cell, and one standby on its network. The topology
|
|
616
|
+
* of the cell stays in front of the primary. Nothing in the pair fails over by itself: the harness
|
|
617
|
+
* does each step, in the order of `pairOnce`.
|
|
618
|
+
*/
|
|
619
|
+
interface Pair {
|
|
620
|
+
/** This flag names the standby in `synchronous_standby_names`. Without it, the standby is asynchronous. */
|
|
621
|
+
readonly synchronous: boolean;
|
|
622
|
+
/** This count is the writers of the client, each with its own connection of the pool. */
|
|
623
|
+
readonly writers: number;
|
|
624
|
+
/** This time is the pause of a writer after each reply. */
|
|
625
|
+
readonly interval: Quantity;
|
|
626
|
+
/** This place is what the black hole cuts the primary from: the standby, or each peer. */
|
|
627
|
+
readonly cuts: "standby" | "all";
|
|
628
|
+
/** This count is the cancels of the waits of the primary, spread across the hold. */
|
|
629
|
+
readonly cancels?: number;
|
|
498
630
|
}
|
|
499
631
|
/**
|
|
500
632
|
* A middlebox expectation tells what the router of a topology does with the flow in the window of
|
|
@@ -533,6 +665,16 @@ interface LineMatch {
|
|
|
533
665
|
readonly where?: Readonly<Record<string, string | number | boolean>>;
|
|
534
666
|
readonly name?: string;
|
|
535
667
|
}
|
|
668
|
+
/**
|
|
669
|
+
* A line count is an exact count of the lines of the target in one run, for a cell whose law gives a
|
|
670
|
+
* count (SYS-67). A count reads no timer, thus it has no band and no noise. The judge compares it with
|
|
671
|
+
* `count`, and `what` names it in the finding.
|
|
672
|
+
*/
|
|
673
|
+
interface LineCount {
|
|
674
|
+
readonly what: string;
|
|
675
|
+
readonly match: LineMatch;
|
|
676
|
+
readonly count: number;
|
|
677
|
+
}
|
|
536
678
|
/**
|
|
537
679
|
* A driver step is one more band of a driver after the band of its cell. An example is the error
|
|
538
680
|
* of the retry after the interruption. It has its own reference on a socket of the driver, its
|
|
@@ -684,7 +826,213 @@ type Prediction = {
|
|
|
684
826
|
* the client. The end has no band, but each wait has one. A wait outside its band is a finding of its run.
|
|
685
827
|
*/
|
|
686
828
|
readonly reconnects?: Reconnects;
|
|
829
|
+
/**
|
|
830
|
+
* These are the exact counts of the lines of the target in each run. A count that differs is a
|
|
831
|
+
* finding of its run. A measurement-only cell with a reference and counts gets a decision from them.
|
|
832
|
+
*/
|
|
833
|
+
readonly counts?: readonly LineCount[];
|
|
834
|
+
/**
|
|
835
|
+
* This record is the law of an accept queue: its limit, its count, its counters, and what each
|
|
836
|
+
* connection sees. A value outside it is a finding of its run.
|
|
837
|
+
*/
|
|
838
|
+
readonly queue?: QueuePrediction;
|
|
839
|
+
/**
|
|
840
|
+
* This record is the law of a port range: the count of connects, the ports that they use, and
|
|
841
|
+
* when a held port comes back. A value outside it is a finding of its run.
|
|
842
|
+
*/
|
|
843
|
+
readonly ports?: PortsPrediction;
|
|
844
|
+
/**
|
|
845
|
+
* This record is the law of a conntrack table: its flows, a connect that finds no entry, and the
|
|
846
|
+
* return of a slot. A value outside it is a finding of its run.
|
|
847
|
+
*/
|
|
848
|
+
readonly conntrack?: ConntrackPrediction;
|
|
849
|
+
/** This record is the law of a paused consumer (`Kafka.pause`). A run outside it is a finding of its run. */
|
|
850
|
+
readonly pause?: PausePrediction;
|
|
851
|
+
/** These are the limits of an open-loop cell (`Cell.probe.plan`). Without them, its load is a measurement. */
|
|
852
|
+
readonly load?: LoadPrediction;
|
|
687
853
|
};
|
|
854
|
+
/** A queue band is a time from one line of a queue cell to another line, with its two bounds. */
|
|
855
|
+
interface QueueBand {
|
|
856
|
+
readonly low: Quantity;
|
|
857
|
+
readonly high: Quantity;
|
|
858
|
+
}
|
|
859
|
+
/** This prediction tells how one connection of a queue cell ends. */
|
|
860
|
+
interface QueueEnd {
|
|
861
|
+
readonly errno: string;
|
|
862
|
+
/** This name is the line of the connection that the time of the end counts from. */
|
|
863
|
+
readonly from: "dial" | "connected" | "sent";
|
|
864
|
+
readonly within: QueueBand;
|
|
865
|
+
/**
|
|
866
|
+
* This band is the time from the last retransmission of the connection to its end. With an
|
|
867
|
+
* `expiry`, the retransmission before the last comes before the expiry, and the last comes after it.
|
|
868
|
+
*/
|
|
869
|
+
readonly retransmitted?: QueueBand;
|
|
870
|
+
}
|
|
871
|
+
/** This prediction tells what one connection of a queue cell sees, by its name in the client. */
|
|
872
|
+
interface QueueConnection {
|
|
873
|
+
readonly name: string;
|
|
874
|
+
/** This choice says if the connect of the connection succeeds. */
|
|
875
|
+
readonly connects: boolean;
|
|
876
|
+
/** These bands are the waits of the SYN: the first from the dial, each next one from the SYN before it. */
|
|
877
|
+
readonly syns?: readonly QueueBand[];
|
|
878
|
+
/** These bands are the waits of each SYN-ACK sent again: the first from the dial, each next one from the SYN-ACK before it. */
|
|
879
|
+
readonly synAcks?: readonly QueueBand[];
|
|
880
|
+
/** This prediction tells how the connection ends. It is null for a connection that lives to the end of the run. */
|
|
881
|
+
readonly ends: QueueEnd | null;
|
|
882
|
+
/** This count is the segments that the peer has not acknowledged at the end of the run. */
|
|
883
|
+
readonly unacked?: number;
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* This prediction is the law of an accept queue. It reads the lines of the queue client and of the
|
|
887
|
+
* queue target. The counters count from the `opened` line of the run.
|
|
888
|
+
*/
|
|
889
|
+
interface QueuePrediction {
|
|
890
|
+
/** This count is the limit of the queue: `sk_max_ack_backlog`, as TCP_INFO of the listener gives it. */
|
|
891
|
+
readonly max: number;
|
|
892
|
+
/** This count is the most connections that the queue holds at one time. */
|
|
893
|
+
readonly held: number;
|
|
894
|
+
/** This count is the connections that connect, and the kernel of the client tells this. */
|
|
895
|
+
readonly connected: number;
|
|
896
|
+
/** These counts are the bounds of `ListenOverflows`. */
|
|
897
|
+
readonly overflows: {
|
|
898
|
+
readonly low: number;
|
|
899
|
+
readonly high: number;
|
|
900
|
+
};
|
|
901
|
+
/** This count is `EmbryonicRsts`: the handshakes that the target reset. */
|
|
902
|
+
readonly resets: number;
|
|
903
|
+
/** These predictions are the connections with a law of their own. */
|
|
904
|
+
readonly connections: readonly QueueConnection[];
|
|
905
|
+
/** A run where this connection did not take the last place in the queue is void: its burst did not land in its sequence. */
|
|
906
|
+
readonly admitted?: string;
|
|
907
|
+
/** This record tells when the kernel of the target forgets the handshakes: the `TCPTimeouts` of their last firings, from the first dial of the burst. */
|
|
908
|
+
readonly expiry?: {
|
|
909
|
+
readonly timeouts: number;
|
|
910
|
+
readonly within: QueueBand;
|
|
911
|
+
};
|
|
912
|
+
/** This record tells when the count of the queue gets back to `count`, from the first dial of the burst, after an accept. */
|
|
913
|
+
readonly rise?: {
|
|
914
|
+
readonly count: number;
|
|
915
|
+
readonly within: QueueBand;
|
|
916
|
+
};
|
|
917
|
+
/** This count is the connections that the target accepted in the run. */
|
|
918
|
+
readonly drained?: number;
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* This prediction is the law of a port range. It reads the lines of the ports client. In each round
|
|
922
|
+
* the client connects to each destination until a connect fails with EADDRNOTAVAIL.
|
|
923
|
+
*/
|
|
924
|
+
interface PortsPrediction {
|
|
925
|
+
/** This port is the low end of the range. */
|
|
926
|
+
readonly low: number;
|
|
927
|
+
/** This count is the ports of the range. */
|
|
928
|
+
readonly size: number;
|
|
929
|
+
/** This count is the rounds of each run. */
|
|
930
|
+
readonly rounds: number;
|
|
931
|
+
/** This count is the destinations of each round. */
|
|
932
|
+
readonly destinations: number;
|
|
933
|
+
/** These counts are the only connects that one destination can get in one round. */
|
|
934
|
+
readonly counts: readonly number[];
|
|
935
|
+
/** These offsets from the low port are the only ports that the run uses. It uses each of them. */
|
|
936
|
+
readonly seen: readonly number[];
|
|
937
|
+
/** This time is the longest connect that fails. */
|
|
938
|
+
readonly refusedWithin: Quantity;
|
|
939
|
+
/** This record is the band of the share of the rounds that get `count` connects. */
|
|
940
|
+
readonly share?: {
|
|
941
|
+
readonly count: number;
|
|
942
|
+
readonly low: number;
|
|
943
|
+
readonly high: number;
|
|
944
|
+
};
|
|
945
|
+
/** This choice says that the ports of the parity of the low port come first in each round. */
|
|
946
|
+
readonly lowFirst?: boolean;
|
|
947
|
+
/** This band is the time from the `closing` line to each `freed` line: when each held port comes back. */
|
|
948
|
+
readonly freed?: QueueBand;
|
|
949
|
+
/** This count is the segments that the sockets of the client send again. */
|
|
950
|
+
readonly retransmissions?: number;
|
|
951
|
+
}
|
|
952
|
+
/**
|
|
953
|
+
* This prediction is the law of a conntrack table. It reads the lines of the ctfull client. The client
|
|
954
|
+
* holds flows on its loopback until the count of its namespace reads the limit, then it does its plan.
|
|
955
|
+
*/
|
|
956
|
+
interface ConntrackPrediction {
|
|
957
|
+
/** This count is the limit of the table: the flows that the client holds, and the count that it reads then. */
|
|
958
|
+
readonly max: number;
|
|
959
|
+
/** This count is what the namespace of the target reads while the client holds its flows. */
|
|
960
|
+
readonly neighbor?: number;
|
|
961
|
+
/** This record is the law of a connect that finds no entry: its end, and the rise of the two counters of the kernel. */
|
|
962
|
+
readonly refused?: {
|
|
963
|
+
readonly within: QueueBand;
|
|
964
|
+
readonly errno: string;
|
|
965
|
+
readonly drops: number;
|
|
966
|
+
readonly retransFail: number;
|
|
967
|
+
};
|
|
968
|
+
/** This band is the time from the `closing` line to the first fall of the count, and to its zero. */
|
|
969
|
+
readonly drained?: QueueBand;
|
|
970
|
+
/**
|
|
971
|
+
* This record is the law of a scan under pressure. It has the lowest count, the count after the
|
|
972
|
+
* connect, and the times of that connect. With `highest`, the lowest count is a band from `lowest` to
|
|
973
|
+
* `highest`. Then the count after the connect is one more than the lowest count of the run.
|
|
974
|
+
*/
|
|
975
|
+
readonly pressure?: {
|
|
976
|
+
readonly lowest: number;
|
|
977
|
+
readonly highest?: number;
|
|
978
|
+
readonly after: number;
|
|
979
|
+
readonly points: readonly QueueBand[];
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* This setting is one sysctl of the namespace of the host, for the time of an environment. The harness
|
|
984
|
+
* reads the value before it, reads the value that it set, and restores the first value at the end.
|
|
985
|
+
*/
|
|
986
|
+
interface HostSysctl {
|
|
987
|
+
readonly name: string;
|
|
988
|
+
readonly value: string;
|
|
989
|
+
/** The harness does not set the value when this sysctl of the host reads above `atMost`. The cell is then void. */
|
|
990
|
+
readonly guard?: {
|
|
991
|
+
readonly name: string;
|
|
992
|
+
readonly atMost: number;
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
/** A load plan is the schedule of an open-loop client as data: the rate over time, and how the arrivals fall. */
|
|
996
|
+
interface LoadPlan {
|
|
997
|
+
readonly profile: Profile;
|
|
998
|
+
readonly options: ScheduleOptions;
|
|
999
|
+
}
|
|
1000
|
+
/**
|
|
1001
|
+
* A load stream is one connection of the client `load`: its key, its schedule and its requests.
|
|
1002
|
+
* Arrival i sends request i modulo the count of requests. Each stream has its own connection, thus
|
|
1003
|
+
* a slow stream does not delay the arrivals of another stream.
|
|
1004
|
+
*/
|
|
1005
|
+
interface LoadStream {
|
|
1006
|
+
/** This text names the stream in each line of the client (`k`). Two streams of a cell do not have the same key. */
|
|
1007
|
+
readonly key: string;
|
|
1008
|
+
readonly plan: LoadPlan;
|
|
1009
|
+
/** These texts are whole HTTP/1.1 requests, each with its head and its body. */
|
|
1010
|
+
readonly requests: readonly string[];
|
|
1011
|
+
}
|
|
1012
|
+
/** A run stream is the schedule that one stream of the client `load` had in a run. */
|
|
1013
|
+
interface RunStream {
|
|
1014
|
+
readonly key: string;
|
|
1015
|
+
readonly schedule: Schedule;
|
|
1016
|
+
}
|
|
1017
|
+
/** A load band is a limit on one quantile of the latency of an open-loop cell, over the arrivals of its counted runs. */
|
|
1018
|
+
interface LoadBand {
|
|
1019
|
+
/** This number is the quantile, from 0 to 1. */
|
|
1020
|
+
readonly quantile: number;
|
|
1021
|
+
readonly low?: Quantity;
|
|
1022
|
+
readonly high: Quantity;
|
|
1023
|
+
}
|
|
1024
|
+
/** A load prediction tells how close to its schedule a client stays, and where the latency lands. */
|
|
1025
|
+
interface LoadPrediction {
|
|
1026
|
+
/** This time is the largest lag of a send behind its planned time. A later send is a finding of its run. */
|
|
1027
|
+
readonly lag: Quantity;
|
|
1028
|
+
readonly bands: readonly LoadBand[];
|
|
1029
|
+
/**
|
|
1030
|
+
* This share is the limit on the failed arrivals of the counted runs, from 0 to 1. An arrival fails
|
|
1031
|
+
* when the client did not send it, when it has no reply, or when its reply has the status of a
|
|
1032
|
+
* failure. The verdict reads the Wilson interval at 0.95, thus a limit of 0.01 needs 381 arrivals.
|
|
1033
|
+
*/
|
|
1034
|
+
readonly failures?: number;
|
|
1035
|
+
}
|
|
688
1036
|
/** A target is the server that a cell connects to: a stock image. */
|
|
689
1037
|
interface Target {
|
|
690
1038
|
/** This image is a stock image, pinned by digest. */
|
|
@@ -740,7 +1088,7 @@ interface Target {
|
|
|
740
1088
|
* grpc-go and `etcd` is etcd on Alpine: each is a subject of a target (`Target.subject`).
|
|
741
1089
|
* `docker-proxy` is the userland proxy of Docker Engine 29.1.5, the program of a proxy hop.
|
|
742
1090
|
*/
|
|
743
|
-
type Shipped = "harness" | "node" | "go-http" | "node-http" | "mongo" | "pg" | "hikari" | "amqp" | "grpc" | "grpc-go" | "etcd" | "router" | "pgbouncer" | "pgpool" | "docker-proxy";
|
|
1091
|
+
type Shipped = "harness" | "node" | "go-http" | "node-http" | "mongo" | "pg" | "hikari" | "amqp" | "kafka" | "grpc" | "grpc-go" | "etcd" | "router" | "pgbouncer" | "pgpool" | "docker-proxy";
|
|
744
1092
|
/**
|
|
745
1093
|
* An image source tells where an image comes from, as data. The harness resolves each kind to an
|
|
746
1094
|
* image that it can start:
|
|
@@ -800,7 +1148,7 @@ interface Subject {
|
|
|
800
1148
|
* (`http-agent`) and an HTTP/1.1 `Client` of undici (`undici`). The MongoDB driver is `mongodb`, node-postgres is `pg`, and HikariCP over pgjdbc is `hikari`.
|
|
801
1149
|
* The client of amqplib is `amqp`, and the client of grpc-js is `grpc`. The WebSocket client of `@procedures/client` is a program of its subject (`ClientImage`).
|
|
802
1150
|
*/
|
|
803
|
-
type Client = "tcp" | "ioredis" | "go-http" | "http-agent" | "undici" | "mongodb" | "pg" | "hikari" | "amqp" | "grpc";
|
|
1151
|
+
type Client = "tcp" | "ioredis" | "go-http" | "http-agent" | "undici" | "mongodb" | "pg" | "hikari" | "amqp" | "grpc" | "load";
|
|
804
1152
|
/**
|
|
805
1153
|
* A WebSocket probe is the workload and the settings of the WebSocket client of
|
|
806
1154
|
* `@procedures/client`, the `client` program of its subject. The cell gives each setting, thus the client takes
|
|
@@ -868,7 +1216,15 @@ interface ClientImage {
|
|
|
868
1216
|
/** This image is a stock image by its name, pinned by digest, or the source of the image of a subject. */
|
|
869
1217
|
readonly image: string | ImageSource;
|
|
870
1218
|
readonly command: readonly string[];
|
|
1219
|
+
/**
|
|
1220
|
+
* These capabilities are added to the default set of the container of the client. A read of the
|
|
1221
|
+
* statistics of conntrack over netlink needs NET_ADMIN in the namespace of the client.
|
|
1222
|
+
*/
|
|
1223
|
+
readonly capabilities?: readonly ClientCapability[] | undefined;
|
|
871
1224
|
}
|
|
1225
|
+
/** These are the capabilities that a client image can get. */
|
|
1226
|
+
declare const CLIENT_CAPABILITIES: readonly ["NET_ADMIN"];
|
|
1227
|
+
type ClientCapability = (typeof CLIENT_CAPABILITIES)[number];
|
|
872
1228
|
/**
|
|
873
1229
|
* An observer is the side whose detection a cell measures. The client is one observer. The
|
|
874
1230
|
* server is another observer. It is the hold of the target on the connection of the client, at
|
|
@@ -893,8 +1249,13 @@ interface Cell {
|
|
|
893
1249
|
* This mode tells if the client is idle after its first reply, or sends a request into the
|
|
894
1250
|
* fault. In a stream, it sends `count` requests into it, each `interval` after the reply before.
|
|
895
1251
|
* An HTTP client in a `gap` sends its second request a gap after its first reply, by itself.
|
|
1252
|
+
* On a `schedule`, it sends each request at its time in `plan`, and a send does not wait for a reply.
|
|
896
1253
|
*/
|
|
897
|
-
readonly mode: "idle" | "inflight" | "stream" | "gap";
|
|
1254
|
+
readonly mode: "idle" | "inflight" | "stream" | "gap" | "schedule";
|
|
1255
|
+
/** This plan is the schedule of the requests in the mode `schedule`. */
|
|
1256
|
+
readonly plan?: LoadPlan;
|
|
1257
|
+
/** These streams are the plan of the client `load` in the mode `schedule`, in place of `plan`. */
|
|
1258
|
+
readonly streams?: readonly LoadStream[];
|
|
898
1259
|
/** This count is the number of requests of a stream. */
|
|
899
1260
|
readonly count?: number;
|
|
900
1261
|
/** This time is the pause after each reply of a stream, before the next request. */
|
|
@@ -912,19 +1273,26 @@ interface Cell {
|
|
|
912
1273
|
/**
|
|
913
1274
|
* This driver replaces the TCP client of the harness, with its own options. The driver then
|
|
914
1275
|
* ignores `keepalive` and `userTimeout`:
|
|
915
|
-
* - ioredis 6 on Node, whose keepAlive is the keepalive delay of the socket.
|
|
1276
|
+
* - ioredis 6 on Node, whose keepAlive is the keepalive delay of the socket. In a group cell,
|
|
1277
|
+
* its write is `SET w:<n> <n>`, or `RPUSH w <n>` with `op: "rpush"`, thus a list keeps each
|
|
1278
|
+
* copy. `window` is the count of writers, each with one write in flight: 1 at the default.
|
|
916
1279
|
* - the MongoDB driver on Node, against the replica set `set`. Its operation is a write, or
|
|
917
1280
|
* the read of a long document (`read-long`). `Cell.driverOptions` are its options.
|
|
918
1281
|
* - node-postgres on Node, as a `pg.Pool` against one server. Its operation is `query`, or
|
|
919
1282
|
* `SELECT 1`. `Cell.driverOptions` are the options of its pool.
|
|
920
1283
|
* - HikariCP over pgjdbc on Java, as a `HikariDataSource` against one server. Its operation is
|
|
921
|
-
* `query`, or `SELECT 1`. `Cell.driverOptions` are the properties of HikariConfig
|
|
922
|
-
* with the prefix `dataSource.` is a property of pgjdbc
|
|
1284
|
+
* `query`, or `SELECT 1`. `Cell.driverOptions` are the properties of HikariConfig. A name
|
|
1285
|
+
* with the prefix `dataSource.` is a property of pgjdbc, and a name with the prefix `system.`
|
|
1286
|
+
* is a system property of the JVM.
|
|
923
1287
|
*
|
|
924
1288
|
* A pg or hikari driver can send a different text in flight (`inflight`): the second query of
|
|
925
1289
|
* an in-flight run. The first query then makes the pool ready at once, and only the query in
|
|
926
1290
|
* flight is slow, for example `SELECT pg_sleep(20)`.
|
|
927
1291
|
*
|
|
1292
|
+
* A hikari driver can send a burst in place of one query in flight. A burst is `count` queries,
|
|
1293
|
+
* query 2 and the next ones. Each one has its own thread, and it starts `gap` after the one before
|
|
1294
|
+
* it. The client writes a `burst` line at the end of the last one, with its counts.
|
|
1295
|
+
*
|
|
928
1296
|
* A grpc driver is grpc-js on Node, with one channel. Its operation is a unary call of
|
|
929
1297
|
* grpc.health.v1.Health/Check. `Cell.driverOptions` are its channel options (`grpc.*`) and
|
|
930
1298
|
* `deadline_ms`. With `hold`, the call in flight asks the server of the harness to hold its reply
|
|
@@ -933,6 +1301,8 @@ interface Cell {
|
|
|
933
1301
|
readonly driver?: {
|
|
934
1302
|
readonly name: "ioredis";
|
|
935
1303
|
readonly keepAlive: Quantity;
|
|
1304
|
+
readonly op?: "set" | "rpush";
|
|
1305
|
+
readonly window?: number;
|
|
936
1306
|
} | {
|
|
937
1307
|
readonly name: "mongodb";
|
|
938
1308
|
readonly set: string;
|
|
@@ -945,6 +1315,10 @@ interface Cell {
|
|
|
945
1315
|
readonly name: "hikari";
|
|
946
1316
|
readonly query?: string;
|
|
947
1317
|
readonly inflight?: string;
|
|
1318
|
+
readonly burst?: {
|
|
1319
|
+
readonly count: number;
|
|
1320
|
+
readonly gap: Quantity;
|
|
1321
|
+
};
|
|
948
1322
|
} | {
|
|
949
1323
|
readonly name: "amqp";
|
|
950
1324
|
} | {
|
|
@@ -978,6 +1352,14 @@ interface Cell {
|
|
|
978
1352
|
readonly latency?: Quantity;
|
|
979
1353
|
/** These commands run in the target before a client connects, each as argv: for example, a large value to read. */
|
|
980
1354
|
readonly targetSetup?: readonly (readonly string[])[];
|
|
1355
|
+
/** These commands run in the namespaces of the client and the target, each as argv, after the first connection of the environment. */
|
|
1356
|
+
readonly namespaceSetup?: readonly (readonly string[])[];
|
|
1357
|
+
/**
|
|
1358
|
+
* These are sysctls of the host, which a cell needs because only the host can write them. The value
|
|
1359
|
+
* applies to each container of the host, thus a shard runs them on its own runner. A host that does
|
|
1360
|
+
* not have one makes the cell void (rule 8 of the environments).
|
|
1361
|
+
*/
|
|
1362
|
+
readonly hostSysctls?: readonly HostSysctl[];
|
|
981
1363
|
readonly prediction: Prediction;
|
|
982
1364
|
/** This side is the side whose detection the cell measures. Without it, the side is the client. */
|
|
983
1365
|
readonly observer?: Observer;
|
|
@@ -1024,6 +1406,14 @@ interface Cell {
|
|
|
1024
1406
|
* record, and the cluster does not read it.
|
|
1025
1407
|
*/
|
|
1026
1408
|
readonly cluster?: Cluster;
|
|
1409
|
+
/**
|
|
1410
|
+
* This Kafka group replaces the target: brokers of Apache Kafka with one controller. The client is
|
|
1411
|
+
* then the producer of kafka-clients, with the settings of `driverOptions`. `target` stays for the
|
|
1412
|
+
* record, and the group does not read it.
|
|
1413
|
+
*/
|
|
1414
|
+
readonly kafka?: Kafka;
|
|
1415
|
+
/** This pair adds a standby to the target (`Pair`). The client is then node-postgres, in a stream of K writers. */
|
|
1416
|
+
readonly pair?: Pair;
|
|
1027
1417
|
/** This place is the node of the client in a cluster: the node of the leader, or of a follower. Without it, the node of a follower. */
|
|
1028
1418
|
readonly clientAt?: ClusterClientAt;
|
|
1029
1419
|
/**
|
|
@@ -1031,6 +1421,11 @@ interface Cell {
|
|
|
1031
1421
|
* that instant, on the clock of the VM. On a direct pair, a frozen target thaws after it.
|
|
1032
1422
|
*/
|
|
1033
1423
|
readonly hold?: Quantity;
|
|
1424
|
+
/**
|
|
1425
|
+
* This time is how much longer a run of a replica set continues after the lift. A prediction of
|
|
1426
|
+
* no failover after a short hold needs it: the run must outlast the timers of an election.
|
|
1427
|
+
*/
|
|
1428
|
+
readonly watch?: Quantity;
|
|
1034
1429
|
/** This flag makes a planned failover coordinated: `SENTINEL FAILOVER <group> COORDINATED`. */
|
|
1035
1430
|
readonly coordinated?: boolean;
|
|
1036
1431
|
/**
|
|
@@ -1171,8 +1566,16 @@ interface Run {
|
|
|
1171
1566
|
readonly group?: RunGroup;
|
|
1172
1567
|
/** These are the lines of a target that writes them (`Target.lines`), from the start to the end of the run. */
|
|
1173
1568
|
readonly server?: readonly ProbeEvent[];
|
|
1569
|
+
/** This text tells what the environment of the run could not do for its cell. The run is void. */
|
|
1570
|
+
readonly missing?: string;
|
|
1571
|
+
/** This record is the other member and the broker logs of a run of a paused consumer. */
|
|
1572
|
+
readonly pause?: RunPause;
|
|
1174
1573
|
/** This record is the fabric of a cell with `Topology.fabric`. */
|
|
1175
1574
|
readonly fabric?: RunFabric;
|
|
1575
|
+
/** This schedule is the one that the client of an open-loop cell had: each planned time stays with its record. */
|
|
1576
|
+
readonly schedule?: Schedule;
|
|
1577
|
+
/** These schedules are the ones that the streams of the client `load` had. */
|
|
1578
|
+
readonly streams?: readonly RunStream[];
|
|
1176
1579
|
}
|
|
1177
1580
|
/** A run route is one change of a route at a leaf of a fabric, on the monotonic clock. */
|
|
1178
1581
|
interface RunRoute {
|
|
@@ -1228,8 +1631,10 @@ interface RunGroup {
|
|
|
1228
1631
|
readonly timeline: readonly SentinelEvent[];
|
|
1229
1632
|
/** This name is the member that was the primary when the group converged after the run, or null when it did not converge. */
|
|
1230
1633
|
readonly after: string | null;
|
|
1231
|
-
/** These are the sequence numbers that the group holds after the run, when it converged, or null. */
|
|
1634
|
+
/** These are the sequence numbers that the group holds after the run, one entry for each copy, when it converged, or null. */
|
|
1232
1635
|
readonly holds: readonly number[] | null;
|
|
1636
|
+
/** These are the sequence numbers that the old primary of a pair holds after its crash recovery. */
|
|
1637
|
+
readonly oldHolds?: readonly number[];
|
|
1233
1638
|
/** This record tells what a recovery drill did. */
|
|
1234
1639
|
readonly drill?: RunDrill;
|
|
1235
1640
|
}
|
|
@@ -1282,5 +1687,5 @@ interface RunTopology {
|
|
|
1282
1687
|
}>>;
|
|
1283
1688
|
}
|
|
1284
1689
|
//#endregion
|
|
1285
|
-
export {
|
|
1286
|
-
//# sourceMappingURL=cell-
|
|
1690
|
+
export { ProxyHop as $, ImageSource as A, Subject as At, LoadStream as B, Hop as C, RunTopology as Ct, HopWrite as D, ShippedImage as Dt, HopSignal as E, Shipped as Et, LineCount as F, isHopPlace as Ft, Outcomes as G, MiddleboxExpectation as H, LineMatch as I, latestEndOf as It, PausePrediction as J, Pair as K, LoadBand as L, Kafka as M, Topology as Mt, KafkaPause as N, Toxic as Nt, HostSysctl as O, Stage as Ot, KernelRecord as P, WsProbe as Pt, ProbeEvent as Q, LoadPlan as R, GroupRole as S, RunStream as St, HopPlace as T, SentinelStage as Tt, MiddleboxForm as U, MiddleboxEvent as V, Observer as W, PortsPrediction as X, PinnedImage as Y, Prediction as Z, Fault as _, RunFabric as _t, ClientCapability as a, Reconnects as at, GroupPlace as b, RunPause as bt, ClusterClientAt as c, ReplicaSet as ct, CountBand as d, RequestPrediction as dt, ProxyTime as et, Drill as f, RouterHop as ft, FabricManifest as g, RunDrill as gt, Fabric as h, RunBackup as ht, Client as i, QueuePrediction as it, Jitter as j, Target as jt, HttpProbe as k, StageBand as kt, ClusterStage as l, ReplicaSetStage as lt, DriverStep as m, Run as mt, CLIENT_CAPABILITIES as n, QueueConnection as nt, ClientImage as o, Recovers as ot, DriverBand as p, RttRange as pt, PauseBand as q, Cell as r, QueueEnd as rt, Cluster as s, Reference as st, BuildImage as t, QueueBand as tt, ConntrackPrediction as u, Replies as ut, FaultPlace as v, RunGroup as vt, HopEvent as w, SentinelEvent as wt, GroupPrediction as x, RunRoute as xt, Group as y, RunPart as yt, LoadPrediction as z };
|
|
1691
|
+
//# sourceMappingURL=cell-biffSiEJ.d.ts.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { valueIn } from "@mark1russell7/quantity";
|
|
1
2
|
import { createHash } from "node:crypto";
|
|
2
3
|
import { execFile } from "node:child_process";
|
|
3
4
|
import { tmpdir } from "node:os";
|
|
@@ -6,6 +7,22 @@ import { copyFileSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpa
|
|
|
6
7
|
import { createRequire } from "node:module";
|
|
7
8
|
import { fileURLToPath } from "node:url";
|
|
8
9
|
import { isDeepStrictEqual } from "node:util";
|
|
10
|
+
//#region src/cell.ts
|
|
11
|
+
/** These are the capabilities that a client image can get. */
|
|
12
|
+
const CLIENT_CAPABILITIES = ["NET_ADMIN"];
|
|
13
|
+
/** This function tells if a fault place is a hop of a topology. */
|
|
14
|
+
const isHopPlace = (place) => typeof place === "object" && "hop" in place;
|
|
15
|
+
/**
|
|
16
|
+
* This function tells if the request of a client goes before the fault of its cell. That is so for a
|
|
17
|
+
* hop event that comes while the request is in flight (`HopEvent.inFlight`). Then a request after the fault is void.
|
|
18
|
+
*/
|
|
19
|
+
const requestFirst = (cell) => cell.fault === "hop-event" && cell.event?.inFlight === true;
|
|
20
|
+
/**
|
|
21
|
+
* This function gives the latest end of a band in seconds, from the reply of the client. It is
|
|
22
|
+
* the high bound, after the latest reference of the band (`startsBy`).
|
|
23
|
+
*/
|
|
24
|
+
const latestEndOf = (prediction) => valueIn(prediction.high, "s") + (prediction.startsBy === void 0 ? 0 : valueIn(prediction.startsBy, "s"));
|
|
25
|
+
//#endregion
|
|
9
26
|
//#region src/locks.ts
|
|
10
27
|
/**
|
|
11
28
|
* These are the names of the lockfiles that the harness records. A `go.mod` is the lockfile of a Go
|
|
@@ -191,6 +208,11 @@ const SHIPPED = {
|
|
|
191
208
|
dockerfile: "harness/image/amqp/Dockerfile",
|
|
192
209
|
from: ["harness/image/amqp"]
|
|
193
210
|
},
|
|
211
|
+
kafka: {
|
|
212
|
+
name: "loom-harness-kafka",
|
|
213
|
+
dockerfile: "harness/image/kafka/Dockerfile",
|
|
214
|
+
from: ["harness/image/kafka"]
|
|
215
|
+
},
|
|
194
216
|
grpc: {
|
|
195
217
|
name: "loom-harness-grpc",
|
|
196
218
|
dockerfile: "harness/image/grpc/Dockerfile",
|
|
@@ -287,6 +309,10 @@ const SHIPPED_CLIENTS = {
|
|
|
287
309
|
grpc: {
|
|
288
310
|
image: shipped("grpc"),
|
|
289
311
|
command: ["node", "/opt/harness/grpc/client-grpc.mjs"]
|
|
312
|
+
},
|
|
313
|
+
load: {
|
|
314
|
+
image: shipped("harness"),
|
|
315
|
+
command: ["/opt/harness/load"]
|
|
290
316
|
}
|
|
291
317
|
};
|
|
292
318
|
/** These are the names of the clients that the harness ships. */
|
|
@@ -624,6 +650,8 @@ const pgClientImage = () => imageOf(shipped("pg"));
|
|
|
624
650
|
const hikariClientImage = () => imageOf(shipped("hikari"));
|
|
625
651
|
/** This function gives the image of the RabbitMQ client: amqplib, with the client and the admin of a cluster cell. */
|
|
626
652
|
const amqpClientImage = () => imageOf(shipped("amqp"));
|
|
653
|
+
/** This function gives the image of the Kafka client: kafka-clients on Java, with the client and the admin of a Kafka cell. */
|
|
654
|
+
const kafkaClientImage = () => imageOf(shipped("kafka"));
|
|
627
655
|
/** This function gives the image of the gRPC client of the harness: grpc-js 1.14.6 on Node 24.21.0, with its client. */
|
|
628
656
|
const grpcClientImage = () => imageOf(shipped("grpc"));
|
|
629
657
|
/**
|
|
@@ -634,6 +662,6 @@ const targetSourceOf = (target) => target.subject ?? target.image;
|
|
|
634
662
|
/** This function gives the image that a target operates: the image of its subject, or its stock image. */
|
|
635
663
|
const targetImageOf = (target) => imageOf(targetSourceOf(target));
|
|
636
664
|
//#endregion
|
|
637
|
-
export {
|
|
665
|
+
export { unlockedManifests as A, isHopPlace as B, programOf as C, subjectProblems as D, subjectClient as E, jarVersions as F, requestFirst as H, locksOf as I, npmVersions as L, LOCK_NAMES as M, cargoVersions as N, targetImageOf as O, goVersions as P, versionsOf as R, planOf as S, shippedSource as T, latestEndOf as V, kafkaClientImage as _, SHIPPED_NAMES as a, nodeHttpImage as b, buildRecordOf as c, harnessImage as d, harnessVersion as f, inContext as g, imageProblems as h, SHIPPED_CLIENTS as i, unpinnedBases as j, targetSourceOf as k, goHttpImage as l, imageOf as m, PINNED as n, amqpClientImage as o, hikariClientImage as p, REPOSITORY as r, basesOf as s, CLIENT_NAMES as t, grpcClientImage as u, mongoClientImage as v, routerImage as w, pgClientImage as x, nodeClientImage as y, CLIENT_CAPABILITIES as z };
|
|
638
666
|
|
|
639
|
-
//# sourceMappingURL=image-
|
|
667
|
+
//# sourceMappingURL=image-BxVTFZ1o.js.map
|