@mark1russell7/harness 0.5.0 → 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.
@@ -0,0 +1,59 @@
1
+ // The JSON lines of the Node programs of the HTTP cells: the server and its two Node clients.
2
+ //
3
+ // Each line has `ev` and `t`, as the TCP client of the harness writes them. `t` is
4
+ // process.hrtime, which libuv reads from CLOCK_MONOTONIC: the clock that the prober stamps the
5
+ // records of the kernel with. The arguments are the host and the port, then flags with a value.
6
+
7
+ import { existsSync, readFileSync } from "node:fs";
8
+
9
+ /** This function gives the time now, in nanoseconds on CLOCK_MONOTONIC. */
10
+ export const now = () => process.hrtime.bigint();
11
+
12
+ /** This function writes one line, with the time `at` (the time now when none is given). */
13
+ export const emit = (ev, fields = {}, at = now()) =>
14
+ process.stdout.write(`${JSON.stringify({ ev, t: Number(at), ...fields })}\n`);
15
+
16
+ /** This function gives the boot id of the kernel, or null where the file does not exist. */
17
+ export const bootId = () => {
18
+ try {
19
+ return readFileSync("/proc/sys/kernel/random/boot_id", "utf8").trim();
20
+ } catch {
21
+ return null;
22
+ }
23
+ };
24
+
25
+ /** This function reads the command line: the host and the port first, then `--name value` pairs. */
26
+ export const commandLine = (usage) => {
27
+ const argv = process.argv.slice(2);
28
+ const [host, port] = argv;
29
+ const flag = (name) => {
30
+ const at = argv.indexOf(name);
31
+ return at === -1 ? undefined : argv[at + 1];
32
+ };
33
+ const number = (name, otherwise) => {
34
+ const value = flag(name);
35
+ return value === undefined ? otherwise : Number(value);
36
+ };
37
+ if (host === undefined || port === undefined) {
38
+ emit("fail", { why: usage });
39
+ process.exit(1);
40
+ }
41
+ return { host, port: Number(port), flag, number, has: (name) => argv.includes(name) };
42
+ };
43
+
44
+ /** This function waits until the file at `path` exists. It looks each 2 ms, as the ioredis client does. */
45
+ export const waitFor = (path) =>
46
+ new Promise((resolve) => {
47
+ const look = setInterval(() => {
48
+ if (!existsSync(path)) return;
49
+ clearInterval(look);
50
+ resolve();
51
+ }, 2);
52
+ });
53
+
54
+ /** This function waits `ms` milliseconds on a Node timer. */
55
+ export const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
56
+
57
+ /** This function gives the path of the second request: a held reply, a long body, or the root. */
58
+ export const pathOf = ({ hold, bytes }) =>
59
+ hold !== undefined ? `/hold?ms=${hold}` : bytes !== undefined ? `/big?bytes=${bytes}` : "/";
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "loom-harness-http-clients",
3
+ "lockfileVersion": 3,
4
+ "requires": true,
5
+ "packages": {
6
+ "": {
7
+ "name": "loom-harness-http-clients",
8
+ "dependencies": {
9
+ "undici": "8.12.2"
10
+ }
11
+ },
12
+ "node_modules/undici": {
13
+ "version": "8.12.2",
14
+ "resolved": "https://registry.npmjs.org/undici/-/undici-8.12.2.tgz",
15
+ "integrity": "sha512-XtuDWVdqTLr3NAxm2ly9/hU6kUsJOgGh1RASzMBbsw6aWCOaQzHdW+QQDfdERjfJ2V5vL5pRPa4RetO9UfivDg==",
16
+ "license": "MIT",
17
+ "engines": {
18
+ "node": ">=22.19.0"
19
+ }
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "loom-harness-http-clients",
3
+ "private": true,
4
+ "type": "module",
5
+ "dependencies": {
6
+ "undici": "8.12.2"
7
+ }
8
+ }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package",
3
3
  "name": "@mark1russell7/harness",
4
- "version": "0.5.0",
5
- "description": "A fault-injection harness for connection timers: a cell runs a client against a stock target in Docker, through a topology of routers and proxies or a replicated group under Sentinels, injects a fault, measures the kernel's own records and judges a prediction.",
4
+ "version": "0.6.0",
5
+ "description": "A fault-injection harness for connection timers: a cell runs a client against a stock target in Docker, through a topology of routers and proxies or a replicated group under Sentinels, injects a fault, measures the kernel's own records and judges a prediction. HTTP clients of Go, Node and undici race the keep-alive of a Node server.",
6
6
  "keywords": [
7
7
  "fault-injection",
8
8
  "chaos-engineering",
@@ -47,6 +47,15 @@
47
47
  "image/node/observer.mjs",
48
48
  "image/node/package.json",
49
49
  "image/node/npm-lock.json",
50
+ "image/go-http/Dockerfile",
51
+ "image/go-http/go.mod",
52
+ "image/go-http/main.go",
53
+ "image/node-http/Dockerfile",
54
+ "image/node-http/package.json",
55
+ "image/node-http/npm-lock.json",
56
+ "image/node-http/lines.mjs",
57
+ "image/node-http/client-agent.mjs",
58
+ "image/node-http/client-undici.mjs",
50
59
  "image/router/Dockerfile",
51
60
  "image/router/mbx.sh",
52
61
  "image/router/ctwatch.py",