@mark1russell7/machines 0.0.0-stage → 0.3.7

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mark Russell
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,164 @@
1
- # Temporary Holding Version
1
+ # @mark1russell7/machines
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The machine documents of the systems program, in one place. Each document is a state machine as data, in the format `mark1russell7.machine/1` of [`@mark1russell7/algebra`](https://www.npmjs.com/package/@mark1russell7/algebra). Each document describes one system at one version, from the source of that version.
4
+
5
+ ## The machine document
6
+
7
+ A machine document gives the states, events, knobs, timers and transitions of one machine.
8
+
9
+ - **States and transitions.** A transition goes from one or more states to a state, on one or more events. Each transition can name the file and the line that it comes from (`source`).
10
+ - **Events.** Each event has a kind. The kinds are `rx` (a segment in), `tx` (a segment out), `app` (a call of the application), `timer`, `local`, `packet` and `peer`.
11
+ - **Knobs.** Each knob has its key in its system, its scope, its unit and its default.
12
+ - **Timers.** A timer has a duration over the knobs, the events that arm it and cancel it, and the event that it fires. It can also have a lateness and an early bound.
13
+ - **Realizations.** A document can give the time of a mechanism (`realizes`): one of its timers, or a time of its own over its knobs.
14
+ - **Layers.** A document can operate on another machine (`over`), as a driver operates on its kernel socket. `over.machine` names the machine below as `systems.machine.<id>`.
15
+ - **Sources.** Each document names its sources, and each source has a rung. The rung tells the type of the source:
16
+ - `normative`: a specification, for example an RFC.
17
+ - `implemented`: the code of the system at the version.
18
+ - `documented`: the documentation of the system.
19
+ - `observed`: a measurement of the system.
20
+ - `derived`: a result of other sources.
21
+
22
+ The algebra reads these documents. It gives the closed form of each timer, the first detector of a failure, and the recovery after a stall.
23
+
24
+ ## The documents
25
+
26
+ | Export | Identifier | System and version | Layer | Sources, by rung |
27
+ | --- | --- | --- | --- | --- |
28
+ | `LINUX_TCP` | `linux-tcp` | TCP of Linux 6.6, for kernels from 6.6 to 6.9 | kernel | 4 normative, 7 implemented |
29
+ | `NF_CONNTRACK_TCP` | `nf-conntrack-tcp` | The TCP state machine of conntrack on Linux 6.6.87.2 | middlebox | 4 implemented |
30
+ | `REDIS_CLIENT` | `redis-client` | One client connection of the Redis 8.10.2 server | server | 3 implemented, 1 documented |
31
+ | `IOREDIS_STATUS` | `ioredis-status` | The connection status of ioredis 6.0.0, standalone | driver | 5 implemented |
32
+ | `IOREDIS_SENTINEL` | `ioredis-sentinel` | ioredis 6.0.0 in Sentinel mode | driver | 10 implemented |
33
+ | `SENTINEL` | `valkey-sentinel` | One Sentinel of Valkey 9.1.2, and the failover that it leads | server | 8 implemented, 1 observed |
34
+ | `NODE_HTTP_SERVER` | `node-http-server` | One connection of the `http.Server` of Node 24.21.0 | server | 8 implemented |
35
+ | `NODE_HTTP_AGENT` | `node-http-agent` | One socket of the `http.Agent` of Node 24.21.0 | driver | 9 implemented |
36
+ | `UNDICI_CLIENT` | `undici-client-h1` | The socket of an HTTP/1.1 `Client` of undici 8.12.2 | driver | 8 implemented |
37
+ | `GO_TRANSPORT` | `go-nethttp-transport` | One connection of the `http.Transport` of Go 1.27.2 | driver | 7 implemented |
38
+ | `PROCEDURES_WS_CLIENT` | `procedures-ws-client` | The WebSocket client of `@procedures/client` 0.3.0 | driver | 9 implemented, 1 documented |
39
+ | `PROCEDURES_WS_SERVER` | `procedures-ws-server` | The WebSocket server of `@procedures/client` 0.3.0 | server | 4 implemented |
40
+ | `MONGODB_NODE` | `mongodb-node` | The MongoDB Node driver 7.7.0, for one server of a replica set | driver | 19 implemented |
41
+ | `MONGOD_REPL` | `mongod-replication` | The replication of mongod 9.0.4: one member of a replica set | server | 29 implemented |
42
+ | `MONGOD_SESSION` | `mongod-session` | One client connection of mongod 9.0.4 | server | 6 implemented |
43
+ | `NODE_POSTGRES` | `node-postgres` | node-postgres 8.23.1 with pg-pool 3.14.0: one client of a `pg.Pool` | driver | 30 implemented, 2 documented, 1 derived |
44
+ | `POSTGRES_SESSION` | `postgres-session` | One client connection of a PostgreSQL 17.11 backend | server | 41 implemented, 2 documented |
45
+ | `HIKARICP_PGJDBC` | `hikaricp-pgjdbc` | HikariCP 7.1.0 over pgjdbc 42.7.13: one connection of a pool | driver | 41 implemented, 1 documented, 2 derived |
46
+ | `PGBOUNCER_CLIENT` | `pgbouncer-client` | PgBouncer 1.26.1 in transaction pooling: one client connection | proxy | 29 implemented |
47
+ | `PGBOUNCER_SERVER` | `pgbouncer-server` | PgBouncer 1.26.1 in transaction pooling: one server connection of a pool | proxy | 26 implemented |
48
+
49
+ Sixteen documents operate on Linux TCP (`over`). Linux TCP, conntrack, the Sentinel and the replication of mongod operate on no other document. The `conditions` of each document give the range where it holds, for example a range of kernels.
50
+
51
+ The package also gives these parts:
52
+
53
+ - **`MACHINES`** gives each document by its identifier, for example `MACHINES["linux-tcp"]`.
54
+ - **`MANIFESTATIONS`** gives, for each manifestation of a failure, the incoming events that continue to arrive at Linux TCP. A black hole lets nothing through. The kernel of a frozen process continues to send ACKs, thus `rx.ack` arrives.
55
+ - **The lateness of a user timer.** A Node timer and a Go timer sleep in `epoll_wait`, and the kernel lets that sleep end late. `nodeTimerLateness`, `NODE_TIMER_EARLY` and `goTimerLateness` give these bounds as expressions over the knobs. `nodeLateSeconds`, `nodeEarlySeconds` and `goLateSeconds` give the same bounds as numbers.
56
+ - **The fast timers of undici.** `undiciFastEarly` and `undiciFastLateness` give the bounds of a timer that counts in ticks of `UNDICI_TICK_MS`.
57
+
58
+ ## How a program reads them
59
+
60
+ Import a document by its name, or find it in `MACHINES` by its identifier. The schema of the algebra examined each document at load, thus a program does not parse it again.
61
+
62
+ ```ts
63
+ import { detection, timerOf } from "@mark1russell7/algebra";
64
+ import { LINUX_TCP, MACHINES, MANIFESTATIONS } from "@mark1russell7/machines";
65
+
66
+ const values = (name: string) =>
67
+ ({
68
+ keepidle: { value: 7200, unit: "s" },
69
+ keepintvl: { value: 75, unit: "s" },
70
+ keepcnt: { value: 9, unit: "count" },
71
+ })[name];
72
+
73
+ timerOf(LINUX_TCP, "keepalive", values).duration; // { value: 7875, unit: "s" }
74
+
75
+ const blackhole = { name: "blackhole", passes: MANIFESTATIONS["blackhole"] ?? [] };
76
+ const idle = { state: "ESTABLISHED", inFlight: false };
77
+ detection(LINUX_TCP, idle, blackhole, values).first?.timer; // "keepalive"
78
+
79
+ MACHINES["ioredis-status"]?.over?.machine; // "systems.machine.linux-tcp"
80
+ ```
81
+
82
+ The workspace of this repository uses the source. The npm package holds the build: ES modules, with each JSON document in the JavaScript.
83
+
84
+ ## How a document changes
85
+
86
+ A document changes only for one of two reasons:
87
+
88
+ - **A reason from the source.** The change cites a fact of the source at its version: a file and a line, or a section of a specification. The citation goes in the `source` of a transition, a `note`, or a source of the document.
89
+ - **A measurement.** A run of the harness refutes a time or a transition of the document. The change names the run, and it adds a source with the rung `observed`.
90
+
91
+ A change to the version of a system changes its sources too. Each fact of the document then cites the new version.
92
+
93
+ In this repository, a snapshot of the predictions of the cells (`packages/cells/src/__snapshots__/predictions.json`) shows each prediction that a change to a document moves.
94
+
95
+ ### 0.3.7
96
+
97
+ - **PgBouncer 1.26.1, in transaction pooling.** Two new documents, each from the C source at the tag pgbouncer_1_26_1. Each of them operates on one socket, on Linux TCP:
98
+ - `pgbouncer-client` is one client connection: its login, its wait in the queue, and its transactions. Between two transactions PgBouncer reads the socket, and in the queue it does not.
99
+ - `pgbouncer-server` is one server connection of a pool: its connect and its login, its checks, and its close. It also gives the wait of the pool after a failed login (`server_login_retry`).
100
+ - Each timer of PgBouncer is a check of its janitor, each 333.3 ms, thus up to one period late. Only the TCP connect has its own timer, of libevent.
101
+ - At the defaults, an idle server older than 30 s gets the empty query as a check before its next use. No timer bounds the reply of the check.
102
+
103
+ ### 0.3.6
104
+
105
+ - **`hikaricp-pgjdbc`: the queue of the keepalive checks.** The keepalive task of each connection operates on the one thread of the housekeeper (HikariPool.java:644-656). Behind a silent fault, each check waits for its read timeout. Thus the check of one connection can wait for the checks of the other connections. The note of the timer `keepalive` says so. No value of a document changes.
106
+
107
+ ### 0.3.5
108
+
109
+ - **`postgres-session`: the slack of the SIGALRM of a backend.** The knob `alarm_slack` has the value 10 ms. It is an assumption of the document, as the slack of the two client documents: the source gives no bound. The handler of SIGALRM sets the latch of the backend (timeout.c:364-377). pg_sleep waits on that latch, and it checks for interrupts before each wait (adt/misc.c:391-412). Thus a statement timer ends a sleep at once.
110
+ - The source of pg_sleep is new. No other part of a document changes.
111
+
112
+ ### 0.3.4
113
+
114
+ - **`hikaricp-pgjdbc`: the start check of the pool.** At its start, the pool tries once, and after a failure it sleeps 1 s (`start_check`). It tries again while `initializationFailTimeout` has not passed, and then the start fails with PoolInitializationException, with the error of the last try. At the default of 1 ms, the start fails after one try and one sleep. The source is HikariPool.java:567-599.
115
+ - The knob `initializationFailTimeout`, the state `start-check` and three transitions are new. No other part of a document changes.
116
+
117
+ ### 0.3.3
118
+
119
+ - **`hikaricp-pgjdbc`: the slack of poll().** The JDK waits for a read or a connect with a timeout in poll() (NioSocketImpl.java at `jdk-21.0.12+8`). Linux ends the wait of poll() up to 0.1 % of its time late, at most 100 ms (fs/select.c of Linux 6.6). Thus four timers get that lateness with the slack of the JVM: the connect, the SSLRequest, the read timeout and the check.
120
+ - The cells of O13 measured it: a read timeout of 11 s closed its socket up to 11.35 ms late (run 39109649303).
121
+ - The bands of the HikariCP cells with these timers move in the snapshot. No other document changes.
122
+
123
+ ### 0.3.2
124
+
125
+ - **`hikaricp-pgjdbc`.** HikariCP 7.1.0 over pgjdbc 42.7.13, for one connection of a pool, from the tags `HikariCP-7.1.0` and `REL42.7.13`. The plan of R3 gives most of its PostgreSQL cells to this client.
126
+ - HikariCP reads no idle socket. It checks a connection only at a borrow, after more than 500 ms of idle time, and at its keepalive. The keepalive comes each 96 to 120 s from the creation of the connection, and a use does not move it. Each check is an empty query with a read timeout of 5 s.
127
+ - At the defaults, no timer of pgjdbc bounds a statement or the startup: `socketTimeout` is 0. The connect timeout of 10 s bounds only the TCP connect and the SSLRequest of sslmode `prefer`.
128
+ - An I/O error of a statement is 08006, and HikariCP closes the connection at once. The lifetime of a connection is 22.5 to 30 min. At the defaults the pool has a fixed size of 10, thus its idle timer has no effect.
129
+ - The login timeout that HikariCP gives the JVM does not apply, because pgjdbc reads its own `loginTimeout`, which is 0.
130
+ - No prediction of the snapshot moves.
131
+
132
+ ### 0.3.1
133
+
134
+ - **PostgreSQL.** Two documents give the first systems of the PG catalog, each from its source at its tag or its npm version:
135
+ - `node-postgres`: pg 8.23.1 with pg-pool 3.14.0. At the defaults, no timer bounds the connect, a checkout from a full pool or a query. The pool removes an idle client after 10 s, and it emits `error` when an idle client fails. No socket of pg has keepalive, and neither package sends a query again.
136
+ - `postgres-session`: a backend of PostgreSQL 17.11 (`REL_17_11`, the image `postgres:17.11`). It turns on SO_KEEPALIVE, and at its defaults the keepalive sysctls of the namespace apply. Each timeout is off at 0. A send to a lost client waits with no timeout, thus the kernel or SIGTERM ends it.
137
+
138
+ ### 0.3.0
139
+
140
+ - **`linux-tcp`: the delayed ACK.** The timer `delayed_ack` arms on each segment of data (`rx.data`), and each segment that goes out stops it. It waits from `TCP_DELACK_MIN` (HZ/25) up to the smoothed round trip, and `TCP_DELACK_MAX` (HZ/5) at most. The models are `linux.delack` and `linux.delack-lateness` of the algebra 0.7.1.
141
+ - The document realizes the ack delay (`systems.mechanism.ack-delay`): from at once to that wait. The kernel acknowledges at once in quick-ACK mode. Thus a client that sends one request acknowledges its reply at once, and a client of many requests waits.
142
+ - The sources are `include/net/tcp.h`, `net/ipv4/tcp_output.c`, `net/ipv4/tcp_input.c` and `net/ipv4/tcp.c` of Linux 6.6, and RFC 1122 §4.2.3.2.
143
+ - One prediction of the snapshot moves. The WST cell `router silent-drop` loses its bound on the round trip, 405 ms. The cap of 200 ms keeps the forget of the router before the first ping at each round trip.
144
+
145
+ ### 0.2.0
146
+
147
+ - **The MongoDB documents realize the mechanisms of a reader.** In `mongod-replication`, the heartbeat window is the heartbeat detection time, and the liveness check is the step-down window. In `mongodb-node`, the selection timeout is the client retry window.
148
+ - **`redis-client`.** A blocking command holds its client in the state `BLOCKED`. The timer `blocked` gives its reply at its timeout, up to one serverCron tick and 1 ms late. The idle timer arms on the entry to `CONNECTED` and on each read, and it closes the client up to 1 s and one tick late. In 0.1.0 it armed on `accept` only, thus it did not fire at any time.
149
+ - The knob `redis_hz` gives the tick. The sources are `src/timeout.c`, `src/blocked.c`, `src/ae.c` and `src/server.c` of Redis 8.10.2.
150
+ - **`off`.** Eight knobs give the value that turns their timers off, each 0. They are `tcp_user_timeout`, Redis's `timeout` and `blocking_timeout`, and two timeouts of Node's server. The MongoDB driver adds `connectTimeoutMS`, `socketTimeoutMS` and `waitQueueTimeoutMS`. Each catalog prediction stays the same.
151
+
152
+ ## Installation
153
+
154
+ ```sh
155
+ pnpm add @mark1russell7/machines @mark1russell7/algebra zod
156
+ ```
157
+
158
+ The package uses `@mark1russell7/algebra` for the type `Machine` and the schema `machineSchema`. The algebra does not use this package. Both packages use `zod` as a peer dependency.
159
+
160
+ ## Tests
161
+
162
+ `pnpm --filter @mark1russell7/machines test` starts the tests. They examine each document with the schema and the consistency checks of the algebra. They also compute the algebra on the real documents: the defaults of Linux 6.6, the backoff waits, recovery after a stall, and detection.
163
+
164
+ `pnpm --filter @mark1russell7/machines build` writes the package for npm into `build/`.
@@ -0,0 +1,341 @@
1
+ import { Expr, Machine } from "@mark1russell7/algebra";
2
+ //#region src/http/go-transport.d.ts
3
+ /**
4
+ * This document is one connection of the `http.Transport` of Go 1.27.2 at its defaults, over its
5
+ * Linux TCP socket. Each fact comes from the source at the tag `go1.27.2`. The comments give the
6
+ * file and the line.
7
+ *
8
+ * The idle timeout is the C of the keep-alive race. The transport ignores the `Keep-Alive` hint of
9
+ * the server. It finds a connection that the server closed when its read loop reads the end of
10
+ * file. A reused connection can fail before any byte of the reply. Then the transport sends a
11
+ * request that it can replay again, on a new connection, by itself.
12
+ */
13
+ export declare const GO_TRANSPORT: Machine;
14
+ //#endregion
15
+ //#region src/http/node-agent.d.ts
16
+ /**
17
+ * This document is one socket of the `http.Agent` of Node v24.21.0, as its global agent sets it.
18
+ * Its keep-alive is on, its free socket timeout is 5 s, and it is LIFO. It is over the Linux TCP socket. Each fact
19
+ * comes from the source at the tag `v24.21.0`, with the file and the line.
20
+ *
21
+ * A free socket keeps its connection until the smaller of the timeout of the agent and the hint of
22
+ * the server less a buffer. An agent without a timeout keeps it with no limit, and then the hint
23
+ * changes nothing.
24
+ *
25
+ * The free socket timer arms on the event loop of the program, when the program has read the
26
+ * whole response. The time from the last segment that the kernel received to that arm is the time
27
+ * of the program. No source bounds it, and this document does not hold it. The race of the cells
28
+ * adds it from a calibration (`HANDLING` in `packages/cells/src/http/race.ts`).
29
+ */
30
+ export declare const NODE_HTTP_AGENT: Machine;
31
+ //#endregion
32
+ //#region src/http/node-server.d.ts
33
+ /**
34
+ * This document is one connection as the `http.Server` of Node v24.21.0 holds it, over the Linux
35
+ * TCP socket of the connection. Each fact comes from the source at the tag `v24.21.0`. The comments
36
+ * give the file and the line.
37
+ *
38
+ * The keep-alive timer is the S of the keep-alive race. It arms when the response ends, not when
39
+ * the request starts. It is a socket timeout on the timers of libuv, thus it has the lateness of a
40
+ * Node timer (`timers.ts`). When it fires, the server closes the socket. The kernel sends a FIN, or
41
+ * a reset when the receive queue has data that nothing read.
42
+ */
43
+ export declare const NODE_HTTP_SERVER: Machine;
44
+ //#endregion
45
+ //#region src/http/undici.d.ts
46
+ /**
47
+ * This document is the socket of an HTTP/1.1 `Client` of undici 8.12.2, over its Linux TCP socket.
48
+ * Each fact comes from the published package at 8.12.2, with the file and the line.
49
+ *
50
+ * The keep-alive timeout comes from the hint of the server less a threshold, capped by a maximum.
51
+ * The headers and body timeouts use the fast timers of undici, which count in ticks of 499 ms. The
52
+ * client sends no request again by itself. A request that it did not write yet goes on the next
53
+ * connection.
54
+ *
55
+ * The keep-alive timer arms on the event loop of the program, in the check phase after the parse
56
+ * of the reply. The time from the last segment that the kernel received to that arm is the time of
57
+ * the program. No source bounds it, and this document does not hold it. The race of the cells adds
58
+ * it from a calibration (`HANDLING` in `packages/cells/src/http/race.ts`).
59
+ */
60
+ export declare const UNDICI_CLIENT: Machine;
61
+ //#endregion
62
+ //#region src/ioredis-sentinel.d.ts
63
+ /**
64
+ * This document is the Sentinel path of ioredis 6.0.0. It tells how ioredis finds the primary of a
65
+ * group through the Sentinels, loses it, and connects to the new one. The standalone states of
66
+ * `ioredis-status` stay, and a connect asks a Sentinel first. The driver has no timer that watches
67
+ * the group: it moves only when its own connection closes. The failover detector, which
68
+ * subscribes to `+switch-master`, is off by default.
69
+ */
70
+ export declare const IOREDIS_SENTINEL: Machine;
71
+ //#endregion
72
+ //#region src/json.d.ts
73
+ /** This document is TCP as Linux 6.6 implements it: one full socket, from the source of the kernel and the RFCs. */
74
+ export declare const LINUX_TCP: Machine;
75
+ /** This document is the TCP state machine of conntrack on Linux 6.6.87.2: the state of a router or a NAT for one flow. */
76
+ export declare const NF_CONNTRACK_TCP: Machine;
77
+ /** This document is one client connection as the Redis 8.10.2 server holds it, over its Linux TCP socket. */
78
+ export declare const REDIS_CLIENT: Machine;
79
+ /** This document is the status of one standalone connection of ioredis 6.0.0, over its Linux TCP socket. */
80
+ export declare const IOREDIS_STATUS: Machine;
81
+ /**
82
+ * This map gives, for each manifestation of a failure, the incoming events that continue to arrive
83
+ * at Linux TCP while the failure lasts. A black hole lets nothing through. The kernel of a frozen
84
+ * process continues to send ACKs, thus `rx.ack` arrives.
85
+ */
86
+ export declare const MANIFESTATIONS: Readonly<Record<string, readonly string[]>>;
87
+ //#endregion
88
+ //#region src/mongo/mongod-replication.d.ts
89
+ /**
90
+ * This document is the replication of mongod 9.0.4. It gives one member of a replica set, its view
91
+ * of the primary, and the election that it can hold. The states are the states of the member. The
92
+ * timers are the heartbeats, the election timeout, the liveness check of a primary, the vote, the
93
+ * catch-up of a new primary and a step-down.
94
+ *
95
+ * Each member sends a heartbeat to each other member. A heartbeat window is 10 s: in it, a failed
96
+ * request goes again at once, two times at most. A window without a response marks the target
97
+ * DOWN. A secondary starts an election when it hears nothing from the primary for the election
98
+ * timeout and a random offset. A primary steps down when it cannot see a majority for the election
99
+ * timeout.
100
+ *
101
+ * A secondary keeps a silent primary as its sync source until its oplog fetcher gives up. That is
102
+ * two timeouts and a restart: 17 s to 18 s at the defaults. Its reporter keeps a
103
+ * replSetUpdatePosition in flight to that primary for 30 s. Until then, a new primary learns the
104
+ * position of that secondary only from the response to each heartbeat.
105
+ */
106
+ export declare const MONGOD_REPL: Machine;
107
+ //#endregion
108
+ //#region src/mongo/mongod-session.d.ts
109
+ /**
110
+ * This document is the hold of mongod 9.0.4 on one client connection, over its socket. `mongod`
111
+ * turns keepalive on for each TCP session. It lowers two keepalive options of the socket to a
112
+ * maximum: the idle time to 300 s and the interval to 1 s. It does not change the probe count.
113
+ * Thus the namespace sysctls give the idle time and the interval only when they are lower, and
114
+ * they always give the count.
115
+ *
116
+ * `mongod` writes no warning about keepalive. A failure to read or to set an option goes to the
117
+ * log at debug level 3 in a release build.
118
+ *
119
+ * An awaitable hello of an exhaust stream waits for a change of the topology or `maxAwaitTimeMS`.
120
+ * Then `mongod` sends the reply, and it starts the next hello of the stream at once.
121
+ */
122
+ export declare const MONGOD_SESSION: Machine;
123
+ //#endregion
124
+ //#region src/mongo/mongodb-node.d.ts
125
+ /**
126
+ * This document is the MongoDB Node driver 7.7.0, for one server of a replica set. It gives one
127
+ * connection of the driver by its role, and the timers that act on it. The roles are the monitor
128
+ * of the server, the pool connection that an operation uses, and the wait of an operation for a
129
+ * suitable server. The monitor streams `hello`: the server answers when its topology changes, or
130
+ * after `heartbeatFrequencyMS`. The monitor writes the server off when its socket is silent for
131
+ * `connectTimeoutMS + heartbeatFrequencyMS`.
132
+ *
133
+ * A knob of the driver at 0 has no timer: give it as no bound (`infinite`). This is true of
134
+ * `connectTimeoutMS`, `socketTimeoutMS`, `waitQueueTimeoutMS`, `maxIdleTimeMS` and
135
+ * `serverSelectionTimeoutMS`.
136
+ */
137
+ export declare const MONGODB_NODE: Machine;
138
+ //#endregion
139
+ //#region src/pg/hikaricp-pgjdbc.d.ts
140
+ /**
141
+ * This document is HikariCP 7.1.0 over pgjdbc 42.7.13, for one connection of a pool. It gives the
142
+ * states of the connection, from its creation to its close, and the timers that act on it. The
143
+ * pool makes its connections one at a time, on one thread. At the defaults the pool has a fixed
144
+ * size of 10, thus its idle timer has no effect.
145
+ *
146
+ * HikariCP reads no idle socket. It finds a dead connection only by a check. A borrow checks a
147
+ * connection that was idle for more than 500 ms. The keepalive checks an idle connection each 96 to
148
+ * 120 s from its creation. Each check is `isValid`: pgjdbc sends one Query message with an empty
149
+ * string, with a read timeout of `validationTimeout`. A read timeout or an I/O error closes the
150
+ * socket.
151
+ *
152
+ * pgjdbc sends nothing on an idle connection. Its only read timeout is `socketTimeout`, which is
153
+ * off at the defaults, thus no timer of pgjdbc bounds a statement or the startup. Its connect
154
+ * timeout of 10 s bounds only the TCP connect and the SSLRequest. At sslmode `prefer` (the
155
+ * default), a read timeout in the connect starts one more connect with SSL off, in what remains of
156
+ * the 10 s.
157
+ *
158
+ * The JDK waits for a read or a connect with a timeout in poll(). Linux ends that wait up to 0.1 % of
159
+ * its time late, at most 100 ms: 11 ms for a read timeout of 11 s (run 39109649303).
160
+ *
161
+ * HikariCP closes a connection at once when a statement fails with an SQLState of the class 08. It
162
+ * also closes it for 57P01, 57P02, 57P03 and 0A000. pgjdbc gives 08006 for each I/O error of a
163
+ * statement. Thus a reset, an end of the stream or a give-up of the kernel each close the
164
+ * connection. HikariCP does not send a statement again.
165
+ */
166
+ export declare const HIKARICP_PGJDBC: Machine;
167
+ //#endregion
168
+ //#region src/pg/node-postgres.d.ts
169
+ /**
170
+ * This document is node-postgres 8.23.1 (the npm package pg) with pg-pool 3.14.0, for one client
171
+ * of a `pg.Pool`. It gives the states of the client, from its connect to its end, and the timers
172
+ * that act on it. The pool hands out an idle client with no test of its connection. At the
173
+ * defaults, the client turns no keepalive on and sends nothing on an idle connection. Neither
174
+ * package sends a query again, and neither package connects again by itself.
175
+ *
176
+ * A knob of pg at 0 or false has no timer: give it as no bound (`infinite`). This is true of
177
+ * `connectionTimeoutMillis`, `query_timeout`, `maxLifetimeSeconds` and `idleTimeoutMillis`. At the
178
+ * defaults of a pool, only the idle timer of the pool runs, for 10000 ms. Thus no timer of pg
179
+ * bounds the connect, the startup, a checkout from a full pool or a query.
180
+ *
181
+ * Three timeouts are not timers of the client: `statement_timeout`, `lock_timeout` and
182
+ * `idle_in_transaction_session_timeout`. The client sends each one to the server in the startup
183
+ * message, and only when it is set.
184
+ *
185
+ * The pool emits `error` when an idle client fails. A client that the application holds emits
186
+ * `error` itself, and the pool does not listen to it. In Node, an `error` event with no listener
187
+ * throws.
188
+ */
189
+ export declare const NODE_POSTGRES: Machine;
190
+ //#endregion
191
+ //#region src/pg/pgbouncer.d.ts
192
+ /**
193
+ * This document is PgBouncer 1.26.1 in transaction pooling, for one client connection. It gives the
194
+ * states of the client, from its accept to its close, and the timers that act on it.
195
+ *
196
+ * In transaction pooling, a client holds a server connection only for a transaction. Between two
197
+ * transactions the client is idle, and PgBouncer reads its socket: the end of the stream or a reset
198
+ * closes it at once. A query that finds no idle server waits in a queue, and PgBouncer does not read
199
+ * the socket of a waiting client. It finds a client that left the queue only when it serves it.
200
+ *
201
+ * Each timer of a client is a check of the janitor, which runs each 333.3 ms. A timer thus fires up
202
+ * to one period after its limit, and a busy loop of events delays it more. At the defaults only two
203
+ * timers act on a client: client_login_timeout (60 s) and query_wait_timeout (120 s). A timer that
204
+ * fires, and the failure of the linked server, close the client with a FATAL error of SQLSTATE 08P01.
205
+ */
206
+ export declare const PGBOUNCER_CLIENT: Machine;
207
+ //#endregion
208
+ //#region src/pg/pgbouncer-server.d.ts
209
+ /**
210
+ * This document is PgBouncer 1.26.1 in transaction pooling, for one server connection of a pool:
211
+ * from its launch to its close. It also gives the wait of the pool before its next connection after
212
+ * a failed login.
213
+ *
214
+ * PgBouncer reads the socket of each idle server, thus the end of the stream or a reset of an idle
215
+ * server closes it at once. A black hole stops nothing that PgBouncer reads. Only a check of the
216
+ * server, a timer of the kernel, server_idle_timeout or server_lifetime removes such a server. The
217
+ * check is the empty query before a reuse, when the server was idle for longer than
218
+ * server_check_delay (30 s). It acts at the defaults, and no timer bounds its reply. Thus behind a
219
+ * black hole, the client that waits for the check stays in the queue until its query_wait_timeout.
220
+ *
221
+ * The TCP connect has a timer of libevent of server_connect_timeout, in whole seconds. The janitor
222
+ * also bounds the whole login by server_connect_timeout, from the launch. After a failed login the
223
+ * pool starts no connection for server_login_retry from the launch of the failed one. In that time
224
+ * each client that needs a server fails at once, and a waiting client stays in the queue.
225
+ */
226
+ export declare const PGBOUNCER_SERVER: Machine;
227
+ //#endregion
228
+ //#region src/pg/postgres-session.d.ts
229
+ /**
230
+ * This document is the hold of a PostgreSQL 17.11 backend on one client connection, over its TCP
231
+ * socket on Linux. The backend turns on SO_KEEPALIVE for each TCP socket. At the defaults of its
232
+ * four TCP GUCs, it changes no keepalive option and no user timeout. Thus the namespace sysctls
233
+ * give the idle time, the interval and the count. A GUC above 0 sets its socket option.
234
+ *
235
+ * Each timer of a backend is a SIGALRM timeout. At startup, the handler ends the process at once.
236
+ * After the startup packet, each handler sets a flag and the latch, directly or by a signal. The
237
+ * backend then acts at its next CHECK_FOR_INTERRUPTS. An idle timer and the transaction timer end
238
+ * the session with FATAL. The statement timer and the lock timer end the statement with ERROR.
239
+ *
240
+ * A send to a slow or a lost client waits for the socket with no timeout. In that wait the
241
+ * backend acts on SIGTERM and on the death of the postmaster only. A timer that fires there takes
242
+ * effect after the send. Thus PostgreSQL gives no bound to a send: the kernel ends it, or SIGTERM
243
+ * does.
244
+ *
245
+ * A timeout knob at 0 has no timer: give it as no bound (`infinite`). This is true of
246
+ * `statement_timeout`, `lock_timeout`, `transaction_timeout`, `idle_in_transaction_session_timeout`,
247
+ * `idle_session_timeout` and `client_connection_check_interval`.
248
+ */
249
+ export declare const POSTGRES_SESSION: Machine;
250
+ //#endregion
251
+ //#region src/procedures-ws.d.ts
252
+ /**
253
+ * This document is the connection of the WebSocket client of `@procedures/client` 0.3.0
254
+ * (`WebSocketTransport`), over its socket class and its Linux TCP socket.
255
+ *
256
+ * - The heartbeat is `heartbeat()` of `@mark1russell7/service` 0.4.0. A tick each interval sends a
257
+ * ping only when no pong is awaited. The timeout of the ping starts before its send. A
258
+ * ping without a pong at its timeout is a miss, and `misses` misses in sequence drop the
259
+ * connection. With a timeout below the interval, each tick after a miss sends the next ping.
260
+ * Thus the drop comes (misses − 1) intervals and one timeout after the first ping without an answer.
261
+ * - A drop ends the socket with `terminate()` when its class has it: the `ws` package. The global
262
+ * `WebSocket` of Node has only `close()`, which writes a close frame and destroys nothing.
263
+ * - Each end of a socket starts the reconnect. The wait of try n is the backoff
264
+ * min(initialDelay × multiplier^(n − 1), maxDelay), less a random part: jitter × backoff × r.
265
+ * - The handshake has a time limit (`connectionTimeout`), and a failed handshake drops at once.
266
+ * - The heartbeat refreshes an idle flow. Each tick writes a ping, whatever data the connection
267
+ * carries, and the pong comes back. Thus the ping timer realizes the idle refresh of O03.
268
+ */
269
+ export declare const PROCEDURES_WS_CLIENT: Machine;
270
+ /**
271
+ * This document is one connection as the WebSocket server of `@procedures/client` 0.3.0 holds it
272
+ * (`WebSocketServerTransport` on the `ws` package), over its Linux TCP socket.
273
+ *
274
+ * The heartbeat of the server (roadmap R3) is a `setInterval`. Each beat pings each connection,
275
+ * and the server ends a connection after `misses` beats without a pong (`terminate()`). Thus the
276
+ * drop comes `misses` beats after the first ping without an answer, and the lateness of each beat
277
+ * adds. Its `http.Server` sets no SO_KEEPALIVE when `keepAlive` is off, the default of Node.
278
+ */
279
+ export declare const PROCEDURES_WS_SERVER: Machine;
280
+ //#endregion
281
+ //#region src/sentinel.d.ts
282
+ /**
283
+ * This document is the Sentinel of Valkey 9.1.2. It gives the view of one Sentinel on the primary
284
+ * of a group that it monitors, and the failover that it can lead. The states are the down states
285
+ * and the states of the failover. The timers are the periods and the timeouts of the Sentinel.
286
+ * Each timer of a period checks at the next tick of the Sentinel, thus its lateness is one tick.
287
+ */
288
+ export declare const SENTINEL: Machine;
289
+ //#endregion
290
+ //#region src/http/timers.d.ts
291
+ /**
292
+ * This function gives the lateness of a Node timer of `ms` milliseconds. The lateness is the slack
293
+ * of its sleep, 1 ms for the truncation of the loop clock, and the step of the coarse clock. The
294
+ * arithmetic reads `ms` in milliseconds, and the knob `hz` in Hz.
295
+ */
296
+ export declare const nodeTimerLateness: (ms: string) => Expr;
297
+ /**
298
+ * This expression is how early a Node timer can fire. It is 1 ms for the truncation of the loop
299
+ * clock that stamps its start, and the step of the coarse clock.
300
+ */
301
+ export declare const NODE_TIMER_EARLY: Expr;
302
+ /** This function gives the lateness of a Go timer of `s` seconds: the slack of its sleep and 1 ms. The arithmetic reads `s` in seconds. */
303
+ export declare const goTimerLateness: (s: string) => Expr;
304
+ /** This function gives the lateness of a Node timer of `seconds` at a HZ, in seconds: the number form of `nodeTimerLateness`. */
305
+ export declare const nodeLateSeconds: (seconds: number, hz: number) => number;
306
+ /** This function gives how early a Node timer can fire at a HZ, in seconds: the number form of `NODE_TIMER_EARLY`. */
307
+ export declare const nodeEarlySeconds: (hz: number) => number;
308
+ /** This function gives the lateness of a Go timer of `seconds`, in seconds: the number form of `goTimerLateness`. */
309
+ export declare const goLateSeconds: (seconds: number) => number;
310
+ /**
311
+ * This count is the tick of the fast timers of undici 8.12.2, in milliseconds:
312
+ * `(RESOLUTION_MS >> 1) - 1` with `RESOLUTION_MS` 1000 (`lib/util/timers.js:30-40`).
313
+ */
314
+ export declare const UNDICI_TICK_MS = 499;
315
+ /**
316
+ * This function gives how early a fast timer of undici can fire, for a duration of `ms`
317
+ * milliseconds. Each tick adds the tick to the clock of the fast timers, whatever time passed
318
+ * (`lib/util/timers.js:115-123`).
319
+ *
320
+ * A new timer takes the clock of the next tick less one tick as its
321
+ * start (`lib/util/timers.js:151-155`). It fires at the first tick where the clock is its start
322
+ * plus its duration or more (`lib/util/timers.js:156-162`). Thus it fires after
323
+ * `ceil(ms / 499) - 1` ticks and part of one more tick. Each tick is a Node timer. The loop clock
324
+ * of each tick has the same lag, thus the early bound of a Node timer comes in one time.
325
+ */
326
+ export declare const undiciFastEarly: (ms: string) => Expr;
327
+ /**
328
+ * This function gives how late a fast timer of undici can fire, for a duration of `ms`
329
+ * milliseconds. It fires after at most `ceil(ms / 499)` whole ticks. Each tick is a Node timer
330
+ * of 499 ms (`lib/util/timers.js:190-207`), with the lateness of a Node timer.
331
+ */
332
+ export declare const undiciFastLateness: (ms: string) => Expr;
333
+ //#endregion
334
+ //#region src/index.d.ts
335
+ /**
336
+ * This map holds each document of the package by its identifier, for example `linux-tcp`. A
337
+ * document on another machine names that machine in `over.machine` as `systems.machine.<id>`.
338
+ */
339
+ export declare const MACHINES: Readonly<Record<string, Machine>>;
340
+ //#endregion
341
+ //# sourceMappingURL=index.d.ts.map