@mark1russell7/machines 0.3.11 → 0.3.12
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 +4 -0
- package/build/index.d.ts +5 -0
- package/build/index.js +14 -1
- package/build/index.js.map +1 -1
- package/package.json +1 -1
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["AT","linuxTcp","nfConntrackTcp","redisClient","ioredisStatus","manifestations","AT","AT","AT","AT","AT"],"sources":["../src/http/timers.ts","../src/http/go-transport.ts","../src/http/node-agent.ts","../src/http/node-server.ts","../src/http/undici.ts","../src/ioredis-sentinel.ts","../src/ioredis-status.json","../src/linux-tcp.json","../src/manifestations.json","../src/nf-conntrack-tcp.json","../src/redis-client.json","../src/json.ts","../src/mongo/mongod-replication.ts","../src/mongo/mongod-session.ts","../src/mongo/mongodb-node.ts","../src/pg/hikaricp-pgjdbc.ts","../src/pg/node-postgres.ts","../src/pg/pgbouncer.ts","../src/pg/pgbouncer-server.ts","../src/pg/pgpool.ts","../src/pg/postgres-session.ts","../src/pg/supavisor-client.ts","../src/pg/supavisor-server.ts","../src/procedures-ws.ts","../src/sentinel.ts","../src/index.ts"],"sourcesContent":["import type { Expr } from \"@mark1russell7/algebra\";\n\n/**\n * This module gives the lateness of a timer in user space on Linux 6.6. A Node timer and a Go timer\n * both sleep in `epoll_wait` with a timeout in whole milliseconds. The kernel lets that sleep end\n * late by a slack, and the loop reads its clock in whole milliseconds.\n *\n * The facts, each from the source at its version:\n * - `fs/eventpoll.c:1836` (Linux v6.6) takes the slack from `select_estimate_accuracy`, and\n * `fs/eventpoll.c:1921` sleeps with `schedule_hrtimeout_range(to, slack)`. Thus the wake comes\n * in [due, due + slack].\n * - `fs/select.c:51-74` makes the slack the remaining time divided by 1000, at most 100 ms\n * (`MAX_SLACK`). A task with a nice value above 0 divides by 200.\n * - `fs/select.c:91-92` and `init/init_task.c:133` make the slack 50 µs at the minimum\n * (`timer_slack_ns`).\n * - libuv 1.52.1 (`deps/uv/src/unix/linux.c:1451` in Node v24.21.0) calls `epoll_pwait` with the\n * timeout in milliseconds. `deps/uv/src/timer.c:143-160` gives that timeout as the due time\n * less the loop clock, in milliseconds.\n * - `deps/uv/src/unix/internal.h:467-470` truncates the loop clock to milliseconds.\n * - `deps/uv/src/unix/linux.c:1603-1629` reads `CLOCK_MONOTONIC_COARSE` for that clock when its\n * resolution is 1 ms or less, and `CLOCK_MONOTONIC` when it is coarser.\n * - The resolution of the coarse clock is one jiffy (`kernel/time/posix-timers.c:187-190`,\n * `include/vdso/ktime.h:13-14`, `include/vdso/jiffies.h`). It gives the time of the last tick.\n * Thus at HZ 1000 the loop clock can be one jiffy behind, and at HZ 250 it is exact.\n * - Node stamps the start of a timer with the loop clock (`lib/internal/timers.js:426-429`,\n * `src/env.cc:1649-1651`). It starts the callback of a timer when the loop clock less that start\n * is the duration or more (`lib/internal/timers.js:631-641`). Thus the start can be up to 1 ms\n * before the arming, and one more step of the coarse clock.\n * - Go 1.27.2 sleeps in `epoll_wait` with the delay truncated to milliseconds, and with 1 ms when\n * less than 1 ms remains (`src/runtime/netpoll_epoll.go:117-133`). A Go timer does not fire\n * early: a wake before the due time sleeps again.\n *\n * The time that the loop itself spends in callbacks is the time of the application. These\n * documents do not bound it, and the noise of the harness (δ_abs) holds a small part of it. The\n * handling of the first reply by a Node client can take more time than δ_abs, before the client\n * arms its pool timer. The race of the cells adds that time from a calibration (`HANDLING` in\n * `packages/cells/src/http/race.ts`).\n */\n\n/** This text is the slack of `epoll_wait` for a sleep of `ms` milliseconds, in milliseconds. */\nconst slackMs = (ms: string): string => `min(max((${ms}) / 1000, 0.05), 100)`;\n\n/**\n * This text is the step of the loop clock of libuv, in milliseconds, from the knob `hz`. It is one\n * jiffy when the coarse clock is 1 ms or finer (HZ 1000). It is 0 when libuv reads `CLOCK_MONOTONIC`.\n */\nconst COARSE_MS = \"min(floor(hz / 1000), 1) * 1000 / hz\";\n\n/**\n * This function gives the lateness of a Node timer of `ms` milliseconds. The lateness is the slack\n * of its sleep, 1 ms for the truncation of the loop clock, and the step of the coarse clock. The\n * arithmetic reads `ms` in milliseconds, and the knob `hz` in Hz.\n */\nexport const nodeTimerLateness = (ms: string): Expr => ({ expr: `${slackMs(ms)} + 1 + ${COARSE_MS}`, unit: \"ms\" });\n\n/**\n * This expression is how early a Node timer can fire. It is 1 ms for the truncation of the loop\n * clock that stamps its start, and the step of the coarse clock.\n */\nexport const NODE_TIMER_EARLY: Expr = { expr: `1 + ${COARSE_MS}`, unit: \"ms\" };\n\n/** 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. */\nexport const goTimerLateness = (s: string): Expr => ({\n expr: `min(max((${s}) / 1000, 0.00005), 0.1) + 0.001`,\n unit: \"s\",\n});\n\n/** This function gives the step of the coarse loop clock at a HZ, in seconds: the number form of `COARSE_MS`. */\nconst coarseSeconds = (hz: number): number => (Math.min(Math.floor(hz / 1000), 1) * 1000) / hz / 1000;\n\n/** This function gives the lateness of a Node timer of `seconds` at a HZ, in seconds: the number form of `nodeTimerLateness`. */\nexport const nodeLateSeconds = (seconds: number, hz: number): number =>\n (Math.min(Math.max(seconds, 0.05), 100) + 1) / 1000 + coarseSeconds(hz);\n\n/** This function gives how early a Node timer can fire at a HZ, in seconds: the number form of `NODE_TIMER_EARLY`. */\nexport const nodeEarlySeconds = (hz: number): number => 0.001 + coarseSeconds(hz);\n\n/** This function gives the lateness of a Go timer of `seconds`, in seconds: the number form of `goTimerLateness`. */\nexport const goLateSeconds = (seconds: number): number => Math.min(Math.max(seconds / 1000, 0.00005), 0.1) + 0.001;\n\n/**\n * This count is the tick of the fast timers of undici 8.12.2, in milliseconds:\n * `(RESOLUTION_MS >> 1) - 1` with `RESOLUTION_MS` 1000 (`lib/util/timers.js:30-40`).\n */\nexport const UNDICI_TICK_MS = 499;\n\n/**\n * This function gives how early a fast timer of undici can fire, for a duration of `ms`\n * milliseconds. Each tick adds the tick to the clock of the fast timers, whatever time passed\n * (`lib/util/timers.js:115-123`).\n *\n * A new timer takes the clock of the next tick less one tick as its\n * start (`lib/util/timers.js:151-155`). It fires at the first tick where the clock is its start\n * plus its duration or more (`lib/util/timers.js:156-162`). Thus it fires after\n * `ceil(ms / 499) - 1` ticks and part of one more tick. Each tick is a Node timer. The loop clock\n * of each tick has the same lag, thus the early bound of a Node timer comes in one time.\n */\nexport const undiciFastEarly = (ms: string): Expr => ({\n expr: `(${ms}) - (ceil((${ms}) / ${UNDICI_TICK_MS}) - 1) * ${UNDICI_TICK_MS} + 1 + ${COARSE_MS}`,\n unit: \"ms\",\n});\n\n/**\n * This function gives how late a fast timer of undici can fire, for a duration of `ms`\n * milliseconds. It fires after at most `ceil(ms / 499)` whole ticks. Each tick is a Node timer\n * of 499 ms (`lib/util/timers.js:190-207`), with the lateness of a Node timer.\n */\nexport const undiciFastLateness = (ms: string): Expr => ({\n expr:\n `ceil((${ms}) / ${UNDICI_TICK_MS}) * ${UNDICI_TICK_MS} - (${ms})` +\n ` + ceil((${ms}) / ${UNDICI_TICK_MS}) * (${slackMs(String(UNDICI_TICK_MS))} + 1 + ${COARSE_MS})`,\n unit: \"ms\",\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { goTimerLateness } from \"./timers.ts\";\n\n/**\n * This document is one connection of the `http.Transport` of Go 1.27.2 at its defaults, over its\n * Linux TCP socket. Each fact comes from the source at the tag `go1.27.2`. The comments give the\n * file and the line.\n *\n * The idle timeout is the C of the keep-alive race. The transport ignores the `Keep-Alive` hint of\n * the server. It finds a connection that the server closed when its read loop reads the end of\n * file. A reused connection can fail before any byte of the reply. Then the transport sends a\n * request that it can replay again, on a new connection, by itself.\n */\nexport const GO_TRANSPORT: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"go-nethttp-transport\",\n title: \"One connection of the http.Transport of Go 1.27.2\",\n layer: \"driver\",\n version: \"go1.27.2\",\n conditions: { go: \"1.27.2\", os: \"linux\", protocol: \"HTTP/1.1 without TLS\" },\n sources: [\n {\n ref: \"go1.27.2 src/net/http/transport.go:47-62 DefaultTransport: Dialer Timeout 30 s and KeepAlive 30 s, MaxIdleConns 100, IdleConnTimeout 90 s, DefaultMaxIdleConnsPerHost 2\",\n rung: \"implemented\",\n },\n {\n ref: \"go1.27.2 src/net/http/transport.go:1129-1236 tryPutIdleConn: the connection goes back to the pool after its reply, with an idle timer of IdleConnTimeout and idleAt = now\",\n rung: \"implemented\",\n },\n {\n ref: \"go1.27.2 src/net/http/transport.go:1241-1303 queueForIdleConn: the most recent idle connection, unless it is broken or idle for IdleConnTimeout or more by the wall clock\",\n rung: \"implemented\",\n },\n {\n ref: \"go1.27.2 src/net/http/transport.go:2454-2512 readLoop and :2653-2672 readLoopPeekFailLocked: an end of file on an idle connection closes it (errServerClosedIdle); a read error while a reply is due is transportReadFromServerError\",\n rung: \"implemented\",\n },\n {\n ref: \"go1.27.2 src/net/http/transport.go:694-769 roundTrip and :844-889 shouldRetryRequest: a new connection for a reused connection that failed before the reply, when the request can be replayed\",\n rung: \"implemented\",\n },\n {\n ref: \"go1.27.2 src/net/http/request.go:1561-1573 isReplayable: GET, HEAD, OPTIONS, TRACE without a body, or a request with an Idempotency-Key\",\n rung: \"implemented\",\n },\n {\n ref: \"go1.27.2 src/net/tcpsock.go:289-307 newTCPConn: TCP_NODELAY on, and keepalive from Dialer.KeepAlive; src/net/tcpsock_unix.go:12-27; src/net/tcpsockopt_unix.go:15-53 (idle and interval 15 s and count 9 when 0, rounded up to whole seconds); src/net/dial.go:18-27\",\n rung: \"implemented\",\n },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n DIALING: {},\n ACTIVE: { note: \"a request owns the connection\" },\n IDLE: { note: \"in the pool of idle connections\" },\n CLOSED: { final: true },\n },\n events: {\n \"req.dispatch\": { kind: \"app\", note: \"a request asks the transport for a connection (getConn)\" },\n \"conn.established\": { kind: \"local\" },\n \"resp.done\": { kind: \"local\", note: \"the reply was read to its end: the read loop puts the connection back\" },\n \"rx.fin\": { kind: \"peer\", note: \"the read loop reads io.EOF\" },\n \"read.error\": { kind: \"local\", note: \"a read fails: ECONNRESET, ETIMEDOUT, EHOSTUNREACH\" },\n \"rx.rst\": { kind: \"peer\" },\n \"rx.icmp-hard\": { kind: \"rx\", note: \"an ICMP error while the dial waits\" },\n \"timer.idle-conn\": { kind: \"timer\" },\n \"timer.dial\": { kind: \"timer\" },\n \"timer.client\": { kind: \"timer\" },\n \"timer.response-header\": { kind: \"timer\" },\n \"tx.request\": { kind: \"tx\", note: \"the write loop wrote the request\" },\n \"rx.headers\": { kind: \"rx\" },\n },\n knobs: {\n IdleConnTimeout: { key: \"go http.Transport IdleConnTimeout\", scope: \"client\", unit: \"s\", default: 90 },\n MaxIdleConnsPerHost: {\n key: \"go http.Transport MaxIdleConnsPerHost\",\n scope: \"client\",\n unit: \"count\",\n default: 2,\n note: \"0 gives DefaultMaxIdleConnsPerHost, 2 (transport.go:1121)\",\n },\n MaxIdleConns: { key: \"go http.Transport MaxIdleConns\", scope: \"client\", unit: \"count\", default: 100 },\n DialTimeout: { key: \"go net.Dialer Timeout\", scope: \"client\", unit: \"s\", default: 30 },\n KeepAlive: {\n key: \"go net.Dialer KeepAlive\",\n scope: \"client\",\n unit: \"s\",\n default: 30,\n note: \"the TCP_KEEPIDLE of the socket; 0 gives 15 s, and a negative value turns keepalive off\",\n },\n KeepAliveInterval: {\n key: \"go net.KeepAliveConfig Interval\",\n scope: \"client\",\n unit: \"s\",\n default: 15,\n note: \"0 gives 15 s (dial.go:24)\",\n },\n KeepAliveCount: {\n key: \"go net.KeepAliveConfig Count\",\n scope: \"client\",\n unit: \"count\",\n default: 9,\n note: \"0 gives 9 (dial.go:27)\",\n },\n Timeout: {\n key: \"go http.Client Timeout\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n note: \"0 is no deadline: a reader gives it no bound\",\n },\n ResponseHeaderTimeout: {\n key: \"go http.Transport ResponseHeaderTimeout\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n note: \"0 is no deadline\",\n },\n },\n timers: {\n idle_conn: {\n duration: { knob: \"IdleConnTimeout\", unit: \"s\" },\n lateness: goTimerLateness(\"IdleConnTimeout\"),\n arms: [\"resp.done\", \"enter:IDLE\"],\n cancels: [\"req.dispatch\"],\n fires: \"timer.idle-conn\",\n note: \"time.AfterFunc(IdleConnTimeout, closeConnIfStillIdle) closes the connection late by a Go timer. The reuse is exact: queueForIdleConn compares idleAt with the wall clock\",\n },\n dial: {\n duration: { knob: \"DialTimeout\", unit: \"s\" },\n lateness: goTimerLateness(\"DialTimeout\"),\n arms: [\"enter:DIALING\"],\n cancels: [\"conn.established\"],\n fires: \"timer.dial\",\n },\n client: {\n duration: { knob: \"Timeout\", unit: \"s\" },\n lateness: goTimerLateness(\"Timeout\"),\n arms: [\"req.dispatch\", \"enter:ACTIVE\"],\n cancels: [\"resp.done\"],\n fires: \"timer.client\",\n },\n response_header: {\n duration: { knob: \"ResponseHeaderTimeout\", unit: \"s\" },\n lateness: goTimerLateness(\"ResponseHeaderTimeout\"),\n arms: [\"tx.request\", \"enter:ACTIVE\"],\n cancels: [\"rx.headers\"],\n fires: \"timer.response-header\",\n },\n },\n realizes: {\n \"systems.mechanism.pool-idle-expiry\": { timer: \"idle_conn\" },\n \"systems.mechanism.connect-bound\": { timer: \"dial\" },\n \"systems.mechanism.request-timeout\": { timer: \"client\" },\n },\n transitions: [\n {\n id: \"gt.dial\",\n from: \"ABSENT\",\n to: \"DIALING\",\n on: \"req.dispatch\",\n guard: \"no idle connection that is younger than IdleConnTimeout and not broken\",\n source: \"transport.go:1613-1616\",\n },\n { id: \"gt.connected\", from: \"DIALING\", to: \"ACTIVE\", on: \"conn.established\" },\n { id: \"gt.dial-timeout\", from: \"DIALING\", to: \"CLOSED\", on: \"timer.dial\", timer: \"dial\", errno: \"TIMEOUT\" },\n { id: \"gt.dial-refused\", from: \"DIALING\", to: \"CLOSED\", on: \"rx.rst\", errno: \"ECONNREFUSED\" },\n { id: \"gt.dial-unreachable\", from: \"DIALING\", to: \"CLOSED\", on: \"rx.icmp-hard\", errno: \"EHOSTUNREACH\" },\n {\n id: \"gt.idle\",\n from: \"ACTIVE\",\n to: \"IDLE\",\n on: \"resp.done\",\n guard: \"neither side asked for a close, and fewer than MaxIdleConnsPerHost connections are idle\",\n timer: \"idle_conn\",\n source: \"transport.go:1129-1236, :2547-2556, :2616-2627\",\n },\n {\n id: \"gt.reuse\",\n from: \"IDLE\",\n to: \"ACTIVE\",\n on: \"req.dispatch\",\n guard: \"idle for less than IdleConnTimeout by the wall clock, and not broken\",\n source: \"transport.go:1258-1303\",\n },\n {\n id: \"gt.expire\",\n from: \"IDLE\",\n to: \"CLOSED\",\n on: \"timer.idle-conn\",\n timer: \"idle_conn\",\n emits: [\"tx.fin\"],\n source: \"transport.go:2342-2352\",\n },\n {\n id: \"gt.server-closed-idle\",\n from: \"IDLE\",\n to: \"CLOSED\",\n on: [\"rx.fin\", \"read.error\"],\n emits: [\"tx.fin\"],\n source: \"transport.go:2493-2500, :2653-2672\",\n },\n {\n id: \"gt.retry\",\n from: \"ACTIVE\",\n to: \"CLOSED\",\n on: [\"rx.fin\", \"read.error\"],\n guard: \"the connection was reused, no byte of the reply came, and the request can be replayed\",\n emits: [\"req.retry\"],\n note: \"the request goes again on a new connection, and the caller sees only the second outcome\",\n source: \"transport.go:740-768, :844-889\",\n },\n {\n id: \"gt.fail\",\n from: \"ACTIVE\",\n to: \"CLOSED\",\n on: [\"rx.fin\", \"read.error\"],\n guard: \"otherwise: a new connection, or a request that it cannot replay\",\n errno: \"EOF\",\n note: \"the caller gets the read error: io.EOF, or the errno of the socket\",\n source: \"transport.go:745-760\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { DIALING: \"SYN_SENT\", ACTIVE: \"ESTABLISHED\", IDLE: \"ESTABLISHED\" },\n sets: {\n keepidle: { expr: \"ceil(KeepAlive)\", unit: \"s\" },\n keepintvl: { expr: \"ceil(KeepAliveInterval)\", unit: \"s\" },\n keepcnt: { knob: \"KeepAliveCount\", unit: \"count\" },\n },\n ends: \"read.error\",\n note: \"Go sets SO_KEEPALIVE with its own idle, interval and count on each dialed socket, rounded up to whole seconds. Thus the keepalive sysctls of the namespace do not reach it. A negative KeepAlive turns it off: a reader gives keepidle no bound.\",\n },\n} satisfies Machine);\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { NODE_TIMER_EARLY, nodeTimerLateness } from \"./timers.ts\";\n\n/**\n * This document is one socket of the `http.Agent` of Node v24.21.0, as its global agent sets it.\n * 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\n * comes from the source at the tag `v24.21.0`, with the file and the line.\n *\n * A free socket keeps its connection until the smaller of the timeout of the agent and the hint of\n * the server less a buffer. An agent without a timeout keeps it with no limit, and then the hint\n * changes nothing.\n *\n * The free socket timer arms on the event loop of the program, when the program has read the\n * whole response. The time from the last segment that the kernel received to that arm is the time\n * of the program. No source bounds it, and this document does not hold it. The race of the cells\n * adds it from a calibration (`HANDLING` in `packages/cells/src/http/race.ts`).\n */\nexport const NODE_HTTP_AGENT: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"node-http-agent\",\n title: \"One socket of the http.Agent of Node 24.21.0\",\n layer: \"driver\",\n version: \"24.21.0\",\n conditions: { node: \"24.21.0\", libuv: \"1.52.1\", agent: \"http.globalAgent, or an Agent with its options\" },\n sources: [\n {\n ref: \"node v24.21.0 lib/internal/http.js:263-265 getGlobalAgent: keepAlive true, scheduling lifo, timeout 5000\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_agent.js:172-185 (keepAliveMsecs 1000, maxFreeSockets 256, scheduling lifo, agentKeepAliveTimeoutBuffer 1000)\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_agent.js:201-265 the free event, and :633-667 keepSocketAlive: setKeepAlive(true, keepAliveMsecs), and the free socket timeout is min(timeout, hint * 1000 - agentKeepAliveTimeoutBuffer), or no reuse when that is 0 or less\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_client.js:964 and :1017-1051 responseOnEnd at the end of the response, :986-1015 responseKeepAlive and :1074-1080 emitFreeNT: the socket emits free on the next tick, on the event loop\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_agent.js:662-664: keepSocketAlive sets the timeout only when it changes. Else the timeout of the socket from its connect (:452-456, lib/net.js:257-258) counts from its last read or write (lib/net.js:738-745, lib/internal/stream_base_commons.js:164-170)\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_agent.js:101-139 freeSocketOnReadGuard: a read on a free socket, an end of file too, destroys it\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_agent.js:385-416 addRequest: a free socket by LIFO, after the destroyed ones at the head; :541-550 onTimeout destroys a free socket; :669-675 reuseSocket sets req.reusedSocket\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_client.js:712-797: an end or a close before the response is socket hang up (ECONNRESET), and a socket error goes to the request. The agent sends no request again\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/net.js:846-888 setKeepAlive (the delay in whole seconds) and src/tcp_wrap.cc:204-219 (interval 1 s and count 10 when none is given)\",\n rung: \"implemented\",\n },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n CONNECTING: {},\n BUSY: { note: \"a request owns the socket\" },\n FREE: { note: \"in the freeSockets list of the agent\" },\n CLOSED: { final: true },\n },\n events: {\n \"req.dispatch\": { kind: \"app\", note: \"agent.addRequest\" },\n \"socket.connect\": { kind: \"local\" },\n \"resp.end\": {\n kind: \"local\",\n note: \"the program read the whole response: the socket emits free on the next tick. It comes after the last segment by the handling time of the program\",\n },\n \"rx.fin\": { kind: \"peer\" },\n \"rx.rst\": { kind: \"peer\" },\n \"rx.data\": { kind: \"peer\", note: \"bytes that nothing asked for\" },\n \"timer.free-socket\": { kind: \"timer\" },\n \"socket.error\": { kind: \"local\", note: \"the kernel beneath gave up, or an ICMP error ended the socket\" },\n },\n knobs: {\n keepAlive: {\n key: \"node http.Agent keepAlive\",\n scope: \"client\",\n unit: null,\n default: 1,\n note: \"1 for the global agent; new Agent() without options has 0\",\n },\n timeout: {\n key: \"node http.Agent timeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 5000,\n note: \"5000 for the global agent; 0 is no free socket timer, and then the hint does not apply: a reader gives timeout and hint no bound\",\n },\n keepAliveMsecs: { key: \"node http.Agent keepAliveMsecs\", scope: \"client\", unit: \"ms\", default: 1000 },\n agentKeepAliveTimeoutBuffer: {\n key: \"node http.Agent agentKeepAliveTimeoutBuffer\",\n scope: \"client\",\n unit: \"ms\",\n default: 1000,\n },\n maxFreeSockets: { key: \"node http.Agent maxFreeSockets\", scope: \"client\", unit: \"count\", default: 256 },\n hint: {\n key: \"Keep-Alive timeout= of the server\",\n scope: \"connection\",\n unit: \"s\",\n default: null,\n note: \"the hint that the response gives; a response without one: a reader gives it no bound\",\n },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"the HZ of the kernel, for the step of the coarse loop clock of libuv (timers.ts)\",\n },\n },\n timers: {\n free_socket: {\n duration: { expr: \"min(timeout, hint * 1000 - agentKeepAliveTimeoutBuffer)\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"min(timeout, hint * 1000 - agentKeepAliveTimeoutBuffer)\"),\n early: NODE_TIMER_EARLY,\n arms: [\"resp.end\", \"enter:FREE\"],\n cancels: [\"req.dispatch\"],\n fires: \"timer.free-socket\",\n note: \"socket.setTimeout(agentTimeout) in keepSocketAlive: the Node timer of the socket. It arms in the free handler, or at the last read of the reply when its duration stays the same. Both come in the handling time of the program after the last segment (race.ts)\",\n },\n },\n realizes: {\n \"systems.mechanism.pool-idle-expiry\": { timer: \"free_socket\" },\n },\n transitions: [\n { id: \"na.connect\", from: \"ABSENT\", to: \"CONNECTING\", on: \"req.dispatch\", guard: \"no free socket\" },\n { id: \"na.connected\", from: \"CONNECTING\", to: \"BUSY\", on: \"socket.connect\" },\n {\n id: \"na.free\",\n from: \"BUSY\",\n to: \"FREE\",\n on: \"resp.end\",\n guard: \"keepAlive, the response keeps the connection, and hint * 1000 - agentKeepAliveTimeoutBuffer > 0\",\n timer: \"free_socket\",\n source: \"lib/_http_agent.js:237-264, :633-667\",\n },\n {\n id: \"na.no-reuse\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: \"resp.end\",\n guard: \"hint * 1000 - agentKeepAliveTimeoutBuffer is 0 or less, or the response closes the connection\",\n emits: [\"tx.fin\"],\n source: \"lib/_http_agent.js:238-254, :649-654\",\n },\n {\n id: \"na.reuse\",\n from: \"FREE\",\n to: \"BUSY\",\n on: \"req.dispatch\",\n guard: \"the socket is not destroyed\",\n source: \"lib/_http_agent.js:385-416\",\n },\n {\n id: \"na.expire\",\n from: \"FREE\",\n to: \"CLOSED\",\n on: \"timer.free-socket\",\n timer: \"free_socket\",\n emits: [\"tx.fin\"],\n source: \"lib/_http_agent.js:541-550\",\n },\n {\n id: \"na.peer-closed\",\n from: \"FREE\",\n to: \"CLOSED\",\n on: [\"rx.fin\", \"rx.rst\", \"rx.data\", \"socket.error\"],\n source: \"lib/_http_agent.js:94-112\",\n },\n {\n id: \"na.hang-up\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: \"rx.fin\",\n errno: \"ECONNRESET\",\n note: \"socket hang up, an error with the code ECONNRESET\",\n source: \"lib/_http_client.js:781-797\",\n },\n {\n id: \"na.reset\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: [\"rx.rst\", \"socket.error\"],\n errno: \"ECONNRESET\",\n note: \"the errno of the socket: ECONNRESET for a reset, ETIMEDOUT or the soft ICMP errno for a give-up\",\n source: \"lib/_http_client.js:757-779\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { CONNECTING: \"SYN_SENT\", BUSY: \"ESTABLISHED\", FREE: \"ESTABLISHED\" },\n sets: {\n keepidle: { expr: \"floor(keepAliveMsecs / 1000)\", unit: \"s\" },\n keepintvl: { const: 1, unit: \"s\" },\n keepcnt: { const: 10, unit: \"count\" },\n },\n ends: \"socket.error\",\n note: \"The agent turns keepalive on at the connect (lib/_http_agent.js:474-478, lib/net.js:1991-1994) and again on each free socket. Node passes the delay in whole seconds and libuv sets 1 s and 10 probes. Thus the keepalive sysctls of the namespace do not reach it.\",\n },\n} satisfies Machine);\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { NODE_TIMER_EARLY, nodeTimerLateness } from \"./timers.ts\";\n\n/**\n * This document is one connection as the `http.Server` of Node v24.21.0 holds it, over the Linux\n * TCP socket of the connection. Each fact comes from the source at the tag `v24.21.0`. The comments\n * give the file and the line.\n *\n * The keep-alive timer is the S of the keep-alive race. It arms when the response ends, not when\n * the request starts. It is a socket timeout on the timers of libuv, thus it has the lateness of a\n * Node timer (`timers.ts`). When it fires, the server closes the socket. The kernel sends a FIN, or\n * a reset when the receive queue has data that nothing read.\n */\nexport const NODE_HTTP_SERVER: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"node-http-server\",\n title: \"One connection as the http.Server of Node 24.21.0 holds it\",\n layer: \"server\",\n version: \"24.21.0\",\n conditions: { node: \"24.21.0\", libuv: \"1.52.1\", kernel: \"Linux 6.6\" },\n sources: [\n {\n ref: \"node v24.21.0 lib/_http_server.js:537-579 (requestTimeout 300000, headersTimeout min(60000, requestTimeout), keepAliveTimeout 5000, keepAliveTimeoutBuffer 1000, connectionsCheckingInterval 30000), :665-667 (timeout 0, maxRequestsPerSocket 0)\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_server.js:1096-1150 resOnFinish: the keep-alive timer arms when the response finishes, at keepAliveTimeout + keepAliveTimeoutBuffer\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_server.js:1167-1168 and :1299-1305 parserOnIncoming and resetSocketTimeout: the headers of the next request disarm it\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_server.js:963-968 onParserExecute and lib/net.js:738-745 _unrefTimer: each read refreshes the socket timeout\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_server.js:900-909 socketOnTimeout: without a timeout listener, the socket is destroyed; lib/net.js:1097-1131 _destroy closes the handle\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_outgoing.js:514-527: Keep-Alive: timeout=floor(keepAliveTimeout / 1000), with max= when maxRequestsPerSocket is set, and Connection: close on the last allowed response\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_server.js:616-624 and :743-764 checkConnections: the headers and request timeouts are a sweep each connectionsCheckingInterval; src/node_http_parser.cc:310-330, :1223-1284 (a connection counts from the start of its message, and leaves the list when the message is complete)\",\n rung: \"implemented\",\n },\n {\n ref: \"linux v6.6 net/ipv4/tcp.c:2771-2797 __tcp_close: unread data in the receive queue makes the close a reset (RFC 2525 2.17), else :2802-2832 a FIN\",\n rung: \"implemented\",\n },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n WAITING: { note: \"accepted, and no byte of a request yet: the headers timeout counts from the accept\" },\n READING: { note: \"a request has started and its headers or its body are not complete\" },\n HANDLING: { note: \"the request is complete and its response is not finished, for example a held reply\" },\n IDLE: { note: \"a response finished and the keep-alive timer is armed\" },\n CLOSED: { final: true },\n },\n events: {\n accept: { kind: \"local\" },\n \"rx.message-begin\": { kind: \"rx\", note: \"the first byte of a request (llhttp on_message_begin)\" },\n \"rx.request\": { kind: \"rx\", note: \"the headers of a request are complete: parserOnIncoming\" },\n \"rx.message-complete\": { kind: \"rx\", note: \"the whole request arrived, its body too\" },\n \"rx.data\": { kind: \"rx\", note: \"bytes arrive on the socket: each read refreshes the socket timeout\" },\n \"res.finish\": { kind: \"local\", note: \"the last byte of a response went to the kernel\" },\n \"rx.fin\": { kind: \"peer\", note: \"the client closed: socketOnEnd ends the socket, because httpAllowHalfOpen is false\" },\n \"rx.rst\": { kind: \"peer\" },\n \"timer.keep-alive\": { kind: \"timer\" },\n \"timer.headers\": { kind: \"timer\" },\n \"timer.request\": { kind: \"timer\" },\n \"timer.socket\": { kind: \"timer\" },\n \"socket.error\": { kind: \"local\", note: \"the kernel beneath gave up on the socket, or a reset arrived\" },\n },\n knobs: {\n keepAliveTimeout: {\n key: \"node http.Server keepAliveTimeout\",\n scope: \"server\",\n unit: \"ms\",\n default: 5000, off: 0,\n note: \"0 disables the keep-alive timer and the hint: a reader gives the timer no bound\",\n },\n keepAliveTimeoutBuffer: {\n key: \"node http.Server keepAliveTimeoutBuffer\",\n scope: \"server\",\n unit: \"ms\",\n default: 1000,\n note: \"added to the timer, not to the hint (lib/_http_server.js:1136-1141)\",\n },\n headersTimeout: { key: \"node http.Server headersTimeout\", scope: \"server\", unit: \"ms\", default: 60000 },\n requestTimeout: { key: \"node http.Server requestTimeout\", scope: \"server\", unit: \"ms\", default: 300000 },\n connectionsCheckingInterval: {\n key: \"node http.Server connectionsCheckingInterval\",\n scope: \"server\",\n unit: \"ms\",\n default: 30000,\n },\n timeout: {\n key: \"node http.Server timeout\",\n scope: \"server\",\n unit: \"ms\",\n default: 0, off: 0,\n note: \"the socket timeout while a request is open (lib/_http_server.js:1303); 0 is off\",\n },\n maxRequestsPerSocket: {\n key: \"node http.Server maxRequestsPerSocket\",\n scope: \"server\",\n unit: \"count\",\n default: 0,\n note: \"0 is no limit; at the limit the response says Connection: close, and a request above it gets 503 (lib/_http_server.js:1255-1271)\",\n },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"the HZ of the kernel: at 1000, libuv reads the coarse clock, a jiffy a step, and each Node timer gets that step on each bound (timers.ts)\",\n },\n },\n timers: {\n keep_alive: {\n duration: { expr: \"keepAliveTimeout + keepAliveTimeoutBuffer\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"keepAliveTimeout + keepAliveTimeoutBuffer\"),\n early: NODE_TIMER_EARLY,\n arms: [\"res.finish\", \"rx.data\", \"enter:IDLE\"],\n cancels: [\"rx.request\"],\n fires: \"timer.keep-alive\",\n note: \"socket.setTimeout(keepAliveTimeout + keepAliveTimeoutBuffer) in resOnFinish; a read refreshes it, and the headers of the next request reset it to the server timeout\",\n },\n headers: {\n duration: { knob: \"headersTimeout\", unit: \"ms\" },\n lateness: {\n expr: \"connectionsCheckingInterval + min(max(connectionsCheckingInterval / 1000, 0.05), 100) + 1\",\n unit: \"ms\",\n },\n arms: [\"accept\", \"rx.message-begin\", \"enter:WAITING\", \"enter:READING\"],\n cancels: [\"rx.request\"],\n fires: \"timer.headers\",\n note: \"a sweep each connectionsCheckingInterval finds the expired connections by uv_hrtime, thus the 408 comes in [T, T + interval], late by the interval timer\",\n },\n request: {\n duration: { knob: \"requestTimeout\", unit: \"ms\" },\n lateness: {\n expr: \"connectionsCheckingInterval + min(max(connectionsCheckingInterval / 1000, 0.05), 100) + 1\",\n unit: \"ms\",\n },\n arms: [\"accept\", \"rx.message-begin\", \"enter:READING\"],\n cancels: [\"rx.message-complete\"],\n fires: \"timer.request\",\n },\n socket: {\n duration: { knob: \"timeout\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"timeout\"),\n early: NODE_TIMER_EARLY,\n arms: [\"rx.request\", \"enter:HANDLING\"],\n cancels: [\"res.finish\"],\n fires: \"timer.socket\",\n note: \"off at its default: a reader gives 0 as no bound\",\n },\n },\n realizes: {\n \"systems.mechanism.server-idle-close\": { timer: \"keep_alive\" },\n },\n transitions: [\n { id: \"ns.accept\", from: \"ABSENT\", to: \"WAITING\", on: \"accept\" },\n {\n id: \"ns.begin\",\n from: [\"WAITING\", \"IDLE\"],\n to: \"READING\",\n on: \"rx.message-begin\",\n source: \"src/node_http_parser.cc:310-330\",\n },\n {\n id: \"ns.request\",\n from: \"READING\",\n to: \"HANDLING\",\n on: [\"rx.request\", \"rx.message-complete\"],\n source: \"lib/_http_server.js:1167-1168, :1299-1305\",\n },\n {\n id: \"ns.respond\",\n from: \"HANDLING\",\n to: \"IDLE\",\n on: \"res.finish\",\n guard: \"keepAliveTimeout > 0, and the response is not the last one (Connection: close or maxRequestsPerSocket)\",\n timer: \"keep_alive\",\n source: \"lib/_http_server.js:1130-1142\",\n },\n {\n id: \"ns.last\",\n from: \"HANDLING\",\n to: \"CLOSED\",\n on: \"res.finish\",\n guard: \"the response is the last one: destroySoon ends the socket after it\",\n emits: [\"tx.fin\"],\n source: \"lib/_http_server.js:1124-1129\",\n },\n {\n id: \"ns.keep-alive\",\n from: \"IDLE\",\n to: \"CLOSED\",\n on: \"timer.keep-alive\",\n timer: \"keep_alive\",\n emits: [\"tx.fin\"],\n note: \"a reset in place of the FIN when the receive queue holds data that nothing read (net/ipv4/tcp.c:2793-2797)\",\n source: \"lib/_http_server.js:900-909\",\n },\n {\n id: \"ns.headers-timeout\",\n from: [\"WAITING\", \"READING\"],\n to: \"CLOSED\",\n on: \"timer.headers\",\n timer: \"headers\",\n emits: [\"tx.408\", \"tx.fin\"],\n source: \"lib/_http_server.js:743-764, :958-961\",\n },\n {\n id: \"ns.request-timeout\",\n from: \"READING\",\n to: \"CLOSED\",\n on: \"timer.request\",\n timer: \"request\",\n emits: [\"tx.408\", \"tx.fin\"],\n source: \"lib/_http_server.js:743-764\",\n },\n {\n id: \"ns.peer-end\",\n from: [\"WAITING\", \"READING\", \"HANDLING\", \"IDLE\"],\n to: \"CLOSED\",\n on: \"rx.fin\",\n emits: [\"tx.fin\"],\n source: \"lib/_http_server.js:932-948\",\n },\n { id: \"ns.error\", from: [\"WAITING\", \"READING\", \"HANDLING\", \"IDLE\"], to: \"CLOSED\", on: [\"rx.rst\", \"socket.error\"] },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { WAITING: \"ESTABLISHED\", READING: \"ESTABLISHED\", HANDLING: \"ESTABLISHED\", IDLE: \"ESTABLISHED\" },\n sets: {},\n ends: \"socket.error\",\n note: \"http.Server passes keepAlive to net.Server, and its default is off (lib/_http_server.js:646-651, lib/net.js:2753-2756). Thus an accepted socket has no SO_KEEPALIVE, and a reader gives the keepalive of the kernel no bound.\",\n },\n} satisfies Machine);\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { NODE_TIMER_EARLY, nodeTimerLateness, undiciFastEarly, undiciFastLateness } from \"./timers.ts\";\n\n/**\n * This document is the socket of an HTTP/1.1 `Client` of undici 8.12.2, over its Linux TCP socket.\n * Each fact comes from the published package at 8.12.2, with the file and the line.\n *\n * The keep-alive timeout comes from the hint of the server less a threshold, capped by a maximum.\n * The headers and body timeouts use the fast timers of undici, which count in ticks of 499 ms. The\n * client sends no request again by itself. A request that it did not write yet goes on the next\n * connection.\n *\n * The keep-alive timer arms on the event loop of the program, in the check phase after the parse\n * of the reply. The time from the last segment that the kernel received to that arm is the time of\n * the program. No source bounds it, and this document does not hold it. The race of the cells adds\n * it from a calibration (`HANDLING` in `packages/cells/src/http/race.ts`).\n */\nexport const UNDICI_CLIENT: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"undici-client-h1\",\n title: \"The socket of an HTTP/1.1 Client of undici 8.12.2\",\n layer: \"driver\",\n version: \"8.12.2\",\n conditions: { undici: \"8.12.2\", node: \"24.21.0\", pipelining: \"1\" },\n sources: [\n {\n ref: \"undici 8.12.2 lib/dispatcher/client.js:309-319 (keepAliveTimeout 4000, keepAliveMaxTimeout 600000, keepAliveTimeoutThreshold 2000, bodyTimeout and headersTimeout 300000)\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/dispatcher/client-h1.js:705-721 onHeadersComplete: the timeout is min(hint - threshold, maximum), no reuse when it is 0 or less, and keepAliveTimeout without a hint; lib/core/util.js:390-398 (the hint in ms)\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/dispatcher/client-h1.js:213-223 and :262-288: a native Node timer for keep-alive, the fast timers for the headers and the body\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/dispatcher/client-h1.js:785-852 onMessageComplete: a reply that ends the connection destroys the socket in the parse (:827-841), else one setImmediate (:842-846). Then lib/dispatcher/client.js:646-676 and client-h1.js:1111-1163 resumeH1 arm the keep-alive timer (:1151-1154). After the write of a request, the headers timer\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/dispatcher/client-h1.js:1087-1106 and :1125-1141: before a request on a used idle socket, the client yields to the check phase, thus a FIN or a reset already received closes the socket first\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/dispatcher/client-h1.js:855-876 onParserTimeout, :990-1007 onHttpSocketError, :1013-1025 onHttpSocketEnd (other side closed) and :1027-1072 onHttpSocketClose (the request at the head fails, the others wait for the next connection)\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/util/timers.js:30-207 the fast timers: a tick each 499 ms, a clock that adds 499 at each tick\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/core/connect.js:68-75 and :141-149 (connect timeout 10000, setKeepAlive(true, 60000), setNoDelay)\",\n rung: \"implemented\",\n },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n CONNECTING: {},\n BUSY: { note: \"a request is written and its reply is not complete\" },\n IDLE: { note: \"a reply is complete and the keep-alive timer is armed\" },\n CLOSED: { final: true },\n },\n events: {\n \"req.dispatch\": { kind: \"app\" },\n \"socket.connect\": { kind: \"local\" },\n \"tx.request\": { kind: \"tx\", note: \"the client wrote the request and resumes\" },\n \"rx.headers\": { kind: \"rx\" },\n \"rx.body\": { kind: \"rx\", note: \"a chunk of the body: it refreshes the body timer\" },\n \"resp.complete\": {\n kind: \"local\",\n note: \"onMessageComplete, in the parse of the reply on the event loop. It comes after the last segment by the handling time of the program\",\n },\n \"rx.fin\": { kind: \"peer\" },\n \"rx.rst\": { kind: \"peer\" },\n \"timer.keep-alive\": { kind: \"timer\" },\n \"timer.headers\": { kind: \"timer\" },\n \"timer.body\": { kind: \"timer\" },\n \"timer.connect\": { kind: \"timer\" },\n \"socket.error\": { kind: \"local\" },\n },\n knobs: {\n keepAliveTimeout: { key: \"undici Client keepAliveTimeout\", scope: \"client\", unit: \"ms\", default: 4000 },\n keepAliveMaxTimeout: { key: \"undici Client keepAliveMaxTimeout\", scope: \"client\", unit: \"ms\", default: 600000 },\n keepAliveTimeoutThreshold: {\n key: \"undici Client keepAliveTimeoutThreshold\",\n scope: \"client\",\n unit: \"ms\",\n default: 2000,\n },\n headersTimeout: { key: \"undici Client headersTimeout\", scope: \"client\", unit: \"ms\", default: 300000 },\n bodyTimeout: { key: \"undici Client bodyTimeout\", scope: \"client\", unit: \"ms\", default: 300000 },\n connectTimeout: { key: \"undici Client connect.timeout\", scope: \"client\", unit: \"ms\", default: 10000 },\n keepAliveInitialDelay: {\n key: \"undici Client connect.keepAliveInitialDelay\",\n scope: \"client\",\n unit: \"ms\",\n default: 60000,\n },\n hint: {\n key: \"Keep-Alive timeout= of the server\",\n scope: \"connection\",\n unit: \"s\",\n default: null,\n note: \"without a hint, the timeout is keepAliveTimeout\",\n },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"the HZ of the kernel, for the step of the coarse loop clock of libuv (timers.ts)\",\n },\n },\n timers: {\n keep_alive: {\n duration: { expr: \"min(hint * 1000 - keepAliveTimeoutThreshold, keepAliveMaxTimeout)\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"min(hint * 1000 - keepAliveTimeoutThreshold, keepAliveMaxTimeout)\"),\n early: NODE_TIMER_EARLY,\n arms: [\"resp.complete\", \"enter:IDLE\"],\n cancels: [\"req.dispatch\"],\n fires: \"timer.keep-alive\",\n note: \"setTimeout(onParserTimeout, delay) with unref: a native Node timer. It arms in resumeH1, in the check phase after the parse of the reply. That comes in the handling time of the program after the last segment (race.ts)\",\n },\n headers: {\n duration: { knob: \"headersTimeout\", unit: \"ms\" },\n lateness: undiciFastLateness(\"headersTimeout\"),\n early: undiciFastEarly(\"headersTimeout\"),\n arms: [\"tx.request\", \"enter:BUSY\"],\n cancels: [\"rx.headers\"],\n fires: \"timer.headers\",\n },\n body: {\n duration: { knob: \"bodyTimeout\", unit: \"ms\" },\n lateness: undiciFastLateness(\"bodyTimeout\"),\n early: undiciFastEarly(\"bodyTimeout\"),\n arms: [\"rx.headers\", \"rx.body\"],\n cancels: [\"resp.complete\"],\n fires: \"timer.body\",\n },\n connect: {\n duration: { knob: \"connectTimeout\", unit: \"ms\" },\n arms: [\"enter:CONNECTING\"],\n cancels: [\"socket.connect\"],\n fires: \"timer.connect\",\n },\n },\n realizes: {\n \"systems.mechanism.pool-idle-expiry\": { timer: \"keep_alive\" },\n \"systems.mechanism.request-timeout\": { timer: \"headers\" },\n \"systems.mechanism.connect-bound\": { timer: \"connect\" },\n },\n transitions: [\n { id: \"un.connect\", from: \"ABSENT\", to: \"CONNECTING\", on: \"req.dispatch\" },\n { id: \"un.connected\", from: \"CONNECTING\", to: \"BUSY\", on: \"socket.connect\" },\n {\n id: \"un.idle\",\n from: \"BUSY\",\n to: \"IDLE\",\n on: \"resp.complete\",\n guard: \"the reply keeps the connection, and min(hint - threshold, maximum) > 0\",\n timer: \"keep_alive\",\n source: \"client-h1.js:705-717, :842-846\",\n },\n {\n id: \"un.no-reuse\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: \"resp.complete\",\n guard: \"hint * 1000 - keepAliveTimeoutThreshold is 0 or less, or the reply closes the connection\",\n emits: [\"tx.fin\"],\n source: \"client-h1.js:709-711, :832-841\",\n },\n {\n id: \"un.reuse\",\n from: \"IDLE\",\n to: \"BUSY\",\n on: \"req.dispatch\",\n guard: \"the socket is still open after the yield to the check phase\",\n source: \"client-h1.js:1087-1106, :1125-1141\",\n },\n {\n id: \"un.expire\",\n from: \"IDLE\",\n to: \"CLOSED\",\n on: \"timer.keep-alive\",\n timer: \"keep_alive\",\n emits: [\"tx.fin\"],\n source: \"client-h1.js:872-875\",\n },\n {\n id: \"un.peer-closed\",\n from: \"IDLE\",\n to: \"CLOSED\",\n on: [\"rx.fin\", \"rx.rst\", \"socket.error\"],\n note: \"no request fails: the next request opens a new connection\",\n source: \"client-h1.js:1013-1025, :1065\",\n },\n {\n id: \"un.other-side-closed\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: \"rx.fin\",\n errno: \"UND_ERR_SOCKET\",\n note: \"SocketError: other side closed. The request at the head fails\",\n source: \"client-h1.js:1013-1025, :1057-1063\",\n },\n {\n id: \"un.reset\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: [\"rx.rst\", \"socket.error\"],\n errno: \"ECONNRESET\",\n note: \"the error of the socket, with its own code\",\n source: \"client-h1.js:990-1007, :1057-1063\",\n },\n {\n id: \"un.headers-timeout\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: \"timer.headers\",\n timer: \"headers\",\n errno: \"UND_ERR_HEADERS_TIMEOUT\",\n source: \"client-h1.js:863-867\",\n },\n {\n id: \"un.body-timeout\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: \"timer.body\",\n timer: \"body\",\n errno: \"UND_ERR_BODY_TIMEOUT\",\n source: \"client-h1.js:868-871\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { CONNECTING: \"SYN_SENT\", BUSY: \"ESTABLISHED\", IDLE: \"ESTABLISHED\" },\n sets: {\n keepidle: { expr: \"floor(keepAliveInitialDelay / 1000)\", unit: \"s\" },\n keepintvl: { const: 1, unit: \"s\" },\n keepcnt: { const: 10, unit: \"count\" },\n },\n ends: \"socket.error\",\n note: \"The connector turns keepalive on with a delay of 60 s, and Node and libuv add 1 s and 10 probes (src/tcp_wrap.cc:215-216). Thus the keepalive sysctls of the namespace do not reach it.\",\n },\n} satisfies Machine);\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the built code of ioredis 6.0.0 as npm has it, under built/.\n// Each line number is a line of that file in the package.\nconst AT = \"ioredis 6.0.0 built\";\n\n/**\n * This document is the Sentinel path of ioredis 6.0.0. It tells how ioredis finds the primary of a\n * group through the Sentinels, loses it, and connects to the new one. The standalone states of\n * `ioredis-status` stay, and a connect asks a Sentinel first. The driver has no timer that watches\n * the group: it moves only when its own connection closes. The failover detector, which\n * subscribes to `+switch-master`, is off by default.\n */\nexport const IOREDIS_SENTINEL: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"ioredis-sentinel\",\n title: \"ioredis 6.0.0 in Sentinel mode: the primary of a group, found through its Sentinels\",\n layer: \"driver\",\n version: \"6.0.0\",\n conditions: { ioredis: \"6.0.0\", mode: \"sentinel\", node: \"24.21.0\" },\n sources: [\n { ref: `${AT}/connectors/SentinelConnector/index.js:46-121 connect (each Sentinel in turn, then sentinelRetryStrategy)`, rung: \"implemented\" },\n { ref: `${AT}/connectors/SentinelConnector/index.js:145-151 resolveMaster (get-master-addr-by-name, then SENTINEL sentinels)`, rung: \"implemented\" },\n { ref: `${AT}/connectors/SentinelConnector/index.js:175-212 connectToSentinel and resolve (one connection for each question, no retry)`, rung: \"implemented\" },\n { ref: `${AT}/connectors/SentinelConnector/index.js:27-39 check (the role of the ready check)`, rung: \"implemented\" },\n { ref: `${AT}/connectors/SentinelConnector/FailoverDetector.js:6-43 (+switch-master, only with failoverDetector)`, rung: \"implemented\" },\n { ref: `${AT}/redis/RedisOptions.js:9-57 (the defaults)`, rung: \"implemented\" },\n { ref: `${AT}/redis/event_handler.js:294-355 closeHandler (retryStrategy, then maxRetriesPerRequest flushes the queue)`, rung: \"implemented\" },\n { ref: `${AT}/redis/event_handler.js:364-449 readyHandler (retryAttempts back to 0, the resend, the offline queue)`, rung: \"implemented\" },\n { ref: `${AT}/Redis.js:123-240 _connect (connectTimeout, keepAlive) and :379-405 sendCommand (the offline queue)`, rung: \"implemented\" },\n { ref: `${AT}/Redis.js:599-605 handleReconnection (reconnectOnError: null, thus a READONLY error goes to the caller)`, rung: \"implemented\" },\n ],\n states: {\n \"[empty]\": { initial: true, pseudo: true },\n resolving: { note: \"a connect: one Sentinel after another, get-master-addr-by-name (SentinelConnector/index.js:50-119)\" },\n connecting: { note: \"the TCP connect to the primary that the Sentinel named\" },\n connect: { note: \"the handshake: HELLO 3, CLIENT SETINFO, then the INFO of the ready check, whose role must be master\" },\n ready: { note: \"writes go to the primary\" },\n close: { note: \"the connection closed: closeHandler (event_handler.js:294-350)\" },\n reconnecting: { note: \"the wait of retryStrategy before the next connect\" },\n end: { final: true },\n },\n events: {\n \"app.connect\": { kind: \"app\" },\n \"sentinel.answer\": { kind: \"local\", note: \"a Sentinel named a primary\" },\n \"sentinel.none\": { kind: \"local\", note: \"no Sentinel answered: sentinelRetryStrategy (SentinelConnector/index.js:51-73)\" },\n \"stream.connect\": { kind: \"local\" },\n \"stream.close\": { kind: \"local\", note: \"a FIN, a reset, a refused connect, a CLIENT KILL, or the connect timeout\" },\n \"handshake.ready\": { kind: \"local\", note: \"the ready check says role:master (event_handler.js:194-210)\" },\n \"handshake.role\": { kind: \"local\", note: \"the ready check says another role: disconnect and connect again (SentinelConnector/index.js:27-39)\" },\n \"timer.retry\": { kind: \"timer\" },\n \"timer.sentinel-retry\": { kind: \"timer\" },\n \"timer.connect-timeout\": { kind: \"timer\" },\n \"local.flush\": { kind: \"local\", note: \"MaxRetriesPerRequestError for each queued command (event_handler.js:337-349)\" },\n \"rx.switch-master\": { kind: \"rx\", note: \"a message on +switch-master: only with failoverDetector (FailoverDetector.js:28-32)\" },\n },\n knobs: {\n connectTimeout: { key: \"ioredis connectTimeout\", scope: \"client\", unit: \"ms\", default: 10000, note: \"RedisOptions.js:9\" },\n disconnectTimeout: { key: \"ioredis disconnectTimeout\", scope: \"client\", unit: \"ms\", default: 2000, note: \"RedisOptions.js:10\" },\n keepAlive: { key: \"ioredis keepAlive\", scope: \"client\", unit: \"ms\", default: 30000, note: \"RedisOptions.js:17: setKeepAlive on the socket of the primary\" },\n maxRetriesPerRequest: {\n key: \"ioredis maxRetriesPerRequest\",\n scope: \"client\",\n unit: \"count\",\n default: 20,\n note: \"RedisOptions.js:57: the queue goes at each close whose count since ready is a multiple of maxRetriesPerRequest + 1\",\n },\n sentinel_retry_step: { key: \"ioredis sentinelRetryStrategy\", scope: \"client\", unit: \"ms\", default: 10, note: \"RedisOptions.js:26-28: min(times × 10, 1000) ms\" },\n sentinel_retry_cap: { key: \"ioredis sentinelRetryStrategy\", scope: \"client\", unit: \"ms\", default: 1000 },\n sentinelReconnect: { key: \"ioredis sentinelReconnectStrategy\", scope: \"client\", unit: \"ms\", default: 60000, note: \"RedisOptions.js:29-35: the detector's own links only\" },\n failoverDetector: { key: \"ioredis failoverDetector\", scope: \"client\", unit: null, default: 0, note: \"RedisOptions.js:40: off\" },\n commandTimeout: { key: \"ioredis commandTimeout\", scope: \"client\", unit: \"ms\", default: null, note: \"unset: a command waits without a limit (Redis.js:368)\" },\n attempt_round_trips: {\n key: \"the round trips of one connect that fails\",\n scope: \"path\",\n unit: \"count\",\n default: 5,\n note: \"a connect to the Sentinel, HELLO with CLIENT SETINFO, get-master-addr-by-name, SENTINEL sentinels, then the connect to the primary\",\n },\n success_round_trips: {\n key: \"the round trips of a connect that succeeds, to its first accepted write\",\n scope: \"path\",\n unit: \"count\",\n default: 9,\n note: \"the five of a failed connect, then HELLO, the INFO of the ready check, and the write itself\",\n },\n rtt: { key: \"the round trip of the network of the group\", scope: \"path\", unit: \"ms\", default: null },\n slack: {\n key: \"the lateness of the event loop of Node for one step\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"an assumption of this document, not a value of ioredis: a timer or a callback of Node that comes late\",\n },\n },\n timers: {\n retry_delay: {\n // min(2 ** (times - 1) × 50, 5000) + floor(random × 200), times = ++retryAttempts (RedisOptions.js:11-16, event_handler.js:326)\n duration: { model: \"ioredis.retry-base\", knobs: [\"fired\"], unit: \"s\" },\n lateness: { expr: \"199 + slack\", unit: \"ms\" },\n arms: [\"stream.close\"],\n fires: \"timer.retry\",\n backoff: { resets: [\"handshake.ready\"] },\n note: \"fired counts the closes since the last ready, from 0: the readyHandler sets retryAttempts to 0 (event_handler.js:367)\",\n },\n attempt: {\n // one connect that fails: each question to a Sentinel is a new connection (SentinelConnector/index.js:197-212)\n duration: { expr: \"attempt_round_trips * rtt\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"timer.retry\"],\n fires: \"stream.close\",\n },\n success: {\n duration: { expr: \"success_round_trips * rtt\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"timer.retry\"],\n fires: \"handshake.ready\",\n },\n connect_timeout: {\n duration: { knob: \"connectTimeout\", unit: \"ms\" },\n arms: [\"enter:connecting\"],\n cancels: [\"stream.connect\"],\n fires: \"timer.connect-timeout\",\n note: \"a connect into a black hole: the socket goes, then stream.close (Redis.js:179-201)\",\n },\n sentinel_retry: {\n duration: { expr: \"min(sentinel_retry_step * (fired + 1), sentinel_retry_cap)\", unit: \"ms\" },\n arms: [\"sentinel.none\"],\n fires: \"timer.sentinel-retry\",\n backoff: { resets: [\"sentinel.answer\"] },\n note: \"only when no Sentinel answers\",\n },\n },\n transitions: [\n { id: \"connect\", from: [\"[empty]\", \"end\"], to: \"resolving\", on: \"app.connect\" },\n { id: \"resolved\", from: \"resolving\", to: \"connecting\", on: \"sentinel.answer\", note: \"the first Sentinel of the list that answers; it moves to the head (SentinelIterator.js)\" },\n { id: \"no-sentinel\", from: \"resolving\", to: \"resolving\", on: \"timer.sentinel-retry\", timer: \"sentinel_retry\" },\n { id: \"socket-up\", from: \"connecting\", to: \"connect\", on: \"stream.connect\" },\n { id: \"attempt-failed\", from: [\"connecting\", \"connect\"], to: \"close\", on: [\"stream.close\", \"timer.connect-timeout\"] },\n { id: \"ready\", from: \"connect\", to: \"ready\", on: \"handshake.ready\" },\n { id: \"wrong-role\", from: \"connect\", to: \"close\", on: \"handshake.role\" },\n { id: \"lost\", from: \"ready\", to: \"close\", on: \"stream.close\", note: \"the commands in flight wait for the resend (event_handler.js:309-316)\" },\n { id: \"detected\", from: \"ready\", to: \"close\", on: \"rx.switch-master\", note: \"only with failoverDetector\" },\n { id: \"retry\", from: \"close\", to: \"reconnecting\", on: \"local.flush\", note: \"a close whose count is a multiple of maxRetriesPerRequest + 1 fails the queue first\" },\n { id: \"wait\", from: \"close\", to: \"reconnecting\", on: \"stream.close\" },\n { id: \"reconnect\", from: \"reconnecting\", to: \"resolving\", on: \"timer.retry\", timer: \"retry_delay\" },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { connecting: \"SYN_SENT\", connect: \"ESTABLISHED\", ready: \"ESTABLISHED\" },\n sets: { keepidle: { expr: \"floor(keepAlive / 1000)\", unit: \"s\" } },\n ends: \"stream.close\",\n note: \"the socket of the primary is a Linux TCP socket with keepalive at keepAlive. A write in flight to a black hole waits for the retransmissions of the kernel\",\n },\n});\n","","","","","","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { z } from \"zod\";\nimport ioredisStatus from \"./ioredis-status.json\" with { type: \"json\" };\nimport linuxTcp from \"./linux-tcp.json\" with { type: \"json\" };\nimport manifestations from \"./manifestations.json\" with { type: \"json\" };\nimport nfConntrackTcp from \"./nf-conntrack-tcp.json\" with { type: \"json\" };\nimport redisClient from \"./redis-client.json\" with { type: \"json\" };\n\n// The documents of the kernel, of Redis and of ioredis are JSON files. The schema of the algebra\n// examines each one at load, and a document that it refuses stops the import.\n\n/** This document is TCP as Linux 6.6 implements it: one full socket, from the source of the kernel and the RFCs. */\nexport const LINUX_TCP: Machine = machineSchema.parse(linuxTcp);\n\n/** 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. */\nexport const NF_CONNTRACK_TCP: Machine = machineSchema.parse(nfConntrackTcp);\n\n/** This document is one client connection as the Redis 8.10.2 server holds it, over its Linux TCP socket. */\nexport const REDIS_CLIENT: Machine = machineSchema.parse(redisClient);\n\n/** This document is the status of one standalone connection of ioredis 6.0.0, over its Linux TCP socket. */\nexport const IOREDIS_STATUS: Machine = machineSchema.parse(ioredisStatus);\n\n/**\n * This map gives, for each manifestation of a failure, the incoming events that continue to arrive\n * at Linux TCP while the failure lasts. A black hole lets nothing through. The kernel of a frozen\n * process continues to send ACKs, thus `rx.ack` arrives.\n */\nexport const MANIFESTATIONS: Readonly<Record<string, readonly string[]>> = z\n .record(z.string(), z.array(z.string()))\n .parse(manifestations);\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is src/mongo/db/repl of MongoDB at the tag r9.0.4, unless a line\n// names another folder. Each line number is a line of that file at that tag.\nconst AT = \"mongodb r9.0.4 src/mongo/db/repl\";\n\n/**\n * This document is the replication of mongod 9.0.4. It gives one member of a replica set, its view\n * of the primary, and the election that it can hold. The states are the states of the member. The\n * timers are the heartbeats, the election timeout, the liveness check of a primary, the vote, the\n * catch-up of a new primary and a step-down.\n *\n * Each member sends a heartbeat to each other member. A heartbeat window is 10 s: in it, a failed\n * request goes again at once, two times at most. A window without a response marks the target\n * DOWN. A secondary starts an election when it hears nothing from the primary for the election\n * timeout and a random offset. A primary steps down when it cannot see a majority for the election\n * timeout.\n *\n * A secondary keeps a silent primary as its sync source until its oplog fetcher gives up. That is\n * two timeouts and a restart: 17 s to 18 s at the defaults. Its reporter keeps a\n * replSetUpdatePosition in flight to that primary for 30 s. Until then, a new primary learns the\n * position of that secondary only from the response to each heartbeat.\n */\nexport const MONGOD_REPL: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"mongod-replication\",\n title: \"mongod 9.0.4 replication: one member of a replica set, its heartbeats, its elections and its step-downs\",\n layer: \"server\",\n version: \"9.0.4\",\n conditions: { mongodb: \"9.0.4\", protocol: \"replication protocol version 1\", members: \"three members, each with one vote and priority 1\" },\n sources: [\n { ref: `${AT}/repl_set_config.idl:74-109 the settings: heartbeatIntervalMillis 2000, heartbeatTimeoutSecs 10, electionTimeoutMillis 10000, catchUpTimeoutMillis -1, catchUpTakeoverDelayMillis 30000`, rung: \"implemented\" },\n { ref: `${AT}/repl_server_parameters.idl:320-328 replElectionTimeoutOffsetLimitFraction 0.15`, rung: \"implemented\" },\n { ref: `${AT}/topology_coordinator.cpp:1058-1101 the heartbeat window and the timeout of each request, :1124-1147 the next heartbeat, :1239-1248 a member DOWN`, rung: \"implemented\" },\n { ref: `${AT}/topology_coordinator.h:62 kMaxHeartbeatRetries 2`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl_heartbeat.cpp:97-111 the random offset, :346-352 a heartbeat from the primary postpones the election, :1215-1271 the election timeout and its offset`, rung: \"implemented\" },\n { ref: `${AT}/data_replicator_external_state_impl.cpp:70-81 an oplog batch that names a primary postpones the election`, rung: \"implemented\" },\n { ref: `${AT}/delayable_timeout_callback.cpp:149-172 the offset changes at most once in its own length`, rung: \"implemented\" },\n { ref: `${AT}/topology_coordinator.cpp:1440-1457 and :1476-1489 the liveness check: a primary that cannot see a majority steps down`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl_heartbeat.cpp:1158-1188 the liveness check runs at the stalest member's last update plus the election timeout`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl_elect_v1.cpp:189-226 the dry run, :268-382 the term, the durable vote and the real vote, :408-468 the win`, rung: \"implemented\" },\n { ref: `${AT}/vote_requester.cpp:96 a vote request times out at min(electionTimeoutMillis, 30 s), :160-177 a majority of yes votes ends the round`, rung: \"implemented\" },\n { ref: `${AT}/topology_coordinator.cpp:3741-3790 a member votes for each candidate whose data is not staler than its own, and only an arbiter refuses one because it sees a primary`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl_catchup.cpp:35-85 the catch-up and its timeout, :110-133 it ends when each other member answered a heartbeat since the win, or failed one, :349-379 the win restarts each heartbeat`, rung: \"implemented\" },\n { ref: `${AT}/topology_coordinator.cpp:3841-3849 and :3910-3932 a restarted heartbeat, and the latest optime that the catch-up waits for`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl.cpp:1490-1570 the end of the drain: a reconfig of the term, then writes, :2580-2588 the hello of a primary that cannot write yet`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl_step_up_step_down.cpp:64-329 replSetStepDown: the wait for a caught-up secondary, the step-down and the hand-off`, rung: \"implemented\" },\n { ref: `${AT}/repl_set_commands.cpp:545-561 stepDownSecs 60 and secondaryCatchUpPeriodSecs 10`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl.idl:18-26 enableElectionHandoff true, and replication_coordinator_impl.cpp:2830-2873 the hand-off: replSetStepUp with skipDryRun`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl.cpp:1516 the reconfig of the term, :4598 and :4750 a new config starts each heartbeat again`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl_heartbeat.cpp:367-376 a heartbeat response that moves a member's optime forward moves the commit point and wakes the writes that wait`, rung: \"implemented\" },\n { ref: `${AT}/oplog_fetcher.cpp:119-133 the awaitData timeout min(electionTimeoutMillis / 2, 30 s), :317-324 the socket timeout adds oplogNetworkTimeoutBufferSeconds, :640-647 the exhaust read`, rung: \"implemented\" },\n { ref: `${AT}/oplog_fetcher.cpp:395-441 an error makes a new cursor while restarts remain, :596-611 the new cursor sets the retried find timeout, :1073-1113 one restart after 5 ms`, rung: \"implemented\" },\n { ref: `${AT}/repl_server_parameters.idl:121-126 oplogRetriedFindMaxSeconds 2, :234-244 oplogFetcherSteadyStateMaxFetcherRestarts 1, :344-351 oplogNetworkTimeoutBufferSeconds 5`, rung: \"implemented\" },\n { ref: \"mongodb r9.0.4 src/mongo/transport/asio/asio_session_impl.cpp:500-527 the timeout of a synchronous session is SO_RCVTIMEO, and src/mongo/client/dbclient_session.cpp:345-349 its connect uses the same timeout\", rung: \"implemented\" },\n { ref: `${AT}/bgsync.cpp:395-447 a member without a sync source waits for new heartbeat data or 1 s (:971-976), and topology_coordinator.cpp:1124-1136 it sends its heartbeats each 500 ms`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl.cpp:4947-4972 a member that loses its sync source starts each heartbeat again at once`, rung: \"implemented\" },\n { ref: `${AT}/sync_source_feedback.cpp:37-47 the keepalive of the reporter min(electionTimeoutMillis / 2, 30 s), :39-40 the network timeout 30 s, :99-117 and :134-236 a new reporter only after the old one ends`, rung: \"implemented\" },\n { ref: `${AT}/reporter.cpp:113-117 a reporter ends when its command in flight ends, :119-169 a trigger, :195-228 each replSetUpdatePosition has the network timeout`, rung: \"implemented\" },\n { ref: \"linux v6.6 net/core/sock.c:427-460 SO_RCVTIMEO in jiffies, and kernel/time/timer.c:516-528 the wheel rounds a timer up to the granularity of its level\", rung: \"implemented\" },\n ],\n states: {\n startup: { initial: true, pseudo: true },\n secondary: { note: \"SECONDARY: it replicates from its sync source, and its election timeout runs\" },\n \"dry-run\": { note: \"a dry run: votes are asked in the current term (replication_coordinator_impl_elect_v1.cpp:200-226)\" },\n candidate: { note: \"the real election: a new term, a durable vote for itself, and a vote request to each member\" },\n catchup: { note: \"PRIMARY in catch-up: it waits for a heartbeat answer from each other member, or a failure (log 21359)\" },\n drain: { note: \"PRIMARY in drain mode: the applier ends its buffer, and the hello says secondary (replication_coordinator_impl.cpp:2580-2584)\" },\n primary: { note: \"PRIMARY that accepts writes (log 21331)\" },\n \"stepping-down\": { note: \"replSetStepDown waits for a caught-up secondary, and the hello says not writable (step_up_step_down.cpp:46-52)\" },\n },\n events: {\n \"tx.heartbeat\": { kind: \"tx\", note: \"a heartbeat request, the first of a window or a retry in it\" },\n \"rx.heartbeat\": { kind: \"rx\", note: \"a heartbeat response\" },\n \"rx.primary-heartbeat\": { kind: \"rx\", note: \"a heartbeat response from the primary in the current term\" },\n \"rx.primary-oplog\": { kind: \"rx\", note: \"an oplog batch whose metadata names a primary\" },\n \"rx.member\": { kind: \"rx\", note: \"any message from a member: a heartbeat request or response, or an update of its position\" },\n \"timer.heartbeat\": { kind: \"timer\" },\n \"timer.heartbeat-window\": { kind: \"timer\", note: \"the window ends without a response: the target is DOWN (log 21216)\" },\n \"timer.election\": { kind: \"timer\", note: \"log 4615652: Starting an election\" },\n \"timer.liveness\": { kind: \"timer\", note: \"log 21809: Can't see a majority of the set, relinquishing primary\" },\n \"rx.votes\": { kind: \"rx\", note: \"a majority of yes votes\" },\n \"rx.no-votes\": { kind: \"rx\", note: \"the round ends without a majority\" },\n \"local.caught-up\": { kind: \"local\", note: \"log 21364 or 21368\" },\n \"timer.catchup\": { kind: \"timer\" },\n \"local.drained\": { kind: \"local\", note: \"log 21331: Transition to primary complete\" },\n \"rx.higher-term\": { kind: \"rx\" },\n \"app.step-down\": { kind: \"app\", note: \"replSetStepDown\" },\n \"timer.step-down-wait\": { kind: \"timer\" },\n \"local.secondary-caught-up\": { kind: \"local\" },\n \"app.step-up\": { kind: \"app\", note: \"replSetStepUp, as a hand-off sends it with skipDryRun\" },\n \"timer.catchup-takeover\": { kind: \"timer\" },\n \"timer.step-down-hold\": { kind: \"timer\" },\n \"rx.oplog-batch\": { kind: \"rx\", note: \"a batch of the exhaust stream of the sync source\" },\n \"timer.oplog-read\": { kind: \"timer\", note: \"log 21275: Recreating cursor for oplog fetcher due to error (NetworkTimeout)\" },\n \"local.oplog-restart\": { kind: \"local\", note: \"the fetcher makes a new cursor on the same sync source\" },\n \"timer.oplog-refind\": { kind: \"timer\", note: \"log 21080: Clearing sync source to choose a new one\" },\n \"tx.update-position\": { kind: \"tx\", note: \"a replSetUpdatePosition to the sync source\" },\n \"rx.update-position\": { kind: \"rx\", note: \"the reply to a replSetUpdatePosition\" },\n \"timer.update-position\": { kind: \"timer\", note: \"log 21760: SyncSourceFeedback error sending update\" },\n },\n knobs: {\n heartbeatIntervalMillis: { key: \"settings.heartbeatIntervalMillis\", scope: \"replica set\", unit: \"ms\", default: 2000, note: \"repl_set_config.idl:74-78\" },\n heartbeatTimeoutSecs: { key: \"settings.heartbeatTimeoutSecs\", scope: \"replica set\", unit: \"s\", default: 10, note: \"repl_set_config.idl:79-85\" },\n electionTimeoutMillis: { key: \"settings.electionTimeoutMillis\", scope: \"replica set\", unit: \"ms\", default: 10000, note: \"repl_set_config.idl:86-92\" },\n offset_fraction: {\n key: \"replElectionTimeoutOffsetLimitFraction\",\n scope: \"process\",\n unit: \"count\",\n default: 0.15,\n note: \"repl_server_parameters.idl:320-328: a fraction, thus the offset is less than 0.15 × electionTimeoutMillis\",\n },\n catchUpTimeoutMillis: {\n key: \"settings.catchUpTimeoutMillis\",\n scope: \"replica set\",\n unit: \"ms\",\n default: null,\n note: \"repl_set_config.idl:93-101: -1 at the defaults, which is no bound. 0 skips the catch-up\",\n },\n catchUpTakeoverDelayMillis: { key: \"settings.catchUpTakeoverDelayMillis\", scope: \"replica set\", unit: \"ms\", default: 30000, note: \"repl_set_config.idl:102-109\" },\n secondaryCatchUpPeriodSecs: { key: \"replSetStepDown secondaryCatchUpPeriodSecs\", scope: \"command\", unit: \"s\", default: 10, note: \"repl_set_commands.cpp:553-561\" },\n stepDownSecs: { key: \"replSetStepDown stepDownSecs\", scope: \"command\", unit: \"s\", default: 60, note: \"repl_set_commands.cpp:545-548\" },\n heartbeat_retries: { key: \"kMaxHeartbeatRetries\", scope: \"build\", unit: \"count\", default: 2, note: \"topology_coordinator.h:62\" },\n vote_timeout_max: { key: \"maximumVoteRequestTimeoutMS\", scope: \"build\", unit: \"ms\", default: 30000, note: \"vote_requester.cpp:96\" },\n executor_slack: {\n key: \"the lateness of the replication executor for one step\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"an assumption of this document, not a value of mongod: a callback of the executor that comes late\",\n },\n election_work: {\n key: \"the local work of an election or a step-up\",\n scope: \"process\",\n unit: \"ms\",\n default: 100,\n note: \"an assumption of this document, not a value of mongod: the durable vote, the reconfig of the term and the first oplog entry of a new primary are local writes\",\n },\n rtt: { key: \"the round trip between members\", scope: \"path\", unit: \"ms\", default: null },\n maximumAwaitDataTimeoutMS: { key: \"maximumAwaitDataTimeoutMS\", scope: \"build\", unit: \"ms\", default: 30000, note: \"oplog_fetcher.cpp:119\" },\n oplogNetworkTimeoutBufferSeconds: { key: \"oplogNetworkTimeoutBufferSeconds\", scope: \"process\", unit: \"s\", default: 5, note: \"repl_server_parameters.idl:344-351\" },\n oplogRetriedFindMaxSeconds: { key: \"oplogRetriedFindMaxSeconds\", scope: \"process\", unit: \"s\", default: 2, note: \"repl_server_parameters.idl:121-126\" },\n oplogFetcherSteadyStateMaxFetcherRestarts: {\n key: \"oplogFetcherSteadyStateMaxFetcherRestarts\",\n scope: \"process\",\n unit: \"count\",\n default: 1,\n note: \"repl_server_parameters.idl:234-244: one new cursor after an error, then the fetcher stops\",\n },\n oplog_read_timeout: {\n key: \"the receive timeout of the exhaust read of an oplog fetcher\",\n scope: \"process\",\n unit: \"ms\",\n default: 10000,\n note: \"the value of min(electionTimeoutMillis / 2, maximumAwaitDataTimeoutMS) + oplogNetworkTimeoutBufferSeconds × 1000 (oplog_fetcher.cpp:124-133, :317-324). The model gives it from the settings. The wheel reads it as a knob\",\n },\n syncSourceFeedbackNetworkTimeoutSecs: { key: \"syncSourceFeedbackNetworkTimeoutSecs\", scope: \"build\", unit: \"s\", default: 30, note: \"sync_source_feedback.cpp:39-40\" },\n maximumKeepAliveIntervalMS: { key: \"maximumKeepAliveIntervalMS\", scope: \"build\", unit: \"ms\", default: 30000, note: \"sync_source_feedback.cpp:37\" },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"the build option of the kernel: SO_RCVTIMEO of the fetcher's socket is a timer on its wheel\",\n },\n },\n timers: {\n heartbeat: {\n // the next heartbeat starts heartbeatIntervalMillis after a response or a failed window (topology_coordinator.cpp:1129, :1146)\n duration: { knob: \"heartbeatIntervalMillis\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"rx.heartbeat\", \"timer.heartbeat-window\"],\n fires: \"timer.heartbeat\",\n },\n heartbeat_fast: {\n // a member that is not primary and has no sync source sends its heartbeats more often (topology_coordinator.cpp:1133-1136)\n duration: { expr: \"min(electionTimeoutMillis / 2, heartbeatIntervalMillis / 4)\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"rx.heartbeat\", \"timer.heartbeat-window\"],\n fires: \"timer.heartbeat\",\n note: \"500 ms at the defaults\",\n },\n heartbeat_window: {\n // a window is heartbeatTimeoutSecs from its first request, and each retry gets what is left (topology_coordinator.cpp:1058-1068, :1096-1100)\n duration: { expr: \"heartbeatTimeoutSecs * 1000\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"tx.heartbeat\"],\n cancels: [\"rx.heartbeat\"],\n fires: \"timer.heartbeat-window\",\n note: \"the target is DOWN at the end of a window without a response (topology_coordinator.cpp:1245-1247, member_data.cpp:86-99)\",\n },\n election: {\n // now + electionTimeoutMillis + an offset in [0, fraction × electionTimeoutMillis) (heartbeat.cpp:1249-1253, :97-111)\n duration: { knob: \"electionTimeoutMillis\", unit: \"ms\" },\n lateness: { expr: \"electionTimeoutMillis * offset_fraction + executor_slack\", unit: \"ms\" },\n arms: [\"enter:secondary\", \"rx.primary-heartbeat\", \"rx.primary-oplog\"],\n fires: \"timer.election\",\n note: \"the offset is random, and it changes at most once in its own length (delayable_timeout_callback.cpp:149-158)\",\n },\n liveness: {\n // a member whose last update is older than the election timeout is stale (topology_coordinator.cpp:1444-1449)\n duration: { knob: \"electionTimeoutMillis\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"enter:primary\", \"rx.member\"],\n fires: \"timer.liveness\",\n note: \"a primary steps down when the stale members leave it without a majority (topology_coordinator.cpp:1452-1455)\",\n },\n vote_request: {\n duration: { expr: \"min(electionTimeoutMillis, vote_timeout_max)\", unit: \"ms\" },\n arms: [\"enter:dry-run\", \"enter:candidate\"],\n cancels: [\"rx.votes\"],\n fires: \"rx.no-votes\",\n note: \"a majority of yes votes ends the round before it (vote_requester.cpp:160-177)\",\n },\n catchup: {\n duration: { knob: \"catchUpTimeoutMillis\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"enter:catchup\"],\n cancels: [\"local.caught-up\"],\n fires: \"timer.catchup\",\n note: \"no bound at -1, and no catch-up at 0 (catchup.cpp:48-75)\",\n },\n catchup_takeover: {\n duration: { knob: \"catchUpTakeoverDelayMillis\", unit: \"ms\" },\n arms: [\"rx.heartbeat\"],\n cancels: [\"local.caught-up\"],\n fires: \"timer.catchup-takeover\",\n note: \"a secondary that is ahead of a primary in catch-up takes over after this delay (heartbeat.cpp:501-515)\",\n },\n step_down_wait: {\n duration: { knob: \"secondaryCatchUpPeriodSecs\", unit: \"s\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"app.step-down\"],\n cancels: [\"local.secondary-caught-up\"],\n fires: \"timer.step-down-wait\",\n note: \"the wait of replSetStepDown for an electable secondary at the primary's optime (step_up_step_down.cpp:197-292)\",\n },\n step_down_hold: {\n duration: { knob: \"stepDownSecs\", unit: \"s\" },\n arms: [\"app.step-down\"],\n fires: \"timer.step-down-hold\",\n note: \"the old primary cannot be elected in this time (step_up_step_down.cpp:313-315)\",\n },\n oplog_read: {\n // the exhaust stream reads with SO_RCVTIMEO: awaitData and the buffer (oplog_fetcher.cpp:640-647, asio_session_impl.cpp:500-527)\n duration: { expr: \"min(electionTimeoutMillis / 2, maximumAwaitDataTimeoutMS) + oplogNetworkTimeoutBufferSeconds * 1000\", unit: \"ms\" },\n early: { model: \"linux.jiffy\", knobs: [\"hz\"], unit: \"s\" },\n lateness: { model: \"linux.wheel\", knobs: [\"oplog_read_timeout\", \"hz\"], unit: \"s\" },\n arms: [\"rx.oplog-batch\"],\n fires: \"timer.oplog-read\",\n note: \"a kernel timer in jiffies (sock.c:427-460), which the wheel rounds up at the level of its length: up to 512 ms late for 10 s at HZ 1000\",\n },\n oplog_restart: {\n duration: { const: 5, unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"timer.oplog-read\"],\n fires: \"local.oplog-restart\",\n note: \"oplog_fetcher.cpp:1097-1112: the first restart sleeps 5 ms, and the fetcher has one restart\",\n },\n oplog_refind: {\n // the new cursor reads with the retried find timeout and the buffer, and the connect uses it too (oplog_fetcher.cpp:596-611, dbclient_session.cpp:345-349)\n duration: { expr: \"(oplogRetriedFindMaxSeconds + oplogNetworkTimeoutBufferSeconds) * 1000\", unit: \"ms\" },\n lateness: { model: \"linux.wheel\", knobs: [\"oplog_read_timeout\", \"hz\"], unit: \"s\" },\n arms: [\"local.oplog-restart\"],\n cancels: [\"rx.oplog-batch\"],\n fires: \"timer.oplog-refind\",\n note: \"a cut source times out the connect, and a frozen source the read of the find, on the wheel. The wheel at the longer read timeout bounds both. Then the member clears its sync source\",\n },\n feedback_keepalive: {\n duration: { expr: \"min(electionTimeoutMillis / 2, maximumKeepAliveIntervalMS)\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"rx.update-position\"],\n cancels: [\"rx.oplog-batch\"],\n fires: \"tx.update-position\",\n note: \"sync_source_feedback.cpp:45-47: a reporter with no news sends its position again after this time\",\n },\n feedback_update: {\n duration: { knob: \"syncSourceFeedbackNetworkTimeoutSecs\", unit: \"s\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"tx.update-position\"],\n cancels: [\"rx.update-position\"],\n fires: \"timer.update-position\",\n note: \"the network timeout of a replSetUpdatePosition (reporter.cpp:195-228). The reporter ends only when this command ends (reporter.cpp:113-117), and the feedback makes the reporter for a new sync source only then (sync_source_feedback.cpp:99-117)\",\n },\n },\n realizes: {\n // from the start of a silence: the next request goes out up to heartbeatIntervalMillis after the last response, and its window starts then\n \"systems.mechanism.heartbeat-detection-time\": {\n duration: { expr: \"heartbeatIntervalMillis + heartbeatTimeoutSecs * 1000\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n early: { knob: \"heartbeatIntervalMillis\", unit: \"ms\" },\n note: \"a member is DOWN at the end of a heartbeat window without a response. A silence that starts just before a request is found one window later. One that starts just after a response is found an interval and a window later\",\n },\n \"systems.mechanism.election-timeout\": { timer: \"election\" },\n // how long a leader keeps its role without a majority: the primary steps down at the end of it\n \"systems.mechanism.step-down-window\": { timer: \"liveness\" },\n },\n transitions: [\n { id: \"rs.secondary\", from: \"startup\", to: \"secondary\", on: \"rx.heartbeat\" },\n { id: \"rs.election\", from: \"secondary\", to: \"dry-run\", on: \"timer.election\", timer: \"election\", emits: [\"4615652\"], source: \"replication_coordinator_impl_heartbeat.cpp:1345-1352\" },\n { id: \"rs.step-up\", from: \"secondary\", to: \"candidate\", on: \"app.step-up\", note: \"a hand-off skips the dry run\", source: \"replication_coordinator_impl_elect_v1.cpp:192-198\" },\n { id: \"rs.dry-run-won\", from: \"dry-run\", to: \"candidate\", on: \"rx.votes\", source: \"replication_coordinator_impl_elect_v1.cpp:257-265\" },\n { id: \"rs.dry-run-lost\", from: \"dry-run\", to: \"secondary\", on: \"rx.no-votes\", timer: \"vote_request\", emits: [\"21440\"], source: \"replication_coordinator_impl_elect_v1.cpp:244-246\" },\n {\n id: \"rs.won\",\n from: \"candidate\",\n to: \"catchup\",\n on: \"rx.votes\",\n emits: [\"21450\", \"21359\"],\n note: \"the win restarts each heartbeat, and the catch-up waits for each other member's answer or failure\",\n source: \"replication_coordinator_impl_elect_v1.cpp:435-463, replication_coordinator_impl_catchup.cpp:349-379\",\n },\n { id: \"rs.lost\", from: \"candidate\", to: \"secondary\", on: \"rx.no-votes\", timer: \"vote_request\", emits: [\"21448\"] },\n { id: \"rs.caught-up\", from: \"catchup\", to: \"drain\", on: [\"local.caught-up\", \"timer.catchup\"], emits: [\"21363\"], source: \"replication_coordinator_impl_catchup.cpp:87-133\" },\n { id: \"rs.writable\", from: \"drain\", to: \"primary\", on: \"local.drained\", emits: [\"21331\"], source: \"replication_coordinator_impl.cpp:1490-1570\" },\n { id: \"rs.no-majority\", from: [\"primary\", \"catchup\", \"drain\"], to: \"secondary\", on: \"timer.liveness\", timer: \"liveness\", emits: [\"21809\"], source: \"topology_coordinator.cpp:1440-1457\" },\n { id: \"rs.higher-term\", from: [\"primary\", \"catchup\", \"drain\"], to: \"secondary\", on: \"rx.higher-term\", emits: [\"21475\"], source: \"replication_coordinator_impl_heartbeat.cpp:469-480\" },\n { id: \"rs.step-down\", from: \"primary\", to: \"stepping-down\", on: \"app.step-down\", note: \"writes stop, and the hello says not writable\", source: \"replication_coordinator_impl_step_up_step_down.cpp:46-52, :118-125\" },\n {\n id: \"rs.stepped-down\",\n from: \"stepping-down\",\n to: \"secondary\",\n on: \"local.secondary-caught-up\",\n emits: [\"962660\", \"21347\"],\n note: \"then the hand-off: replSetStepUp with skipDryRun to the best secondary\",\n source: \"replication_coordinator_impl_step_up_step_down.cpp:207-321\",\n },\n { id: \"rs.step-down-failed\", from: \"stepping-down\", to: \"primary\", on: \"timer.step-down-wait\", timer: \"step_down_wait\", errno: \"ExceededTimeLimit\" },\n ],\n observe: {\n \"mongod-log\": {\n fidelity: \"complete\",\n note: \"the JSON log of mongod: id 21358 gives each state change, and the ids of the transitions give the steps between them\",\n states: { SECONDARY: \"secondary\", PRIMARY: \"catchup\" },\n },\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the source of MongoDB at the tag r9.0.4. Each line number is a\n// line of that file at that tag.\nconst AT = \"mongodb r9.0.4 src/mongo\";\n\n/**\n * This document is the hold of mongod 9.0.4 on one client connection, over its socket. `mongod`\n * turns keepalive on for each TCP session. It lowers two keepalive options of the socket to a\n * maximum: the idle time to 300 s and the interval to 1 s. It does not change the probe count.\n * Thus the namespace sysctls give the idle time and the interval only when they are lower, and\n * they always give the count.\n *\n * `mongod` writes no warning about keepalive. A failure to read or to set an option goes to the\n * log at debug level 3 in a release build.\n *\n * An awaitable hello of an exhaust stream waits for a change of the topology or `maxAwaitTimeMS`.\n * Then `mongod` sends the reply, and it starts the next hello of the stream at once.\n */\nexport const MONGOD_SESSION: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"mongod-session\",\n title: \"A client connection as mongod 9.0.4 holds it, over its Linux socket\",\n layer: \"server\",\n version: \"9.0.4\",\n conditions: { mongodb: \"9.0.4\", os: \"linux\", image: \"mongo:9.0.4 (Ubuntu 26.04)\" },\n sources: [\n { ref: `${AT}/transport/asio/asio_session_impl.cpp:156-165 each TCP session: TCP_NODELAY, SO_KEEPALIVE, setSocketKeepAliveParams, failures at debug 3 in a release build`, rung: \"implemented\" },\n { ref: `${AT}/util/net/socket_utils.h:15-16 kMaxKeepIdleSecs 300 and kMaxKeepIntvlSecs 1, :19-22 the defaults of setSocketKeepAliveParams`, rung: \"implemented\" },\n { ref: `${AT}/util/net/socket_utils.cpp:165-196 applyMax: read the option, and set the maximum only when the value is higher, :199-220 TCP_KEEPIDLE and TCP_KEEPINTVL, never TCP_KEEPCNT`, rung: \"implemented\" },\n { ref: `${AT}/util/net/socket_utils.cpp:176-181 and :190-194 the log of a failed read or set, at the severity of the caller`, rung: \"implemented\" },\n { ref: `${AT}/util/net/sock.cpp:135-142 the older socket path: SO_KEEPALIVE, then the same maximums, failures as errors`, rung: \"implemented\" },\n { ref: `${AT}/db/repl/replication_info.cpp:131-143 an awaitable hello waits until now + maxAwaitTimeMS on the precise clock, or a change of the topology`, rung: \"implemented\" },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n CONNECTED: { note: \"a session of the transport layer, with its socket\" },\n GONE: { final: true },\n },\n events: {\n accept: { kind: \"local\" },\n \"peer.fin\": { kind: \"peer\", note: \"a read gives 0 bytes: the client closed\" },\n \"peer.rst\": { kind: \"peer\" },\n \"socket.error\": { kind: \"local\", note: \"a read fails with the error of the socket: the kernel gave up, by keepalive or by its retransmissions\" },\n \"rx.hello\": { kind: \"rx\", note: \"an awaitable hello with exhaustAllowed: the start of a stream\" },\n \"tx.hello-reply\": { kind: \"tx\", note: \"a reply of the stream, after which mongod runs the next hello\" },\n },\n knobs: {\n tcp_keepalive_time: { key: \"net.ipv4.tcp_keepalive_time\", scope: \"netns\", unit: \"s\", default: 7200, note: \"the value of a new socket, which mongod lowers to max_keep_idle\" },\n tcp_keepalive_intvl: { key: \"net.ipv4.tcp_keepalive_intvl\", scope: \"netns\", unit: \"s\", default: 75, note: \"the value of a new socket, which mongod lowers to max_keep_intvl\" },\n tcp_keepalive_probes: { key: \"net.ipv4.tcp_keepalive_probes\", scope: \"netns\", unit: \"count\", default: 9, note: \"mongod does not change it\" },\n max_keep_idle: { key: \"kMaxKeepIdleSecs\", scope: \"build\", unit: \"s\", default: 300, note: \"socket_utils.h:15\" },\n max_keep_intvl: { key: \"kMaxKeepIntvlSecs\", scope: \"build\", unit: \"s\", default: 1, note: \"socket_utils.h:16\" },\n hz: { key: \"CONFIG_HZ\", scope: \"global\", unit: \"Hz\", default: null, note: \"the kernel's build option: the timer wheel rounds the keepalive of mongod\" },\n maxAwaitTimeMS: { key: \"hello maxAwaitTimeMS\", scope: \"command\", unit: \"ms\", default: null, note: \"the field of an awaitable hello: the driver sends its heartbeatFrequencyMS (mongodb monitor.ts:338-371)\" },\n wait_slack: {\n key: \"the lateness of a wait of a command of mongod\",\n scope: \"process\",\n unit: \"ms\",\n default: 20,\n note: \"an assumption of this document, not a value of mongod. In CI, the first reply of a stream after a fault came 1 ms to 10.6 ms after maxAwaitTimeMS (T01.defaults.42, T03.defaults.3)\",\n },\n },\n timers: {\n hello_await: {\n duration: { knob: \"maxAwaitTimeMS\", unit: \"ms\" },\n lateness: { knob: \"wait_slack\", unit: \"ms\" },\n arms: [\"rx.hello\", \"tx.hello-reply\"],\n fires: \"tx.hello-reply\",\n note: \"replication_info.cpp:131-143: with no change of the topology, each reply of the stream comes maxAwaitTimeMS after the last reply, or after the request\",\n },\n },\n realizes: {\n \"systems.mechanism.idle-refresh-interval\": {\n duration: { expr: \"min(tcp_keepalive_time, max_keep_idle)\", unit: \"s\" },\n lateness: { model: \"linux.wheel\", knobs: [\"max_keep_idle\", \"hz\"], unit: \"s\" },\n early: { model: \"linux.jiffy\", knobs: [\"hz\"], unit: \"s\" },\n note: \"the first probe of an idle connection. The lateness is the wheel's at 300 s: at a lower idle time it is the same or longer than the true one\",\n },\n \"systems.mechanism.keepalive-detection-window\": { timer: \"keepalive\" },\n },\n transitions: [\n { id: \"ms.accept\", from: \"ABSENT\", to: \"CONNECTED\", on: \"accept\", source: \"asio_session_impl.cpp:149-165\" },\n { id: \"ms.gone\", from: \"CONNECTED\", to: \"GONE\", on: [\"peer.fin\", \"peer.rst\", \"socket.error\"] },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { CONNECTED: \"ESTABLISHED\" },\n sets: {\n keepidle: { expr: \"min(tcp_keepalive_time, max_keep_idle)\", unit: \"s\" },\n keepintvl: { expr: \"min(tcp_keepalive_intvl, max_keep_intvl)\", unit: \"s\" },\n keepcnt: { knob: \"tcp_keepalive_probes\", unit: \"count\" },\n },\n ends: \"socket.error\",\n note: \"at the Linux defaults the window is 300 s + 9 × 1 s = 309 s, not 300 s + 9 × 75 s: the interval has a maximum too\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the TypeScript source of the npm package mongodb at 7.7.0,\n// under src/. Each line number is a line of that file in the package. Node's own facts are from\n// node v24.21.0, as the ioredis document of this repository cites them.\nconst AT = \"mongodb 7.7.0 src\";\n\n/**\n * This document is the MongoDB Node driver 7.7.0, for one server of a replica set. It gives one\n * connection of the driver by its role, and the timers that act on it. The roles are the monitor\n * of the server, the pool connection that an operation uses, and the wait of an operation for a\n * suitable server. The monitor streams `hello`: the server answers when its topology changes, or\n * after `heartbeatFrequencyMS`. The monitor writes the server off when its socket is silent for\n * `connectTimeoutMS + heartbeatFrequencyMS`.\n *\n * A knob of the driver at 0 has no timer: give it as no bound (`infinite`). This is true of\n * `connectTimeoutMS`, `socketTimeoutMS`, `waitQueueTimeoutMS`, `maxIdleTimeMS` and\n * `serverSelectionTimeoutMS`.\n */\nexport const MONGODB_NODE: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"mongodb-node\",\n title: \"MongoDB Node driver 7.7.0: one server of a replica set, its monitor, its pool and the retry of an operation\",\n layer: \"driver\",\n version: \"7.7.0\",\n conditions: {\n mongodb: \"7.7.0\",\n node: \"24.21.0\",\n topology: \"a replica set, with the streaming monitor (serverMonitoringMode auto, not in a FaaS environment)\",\n timeouts: \"no timeoutMS: the legacy timeout context\",\n },\n sources: [\n { ref: `${AT}/connection_string.ts:804-807 connectTimeoutMS 30000, :850-853 heartbeatFrequencyMS 10000, :934-937 minHeartbeatFrequencyMS 500`, rung: \"implemented\" },\n { ref: `${AT}/connection_string.ts:1100-1103 serverSelectionTimeoutMS 30000, :1107-1111 socketTimeoutMS 0, :1178-1182 waitQueueTimeoutMS 0`, rung: \"implemented\" },\n { ref: `${AT}/connection_string.ts:896-898 maxConnecting 2, :906-908 maxIdleTimeMS 0, :910-912 maxPoolSize 100, :930-933 minPoolSize 0, :1075-1082 retryReads and retryWrites true, :1089-1091 serverMonitoringMode auto`, rung: \"implemented\" },\n { ref: `${AT}/cmap/connect.ts:291 DEFAULT_KEEP_ALIVE_INITIAL_DELAY_MS 120000, :336-338 keepAlive and noDelay, :378-417 makeSocket: setKeepAlive, setNoDelay, setTimeout(connectTimeoutMS), :432-438 the connect timeout`, rung: \"implemented\" },\n { ref: `${AT}/cmap/connect.ts:117-120 the handshake reads with socketTimeoutMS = connectTimeoutMS`, rung: \"implemented\" },\n { ref: `${AT}/sdam/monitor.ts:245-259 the streaming protocol, :338-371 the awaitable hello: maxAwaitTimeMS = heartbeatFrequencyMS, socketTimeoutMS = connectTimeoutMS + maxAwaitTimeMS`, rung: \"implemented\" },\n { ref: `${AT}/sdam/monitor.ts:273-293 a failed heartbeat: ResetPool, and InterruptInUseConnections for a timeout`, rung: \"implemented\" },\n { ref: `${AT}/sdam/monitor.ts:175-194 reset: the next check after heartbeatFrequencyMS, :609-636 wake: no check sooner than minHeartbeatFrequencyMS, :668-691 the next check after heartbeatFrequencyMS`, rung: \"implemented\" },\n { ref: `${AT}/sdam/monitor.ts:490-565 the RTT pinger: its own connection, a hello each heartbeatFrequencyMS, no socket timeout`, rung: \"implemented\" },\n { ref: `${AT}/cmap/connection.ts:328-334 a socket timeout, 1 ms later, is a MongoNetworkTimeoutError, :461-505 the socket timeout of a command, set again at each reply`, rung: \"implemented\" },\n { ref: `${AT}/sdam/server.ts:186 resetServer, :390-444 handleError, :450-515 decorateCommandError, :532-546 markServerUnknown: a network error that is not a timeout resets the monitor`, rung: \"implemented\" },\n { ref: `${AT}/sdam/topology.ts:559 the selection timeout, :568-572 and :635-664 MongoServerSelectionError, :862-888 updateServers clears the pool, :1082-1089 a waiting selection wakes each monitor`, rung: \"implemented\" },\n { ref: `${AT}/sdam/topology_description.ts:458-467 a primary that another primary replaces is Unknown, and nothing clears its pool`, rung: \"implemented\" },\n { ref: `${AT}/cmap/connection_pool.ts:417-468 clear, :475-481 interruptInUseConnections: PoolClearedOnNetworkError, :584 a connection idle for maxIdleTimeMS is perished at the next check-out`, rung: \"implemented\" },\n { ref: `${AT}/cmap/errors.ts:37-84 PoolClearedError and PoolClearedOnNetworkError, with the label PoolRequestedRetry`, rung: \"implemented\" },\n { ref: `${AT}/operations/execute_operation.ts:252-279 two attempts for a retryable read or write, :375-380 the retry selects a server again, :442-445 canRetry`, rung: \"implemented\" },\n { ref: `${AT}/error.ts:1377-1394 the retryable codes, :1431-1436 isRetryableWriteError: RetryableWriteError or PoolRequestedRetry`, rung: \"implemented\" },\n { ref: `${AT}/timeout.ts:362-372 the legacy timeout context: the selection timeout, and no check-out timeout at waitQueueTimeoutMS 0`, rung: \"implemented\" },\n { ref: \"node v24.21.0 lib/net.js:846-888 (setKeepAlive truncates the delay to whole seconds) and src/tcp_wrap.cc:204-221 (interval 1 s and count 10 when none is given)\", rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"before the driver opens a connection to the server\" },\n connecting: { note: \"the TCP connect of a connection of any role, with the socket timeout connectTimeoutMS (connect.ts:417)\" },\n handshake: { note: \"the first hello of a new connection: a read with socketTimeoutMS = connectTimeoutMS (connect.ts:117-120)\" },\n streaming: { note: \"the monitor waits for the next hello reply of an exhaust stream (monitor.ts:338-371)\" },\n waiting: { note: \"the monitor waits for its next check: heartbeatFrequencyMS, or minHeartbeatFrequencyMS on a request (monitor.ts:609-691)\" },\n pooled: { note: \"a pool connection that no operation uses\" },\n \"in-use\": { note: \"a pool connection with an operation in flight: its read has socketTimeoutMS, 0 at the defaults (connection.ts:461-465)\" },\n selecting: { note: \"an operation waits for a suitable server, for serverSelectionTimeoutMS (topology.ts:559-572)\" },\n retrying: { note: \"the second attempt of a retryable operation, after a new selection (execute_operation.ts:375-380)\" },\n closed: { final: true, note: \"the connection ends, or the operation fails to the application\" },\n },\n events: {\n \"app.operation\": { kind: \"app\", note: \"an operation selects a server and checks out a connection\" },\n \"socket.connect\": { kind: \"local\" },\n \"socket.error\": { kind: \"local\", note: \"the socket ends: a FIN, a reset, or an error from the kernel (ETIMEDOUT, EHOSTUNREACH)\" },\n \"rx.hello\": { kind: \"rx\", note: \"a hello reply to the monitor\" },\n \"rx.reply\": { kind: \"rx\", note: \"the reply to the operation\" },\n \"timer.connect-timeout\": { kind: \"timer\" },\n \"timer.handshake-timeout\": { kind: \"timer\" },\n \"timer.stream-timeout\": { kind: \"timer\", note: \"the monitor socket was silent for connectTimeoutMS + heartbeatFrequencyMS: MongoNetworkTimeoutError\" },\n \"timer.socket-timeout\": { kind: \"timer\" },\n \"timer.check\": { kind: \"timer\", note: \"the next check of the monitor\" },\n \"timer.selection-timeout\": { kind: \"timer\", note: \"MongoServerSelectionError\" },\n \"timer.checkout-timeout\": { kind: \"timer\", note: \"WaitQueueTimeoutError\" },\n \"local.interrupt\": { kind: \"local\", note: \"the pool interrupts each connection in use: PoolClearedOnNetworkError\" },\n \"local.suitable\": { kind: \"local\", note: \"a server description suits the selection: a primary for a write\" },\n \"local.newer-primary\": { kind: \"local\", note: \"a hello from another member with a newer electionId\" },\n },\n knobs: {\n connectTimeoutMS: { key: \"mongodb connectTimeoutMS\", scope: \"client\", unit: \"ms\", default: 30000, off: 0, note: \"connection_string.ts:804-807. 0 is no timeout, thus also no stream timeout (monitor.ts:353)\" },\n heartbeatFrequencyMS: { key: \"mongodb heartbeatFrequencyMS\", scope: \"client\", unit: \"ms\", default: 10000, note: \"connection_string.ts:850-853: the period of the monitor, and the maxAwaitTimeMS of its hello\" },\n minHeartbeatFrequencyMS: { key: \"mongodb minHeartbeatFrequencyMS\", scope: \"client\", unit: \"ms\", default: 500, note: \"connection_string.ts:934-937\" },\n serverSelectionTimeoutMS: { key: \"mongodb serverSelectionTimeoutMS\", scope: \"client\", unit: \"ms\", default: 30000, note: \"connection_string.ts:1100-1103\" },\n socketTimeoutMS: { key: \"mongodb socketTimeoutMS\", scope: \"client\", unit: \"ms\", default: 0, off: 0, note: \"connection_string.ts:1107-1111. 0 is no timeout\" },\n waitQueueTimeoutMS: { key: \"mongodb waitQueueTimeoutMS\", scope: \"client\", unit: \"ms\", default: 0, off: 0, note: \"connection_string.ts:1178-1182 and timeout.ts:368-372. 0 is no timeout\" },\n maxIdleTimeMS: { key: \"mongodb maxIdleTimeMS\", scope: \"client\", unit: \"ms\", default: 0, note: \"connection_string.ts:906-908 and connection_pool.ts:584. 0 is no limit\" },\n maxPoolSize: { key: \"mongodb maxPoolSize\", scope: \"client\", unit: \"count\", default: 100, note: \"connection_string.ts:910-912\" },\n minPoolSize: { key: \"mongodb minPoolSize\", scope: \"client\", unit: \"count\", default: 0, note: \"connection_string.ts:930-933\" },\n maxConnecting: { key: \"mongodb maxConnecting\", scope: \"client\", unit: \"count\", default: 2, note: \"connection_string.ts:896-898\" },\n keepAliveInitialDelay: { key: \"mongodb keepAliveInitialDelay\", scope: \"client\", unit: \"ms\", default: 120000, note: \"connect.ts:291 and :415: setKeepAlive(true, delay) on each socket\" },\n node_keepalive_interval: { key: \"node net.Socket setKeepAlive interval\", scope: \"client\", unit: \"s\", default: 1, note: \"Node passes 1 s to libuv when setKeepAlive gets no interval, as the driver gives none\" },\n node_keepalive_count: { key: \"node net.Socket setKeepAlive count\", scope: \"client\", unit: \"count\", default: 10, note: \"Node passes 10 to libuv when setKeepAlive gets no count, as the driver gives none\" },\n retryWrites: { key: \"mongodb retryWrites\", scope: \"client\", unit: null, default: 1, note: \"connection_string.ts:1079-1082: on\" },\n retryReads: { key: \"mongodb retryReads\", scope: \"client\", unit: null, default: 1, note: \"connection_string.ts:1075-1078: on\" },\n attempts: { key: \"the attempts of a retryable operation\", scope: \"client\", unit: \"count\", default: 2, note: \"execute_operation.ts:272-279: one try and one retry, without timeoutMS\" },\n slack: {\n key: \"the lateness of the event loop of Node for one step\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"an assumption of this document, not a value of the driver: a timer or a callback of Node that comes late\",\n },\n rtt: { key: \"the round trip to the server\", scope: \"path\", unit: \"ms\", default: null },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"the build option of the kernel: the keepalive of the driver is the kernel's, thus the timer wheel rounds its firings\",\n },\n },\n timers: {\n stream_timeout: {\n // the exhaust hello reads with socketTimeoutMS = connectTimeoutMS + maxAwaitTimeMS (monitor.ts:351-356),\n // and each reply sets the timeout again (connection.ts:492-501). The timeout is 1 ms later (connection.ts:328-334)\n duration: { expr: \"connectTimeoutMS + heartbeatFrequencyMS\", unit: \"ms\" },\n early: { const: 1, unit: \"ms\" },\n lateness: { expr: \"1 + slack\", unit: \"ms\" },\n arms: [\"enter:streaming\", \"rx.hello\"],\n cancels: [\"socket.error\"],\n fires: \"timer.stream-timeout\",\n note: \"the write-off of a silent server: the monitor fails its heartbeat with MongoNetworkTimeoutError, clears the pool and interrupts each connection in use\",\n },\n connect_timeout: {\n duration: { knob: \"connectTimeoutMS\", unit: \"ms\" },\n lateness: { expr: \"1 + slack\", unit: \"ms\" },\n arms: [\"enter:connecting\"],\n cancels: [\"socket.connect\", \"socket.error\"],\n fires: \"timer.connect-timeout\",\n note: \"connect.ts:417 and :432-438: the socket timeout of the TCP connect. The kernel's SYN retransmissions go on under it\",\n },\n handshake_timeout: {\n duration: { knob: \"connectTimeoutMS\", unit: \"ms\" },\n lateness: { expr: \"1 + slack\", unit: \"ms\" },\n arms: [\"enter:handshake\"],\n cancels: [\"rx.hello\", \"socket.error\"],\n fires: \"timer.handshake-timeout\",\n note: \"connect.ts:117-120: the first hello of a connection reads with socketTimeoutMS = connectTimeoutMS\",\n },\n socket_timeout: {\n duration: { knob: \"socketTimeoutMS\", unit: \"ms\" },\n lateness: { expr: \"1 + slack\", unit: \"ms\" },\n arms: [\"enter:in-use\"],\n cancels: [\"rx.reply\", \"socket.error\", \"local.interrupt\"],\n fires: \"timer.socket-timeout\",\n note: \"connection.ts:461-465: no bound at the defaults, thus an operation in flight waits for the kernel or for an interruption\",\n },\n check_period: {\n duration: { knob: \"heartbeatFrequencyMS\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:waiting\"],\n fires: \"timer.check\",\n note: \"monitor.ts:190-193 and :668-691: after a check that failed, or after a reset, the next check waits heartbeatFrequencyMS. A waiting selection wakes it after minHeartbeatFrequencyMS (monitor.ts:629-633)\",\n },\n selection_timeout: {\n duration: { knob: \"serverSelectionTimeoutMS\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:selecting\", \"enter:retrying\"],\n cancels: [\"local.suitable\"],\n fires: \"timer.selection-timeout\",\n note: \"topology.ts:559, :568-572: each selection, the retry's too, waits serverSelectionTimeoutMS\",\n },\n checkout_timeout: {\n duration: { knob: \"waitQueueTimeoutMS\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"app.operation\"],\n cancels: [\"socket.connect\"],\n fires: \"timer.checkout-timeout\",\n note: \"timeout.ts:368-372: no bound at the defaults\",\n },\n interrupt: {\n duration: { const: 0, unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"timer.stream-timeout\", \"timer.connect-timeout\", \"timer.handshake-timeout\"],\n fires: \"local.interrupt\",\n note: \"connection_pool.ts:463-481: a heartbeat that fails with a timeout clears the pool and interrupts each connection in use, one microtask later\",\n },\n },\n realizes: {\n \"systems.mechanism.connect-bound\": { timer: \"connect_timeout\" },\n \"systems.mechanism.driver-writeoff-time\": { timer: \"stream_timeout\" },\n \"systems.mechanism.heartbeat-interval\": { timer: \"check_period\" },\n // an operation that fails on a server is retried once, and the retry selects again with a new serverSelectionTimeoutMS\n \"systems.mechanism.client-retry-window\": { timer: \"selection_timeout\" },\n \"systems.mechanism.idle-refresh-interval\": {\n duration: { expr: \"floor(keepAliveInitialDelay / 1000)\", unit: \"s\" },\n lateness: { model: \"linux.wheel\", knobs: [\"keepAliveInitialDelay\", \"hz\"], unit: \"s\" },\n early: { model: \"linux.jiffy\", knobs: [\"hz\"], unit: \"s\" },\n note: \"the first keepalive probe of an idle pool connection: the delay in whole seconds, rounded up on the timer wheel of the kernel\",\n },\n },\n transitions: [\n { id: \"open\", from: \"[none]\", to: \"connecting\", on: \"app.operation\", source: \"connect.ts:378-417\" },\n { id: \"connected\", from: \"connecting\", to: \"handshake\", on: \"socket.connect\", source: \"connect.ts:427-428\" },\n {\n id: \"connect-timed-out\",\n from: \"connecting\",\n to: \"waiting\",\n on: \"timer.connect-timeout\",\n timer: \"connect_timeout\",\n errno: \"MongoNetworkTimeoutError\",\n emits: [\"local.interrupt\"],\n note: \"a timeout of the monitor's connect interrupts each connection in use, as a stream timeout does\",\n source: \"connect.ts:432-438, monitor.ts:418-422\",\n },\n { id: \"connect-failed\", from: [\"connecting\", \"handshake\"], to: \"waiting\", on: \"socket.error\", errno: \"MongoNetworkError\", source: \"connect.ts:429-431\" },\n {\n id: \"handshake-timed-out\",\n from: \"handshake\",\n to: \"waiting\",\n on: \"timer.handshake-timeout\",\n timer: \"handshake_timeout\",\n errno: \"MongoNetworkTimeoutError\",\n emits: [\"local.interrupt\"],\n source: \"connect.ts:117-120, monitor.ts:418-422\",\n },\n { id: \"monitor-up\", from: \"handshake\", to: \"streaming\", on: \"rx.hello\", note: \"the monitor sends the awaitable hello at once (monitor.ts:449-456)\", source: \"monitor.ts:394-417\" },\n { id: \"pool-up\", from: \"handshake\", to: \"pooled\", on: \"rx.hello\" },\n { id: \"hello\", from: \"streaming\", to: \"streaming\", on: \"rx.hello\", note: \"each reply arms the stream timeout again\", source: \"monitor.ts:295-336\" },\n {\n id: \"written-off\",\n from: \"streaming\",\n to: \"waiting\",\n on: \"timer.stream-timeout\",\n timer: \"stream_timeout\",\n errno: \"MongoNetworkTimeoutError\",\n emits: [\"local.interrupt\"],\n note: \"ResetPool and InterruptInUseConnections: the pool interrupts each operation in flight on the server\",\n source: \"monitor.ts:273-293, topology.ts:862-876\",\n },\n {\n id: \"stream-ended\",\n from: \"streaming\",\n to: \"waiting\",\n on: \"socket.error\",\n errno: \"MongoNetworkError\",\n note: \"ResetPool only: the pool does not interrupt an operation in flight. The monitor resets, and checks again after heartbeatFrequencyMS\",\n source: \"monitor.ts:273-293, server.ts:538-540, monitor.ts:175-194\",\n },\n {\n id: \"replaced\",\n from: \"streaming\",\n to: \"streaming\",\n on: \"local.newer-primary\",\n note: \"the description of the old primary is Unknown, its stream goes on, and nothing clears its pool\",\n source: \"topology_description.ts:458-467, topology.ts:862-888\",\n },\n { id: \"check\", from: \"waiting\", to: \"connecting\", on: \"timer.check\", timer: \"check_period\" },\n { id: \"checkout\", from: \"pooled\", to: \"in-use\", on: \"app.operation\" },\n { id: \"replied\", from: \"in-use\", to: \"pooled\", on: \"rx.reply\" },\n { id: \"socket-timed-out\", from: \"in-use\", to: \"closed\", on: \"timer.socket-timeout\", timer: \"socket_timeout\", errno: \"MongoNetworkTimeoutError\" },\n { id: \"interrupted\", from: \"in-use\", to: \"retrying\", on: \"local.interrupt\", errno: \"PoolClearedOnNetworkError\", note: \"a retryable error: the label PoolRequestedRetry\", source: \"connection_pool.ts:475-481, cmap/errors.ts:71-84\" },\n { id: \"op-socket-ended\", from: \"in-use\", to: \"retrying\", on: \"socket.error\", errno: \"MongoNetworkError\", note: \"the driver adds RetryableWriteError, and the server is Unknown\", source: \"server.ts:474-493\" },\n { id: \"selected\", from: [\"selecting\", \"retrying\"], to: \"in-use\", on: \"local.suitable\" },\n { id: \"no-server\", from: [\"selecting\", \"retrying\"], to: \"closed\", on: \"timer.selection-timeout\", timer: \"selection_timeout\", errno: \"MongoServerSelectionError\", source: \"topology.ts:635-664\" },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { connecting: \"SYN_SENT\", handshake: \"ESTABLISHED\", streaming: \"ESTABLISHED\", pooled: \"ESTABLISHED\", \"in-use\": \"ESTABLISHED\" },\n sets: {\n keepidle: { expr: \"floor(keepAliveInitialDelay / 1000)\", unit: \"s\" },\n keepintvl: { knob: \"node_keepalive_interval\", unit: \"s\" },\n keepcnt: { knob: \"node_keepalive_count\", unit: \"count\" },\n },\n ends: \"socket.error\",\n note: \"each socket of the driver is a Linux TCP socket. makeSocket calls setKeepAlive(true, keepAliveInitialDelay), and Node gives libuv the delay in whole seconds with its own interval and count. Thus the keepalive sysctls of the namespace never reach these sockets\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the Java source of HikariCP at the tag HikariCP-7.1.0 (commit\n// e4c04e8b6d33) and of pgjdbc at the tag REL42.7.13 (commit 3297557c6a80). Each line number is a\n// line of that file at its tag. A fact of the JDK (java.net.Socket, the executors) is an\n// assumption of this document, and its note says so.\nconst HK = \"HikariCP-7.1.0 src/main/java/com/zaxxer/hikari\";\nconst PG = \"pgjdbc REL42.7.13 pgjdbc/src/main/java/org/postgresql\";\n\n/**\n * This document is HikariCP 7.1.0 over pgjdbc 42.7.13, for one connection of a pool. It gives the\n * states of the connection, from its creation to its close, and the timers that act on it. The\n * pool makes its connections one at a time, on one thread. At the defaults the pool has a fixed\n * size of 10, thus its idle timer has no effect.\n *\n * HikariCP reads no idle socket. It finds a dead connection only by a check. A borrow checks a\n * connection that was idle for more than 500 ms. The keepalive checks an idle connection each 96 to\n * 120 s from its creation. Each check is `isValid`: pgjdbc sends one Query message with an empty\n * string, with a read timeout of `validationTimeout`. A read timeout or an I/O error closes the\n * socket.\n *\n * pgjdbc sends nothing on an idle connection. Its only read timeout is `socketTimeout`, which is\n * off at the defaults, thus no timer of pgjdbc bounds a statement or the startup. Its connect\n * timeout of 10 s bounds only the TCP connect and the SSLRequest. At sslmode `prefer` (the\n * default), a read timeout in the connect starts one more connect with SSL off, in what remains of\n * the 10 s.\n *\n * The JDK waits for a read or a connect with a timeout in poll(). Linux ends that wait up to 0.1 % of\n * its time late, at most 100 ms: 11 ms for a read timeout of 11 s (run 39109649303).\n *\n * HikariCP closes a connection at once when a statement fails with an SQLState of the class 08. It\n * also closes it for 57P01, 57P02, 57P03 and 0A000. pgjdbc gives 08006 for each I/O error of a\n * statement. Thus a reset, an end of the stream or a give-up of the kernel each close the\n * connection. HikariCP does not send a statement again.\n */\nexport const HIKARICP_PGJDBC: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"hikaricp-pgjdbc\",\n title: \"HikariCP 7.1.0 over pgjdbc 42.7.13: one connection of a pool, its creation, its checks, its statements and its lifetime\",\n layer: \"driver\",\n version: \"7.1.0\",\n conditions: {\n hikaricp: \"7.1.0\",\n pgjdbc: \"42.7.13\",\n client: \"a HikariDataSource with jdbcUrl, at the defaults of HikariCP and pgjdbc unless a knob says otherwise, with no connectionTestQuery\",\n transport: \"TCP to a host and port, at sslmode prefer against a server with no TLS: the server answers the SSLRequest with N, and the connection stays plain\",\n },\n sources: [\n { ref: `${HK}/HikariConfig.java:50-56, :115-134 the defaults: connectionTimeout 30 s, validationTimeout 5 s, idleTimeout 10 min, maxLifetime 30 min, keepaliveTime 2 min, maximumPoolSize 10`, rung: \"implemented\" },\n { ref: `${HK}/HikariConfig.java:120, :1137-1139 minimumIdle is maximumPoolSize when it is not set: a pool of a fixed size`, rung: \"implemented\" },\n { ref: `${HK}/HikariConfig.java:189-200, :351-358 a connectionTimeout of 0 is Integer.MAX_VALUE, and a timeout below 250 ms throws`, rung: \"implemented\" },\n { ref: `${HK}/HikariConfig.java:1101-1152 validateNumerics: a maxLifetime below 30 s is 30 min, a keepaliveTime below 30 s or at maxLifetime or above is off, an idleTimeout below 10 s is 10 min, and an idleTimeout has no effect in a pool of a fixed size`, rung: \"implemented\" },\n { ref: `${HK}/HikariConfig.java:745, :755 the javadoc of keepaliveTime gives 0 as its default, against the code (:55, :128)`, rung: \"documented\" },\n { ref: `${HK}/pool/HikariPool.java:62-64 aliveBypassWindowMs 500, housekeeping.periodMs 30000, lifeTimeVarianceFactor 4 (from 2 to 40)`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:118, :644-656 the housekeeper: one thread, 100 ms after the start and then a fixed delay of 30 s. It also runs each lifetime and keepalive task`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:793-851 each run of the housekeeper: idle eviction only when minimumIdle is below maximumPoolSize, then fillPool`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:490-496 the lifetime of each connection is maxLifetime less a variance of 0 to maxLifetime / lifeTimeVarianceFactor, drawn one time`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:498-504 the keepalive of each connection: a fixed delay of keepaliveTime less a variance of 0 to keepaliveTime / 5, drawn one time, from the creation`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:870-892 the keepalive checks only a connection that it can reserve (not in use): a dead one closes at once`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:853-868, :626-635 the end of a lifetime evicts an idle connection at once, and marks a connection in use, which closes at its return`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:152-193 getConnection: a borrow waits up to connectionTimeout, and a connection idle for more than aliveBypassWindowMs is checked first. A dead one closes, and the borrow goes on in the time that remains`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:183-184, :700-721 the timeout of a borrow: SQLTransientConnectionException 'Connection is not available, request timed out after', with the SQLState of the last failed creation`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:745-787 the creator: one connection at a time, with a backoff from 10 ms to 5000 ms after a failure`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:567-599 checkFailFast: at the start of the pool, one attempt, then a sleep of 1 s after a failure, until initializationFailTimeout passes. Then PoolInitializationException, with the error of the last attempt`, rung: \"implemented\" },\n { ref: `${HK}/HikariConfig.java:126 initializationFailTimeout 1 ms`, rung: \"implemented\" },\n { ref: `${HK}/util/UtilityElf.java:168-191 the adder and the closer each have one thread`, rung: \"implemented\" },\n { ref: `${HK}/pool/PoolBase.java:157-192 isConnectionDead: setNetworkTimeout(validationTimeout), then isValid(validationTimeout in whole seconds, at least 1). An exception or false is a dead connection`, rung: \"implemented\" },\n { ref: `${HK}/pool/PoolBase.java:416-456, :463-493 the setup of a new connection runs under setNetworkTimeout(validationTimeout), then gives back the network timeout of the driver`, rung: \"implemented\" },\n { ref: `${HK}/pool/PoolBase.java:360-408 HikariCP puts no timer around the connect of the driver`, rung: \"implemented\" },\n { ref: `${HK}/pool/PoolBase.java:639-649 and util/DriverDataSource.java:159-163 the login timeout that HikariCP gives goes to DriverManager, for the whole JVM`, rung: \"implemented\" },\n { ref: `${HK}/pool/PoolEntry.java:70, :77-83 lastAccessed changes only at the creation and at each return: a keepalive does not change it`, rung: \"implemented\" },\n { ref: `${HK}/pool/ProxyConnection.java:67-84, :151-186 checkException: the class 08, 0A000, 57P01, 57P02, 57P03, 01002, JZ0C0 and JZ0C1 close the connection at once, and the exception goes to the application`, rung: \"implemented\" },\n { ref: `${HK}/pool/ProxyConnection.java:538-564 a closed proxy throws 'Connection is closed' for each call`, rung: \"implemented\" },\n { ref: `${HK}/util/ClockSource.java:190-213 the clock is System.nanoTime() on Linux`, rung: \"implemented\" },\n { ref: `${PG}/PGProperty.java:205-214 connectTimeout 10 s, :746-755 socketTimeout 0, :441-448 loginTimeout 0, :908-920 tcpKeepAlive false and tcpNoDelay true, :139-148 cancelSignalTimeout 10 s, :586-592 queryTimeout 0, :862-869 sslResponseTimeout 5000 ms`, rung: \"implemented\" },\n { ref: `${PG}/Driver.java:730-740 and PGProperty.java:1046-1048 an unset loginTimeout is 0, thus the login timeout of DriverManager does not apply`, rung: \"derived\" },\n { ref: `${PG}/core/v3/ConnectionFactoryImpl.java:195-208, :221, :323-324 the connect budget: one deadline for each connect of the attempt, and 1 ms when it is spent`, rung: \"implemented\" },\n { ref: `${PG}/core/v3/ConnectionFactoryImpl.java:221-265 SO_TIMEOUT from socketTimeout, then SO_KEEPALIVE and TCP_NODELAY on each new socket`, rung: \"implemented\" },\n { ref: `${PG}/core/PGStream.java:255-283, :299-302 Socket.connect with the connect budget, and TCP_NODELAY on each socket`, rung: \"implemented\" },\n { ref: `${PG}/jdbc/SslMode.java:63-71 sslmode prefer when it is not set, and ConnectionFactoryImpl.java:646-720 the SSLRequest, with a read timeout of sslResponseTimeout`, rung: \"implemented\" },\n { ref: `${PG}/core/v3/ConnectionFactoryImpl.java:141-159, :365-455 a SocketTimeoutException at prefer connects again with SSL off. A refusal is 'Connection to … refused' and each other I/O error is 'The connection attempt failed.', both 08001`, rung: \"implemented\" },\n { ref: `${PG}/core/v3/ConnectionFactoryImpl.java:473-476, :1076-1121 after the startup, SET application_name as one more simple query`, rung: \"implemented\" },\n { ref: `${PG}/core/v3/QueryExecutorImpl.java:471-475, :2880-2884 and core/QueryExecutorCloseAction.java:42-54 each I/O error of a statement closes the socket with no Terminate: 08006 'An I/O error occurred while sending to the backend.'`, rung: \"implemented\" },\n { ref: `${PG}/core/v3/QueryExecutorImpl.java:2654-2669, :2977-3000 an ErrorResponse is a PSQLException with the SQLState of the server`, rung: \"implemented\" },\n { ref: `${PG}/jdbc/PgConnection.java:1578-1621 and core/v3/QueryExecutorImpl.java:2253-2274 isValid sends a simple Query with the empty string, and true needs its ReadyForQuery`, rung: \"implemented\" },\n { ref: `${PG}/jdbc/PgConnection.java:1788-1806 and core/PGStream.java:738-745 setNetworkTimeout is SO_TIMEOUT`, rung: \"implemented\" },\n { ref: `${PG}/jdbc/PgStatement.java:532-537, :1032-1048 and core/QueryExecutorBase.java:189-230 a query timeout is a task of java.util.Timer that sends a CancelRequest on a new connection`, rung: \"implemented\" },\n { ref: `${PG}/jdbc/PgConnection.java:1048-1053 after a close, each call fails with 'This connection has been closed.', 08003, and :1251-1253 isClosed tells only of a close at this end`, rung: \"implemented\" },\n { ref: `${PG}/core/QueryExecutorCloseAction.java:42-93 a close sends Terminate with a read timeout of at most 1000 ms`, rung: \"implemented\" },\n { ref: \"the JDK: SO_TIMEOUT bounds each blocking read and not a write, and a read that gets data starts its time again\", rung: \"derived\" },\n { ref: \"jdk-21.0.12+8 src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java:172-191, :270-304, :548: a read or a connect with a timeout waits in poll() (Net.poll), with the time that remains\", rung: \"implemented\" },\n { ref: \"linux v6.6 fs/select.c:39-50, :51-95, :902: the timeout of poll() gets a slack of 0.1 % of itself, at most 100 ms (0.5 % for a nice task), and at least the timer slack of the task\", rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"Before the pool creates the connection, or before a borrow gets one\" },\n waiting: { note: \"A borrow of the application waits in the bag for a connection, up to connectionTimeout (HikariPool.java:152-193)\" },\n connecting: { note: \"The TCP connect of a new connection, with TCP_NODELAY and no keepalive at the defaults (PGStream.java:255-283)\" },\n \"start-check\": {\n note: \"The start of the pool after a failed attempt of its check: a sleep of 1 s, then one more attempt while initializationFailTimeout has not passed (HikariPool.java:567-599)\",\n },\n negotiating: { note: \"The SSLRequest of sslmode prefer and its answer, with a read timeout of sslResponseTimeout (ConnectionFactoryImpl.java:646-720)\" },\n startup: {\n note: \"The startup message, the authentication, the first ReadyForQuery and SET application_name. Only socketTimeout bounds a read here, and it is off at the defaults\",\n },\n setup: { note: \"The setup of HikariCP on the new connection, under a read timeout of validationTimeout (PoolBase.java:416-456)\" },\n pooled: { note: \"An idle connection in the bag, which nothing reads (HikariPool.java:870-892)\" },\n checking: { note: \"The check of a borrow: isValid, with a read timeout of validationTimeout. The borrow waits for it (HikariPool.java:166-169)\" },\n probing: { note: \"The keepalive: isValid on a reserved idle connection, with a read timeout of validationTimeout (HikariPool.java:870-892)\" },\n held: { note: \"A connection that the application holds, with no statement in flight. Nothing reads its socket\" },\n querying: { note: \"A statement in flight: pgjdbc waits for its ReadyForQuery, with a read timeout of socketTimeout\" },\n cancelling: { note: \"The query timeout fired, and pgjdbc sent a CancelRequest on a new connection. The statement waits for the answer of the server (PgStatement.java:1032-1048)\" },\n ended: {\n final: true,\n note: \"The pool closed the connection, or its creation failed. A call on its proxy fails with 'Connection is closed' (ProxyConnection.java:538-564)\",\n },\n },\n events: {\n \"app.borrow\": { kind: \"app\", note: \"The application calls getConnection\" },\n \"app.statement\": { kind: \"app\", note: \"The application runs a statement on the connection\" },\n \"app.close\": { kind: \"app\", note: \"The application closes the connection: it goes back to the pool\" },\n \"local.create\": { kind: \"local\", note: \"The adder of the pool starts a new connection: to fill the pool, or for a waiting borrow (HikariPool.java:525-538, :745-787)\" },\n \"local.handout\": { kind: \"local\", note: \"The bag gives an idle connection to a waiting borrow (ConcurrentBag.java:161-205)\" },\n \"socket.connect\": { kind: \"local\" },\n \"rx.ssl-refused\": { kind: \"rx\", note: \"The server answers the SSLRequest with N: the connection stays plain\" },\n \"local.connected\": { kind: \"local\", note: \"The connect of pgjdbc returns: the first ReadyForQuery and the initial queries\" },\n \"local.created\": { kind: \"local\", note: \"The setup of HikariCP ends, and the connection goes into the bag\" },\n \"rx.valid\": { kind: \"rx\", note: \"The EmptyQueryResponse and the ReadyForQuery of isValid\" },\n \"rx.ready-for-query\": { kind: \"rx\", note: \"The ReadyForQuery that ends a statement\" },\n \"rx.error-response\": { kind: \"rx\", note: \"An ErrorResponse of the server: a PSQLException with the SQLState of the server\" },\n \"peer.fin\": { kind: \"peer\", note: \"The server or a middlebox closes the connection: a read gets the end of the stream\" },\n \"peer.rst\": { kind: \"peer\", note: \"A reset of the connection: a read or a write fails\" },\n \"socket.error\": { kind: \"local\", note: \"The socket fails with its own error: a reset, an ICMP error or a give-up of the kernel\" },\n \"tx.ssl-request\": { kind: \"tx\", note: \"The SSLRequest of sslmode prefer\" },\n \"tx.empty-query\": { kind: \"tx\", note: \"The empty simple Query of isValid\" },\n \"tx.cancel\": { kind: \"tx\", note: \"A CancelRequest on a new TCP connection to the server (QueryExecutorBase.java:189-230)\" },\n \"tx.terminate\": { kind: \"tx\", note: \"The Terminate message, then the close of the socket (QueryExecutorCloseAction.java:42-93)\" },\n \"timer.connect-timeout\": { kind: \"timer\", note: \"Socket.connect throws SocketTimeoutException\" },\n \"timer.ssl-response-timeout\": { kind: \"timer\", note: \"The read of the answer to the SSLRequest throws SocketTimeoutException\" },\n \"timer.socket-timeout\": { kind: \"timer\", note: \"A read of a statement throws SocketTimeoutException: pgjdbc closes the socket\" },\n \"timer.validation-timeout\": { kind: \"timer\", note: \"A read of isValid or of the setup throws SocketTimeoutException: pgjdbc closes the socket\" },\n \"timer.query-timeout\": { kind: \"timer\", note: \"The query timeout of the statement: pgjdbc sends a CancelRequest\" },\n \"timer.connection-timeout\": { kind: \"timer\", note: \"The borrow fails: 'Connection is not available, request timed out after'\" },\n \"timer.keepalive\": { kind: \"timer\", note: \"The keepalive task of the connection\" },\n \"timer.max-lifetime\": { kind: \"timer\", note: \"The lifetime of the connection ends\" },\n \"timer.idle\": { kind: \"timer\", note: \"A run of the housekeeper finds the connection idle for more than idleTimeout\" },\n \"timer.start-check\": { kind: \"timer\", note: \"The sleep of 1 s of the start check ends\" },\n },\n knobs: {\n connectionTimeout: {\n key: \"HikariCP connectionTimeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 30000,\n off: 0,\n note: \"HikariConfig.java:50, :189-200: the most that a borrow waits. 0 is Integer.MAX_VALUE, and a value below 250 ms throws\",\n },\n validationTimeout: {\n key: \"HikariCP validationTimeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 5000,\n note: \"HikariConfig.java:51, :351-358: the read timeout of each check and of the setup. isValid gets it in whole seconds, at least 1 (PoolBase.java:157-192)\",\n },\n idleTimeout: {\n key: \"HikariCP idleTimeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 600000,\n off: 0,\n note: \"HikariConfig.java:53, :1141-1151: it has an effect only when minimumIdle is below maximumPoolSize. Then a value below 10 s is 10 min\",\n },\n maxLifetime: {\n key: \"HikariCP maxLifetime\",\n scope: \"client\",\n unit: \"ms\",\n default: 1800000,\n off: 0,\n note: \"HikariConfig.java:54, :1103-1106: a value below 30 s is 30 min\",\n },\n keepaliveTime: {\n key: \"HikariCP keepaliveTime\",\n scope: \"client\",\n unit: \"ms\",\n default: 120000,\n off: 0,\n note: \"HikariConfig.java:55, :1108-1118: a value below 30 s, or at maxLifetime or above, turns the keepalive off\",\n },\n idle_eviction: {\n key: \"the idle eviction time of the pool\",\n scope: \"client\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"A value of this document. The idle timer has an effect only when minimumIdle is below maximumPoolSize: then give idleTimeout. At the defaults the pool has a fixed size, thus 0 (off)\",\n },\n maximumPoolSize: { key: \"HikariCP maximumPoolSize\", scope: \"client\", unit: \"count\", default: 10, note: \"HikariConfig.java:56\" },\n initializationFailTimeout: {\n key: \"HikariCP initializationFailTimeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 1,\n note: \"HikariConfig.java:126. Below 0, the pool does no check at its start. At 0, the pool starts after a failed check. Above 0, the check tries again each 1 s while it has not passed, and then the start fails (HikariPool.java:567-599). At 1 ms, the start fails after one attempt and one sleep\",\n },\n minimumIdle: {\n key: \"HikariCP minimumIdle\",\n scope: \"client\",\n unit: \"count\",\n default: 10,\n note: \"HikariConfig.java:120, :1137-1139: maximumPoolSize when it is not set, thus a pool of a fixed size\",\n },\n lifeTimeVarianceFactor: {\n key: \"the system property com.zaxxer.hikari.lifeTimeVarianceFactor\",\n scope: \"process\",\n unit: \"count\",\n default: 4,\n note: \"HikariPool.java:64: from 2 to 40. The variance of a lifetime is up to 100 / factor percent\",\n },\n housekeepingPeriodMs: {\n key: \"the system property com.zaxxer.hikari.housekeeping.periodMs\",\n scope: \"process\",\n unit: \"ms\",\n default: 30000,\n note: \"HikariPool.java:63. The README names it housekeeping.period, but the code reads housekeeping.periodMs\",\n },\n aliveBypassWindowMs: {\n key: \"the system property com.zaxxer.hikari.aliveBypassWindowMs\",\n scope: \"process\",\n unit: \"ms\",\n default: 500,\n note: \"HikariPool.java:62: a borrow checks a connection only when it was idle for longer\",\n },\n connectTimeout: {\n key: \"pgjdbc connectTimeout\",\n scope: \"client\",\n unit: \"s\",\n default: 10,\n off: 0,\n note: \"PGProperty.java:205-214: the TCP connect and the SSLRequest of each attempt, with its connects again (ConnectionFactoryImpl.java:195-208)\",\n },\n socketTimeout: {\n key: \"pgjdbc socketTimeout\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"PGProperty.java:746-755: SO_TIMEOUT for each read of the startup and of a statement\",\n },\n sslResponseTimeout: {\n key: \"pgjdbc sslResponseTimeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 5000,\n note: \"PGProperty.java:862-869: the read timeout of the answer to the SSLRequest\",\n },\n queryTimeout: {\n key: \"pgjdbc queryTimeout\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"PGProperty.java:586-592: the query timeout of each statement. At its end, pgjdbc sends a CancelRequest\",\n },\n cancelSignalTimeout: {\n key: \"pgjdbc cancelSignalTimeout\",\n scope: \"client\",\n unit: \"s\",\n default: 10,\n note: \"PGProperty.java:139-148: the connect timeout and the read timeout of the connection of a CancelRequest\",\n },\n tcpKeepAlive: {\n key: \"pgjdbc tcpKeepAlive\",\n scope: \"client\",\n unit: null,\n default: 0,\n note: \"PGProperty.java:908-914: off. When it is on, pgjdbc sets SO_KEEPALIVE and no other option, thus the keepalive sysctls of the namespace apply\",\n },\n keepalive_idle: {\n key: \"the keepalive idle time of the socket of pgjdbc\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"A value of this document. 0 is no keepalive, as at the defaults. With tcpKeepAlive on, give tcp_keepalive_time of the namespace\",\n },\n slack: {\n key: \"the lateness of a timer or a thread of the JVM for one step\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of HikariCP or pgjdbc\",\n },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"The build option of the kernel: the keepalive of the socket is the kernel's, thus the timer wheel rounds its firings\",\n },\n },\n timers: {\n connect_timeout: {\n duration: { knob: \"connectTimeout\", unit: \"s\" },\n lateness: { expr: \"min(connectTimeout, 100) + slack\", unit: \"ms\" },\n arms: [\"enter:connecting\"],\n cancels: [\"socket.connect\", \"socket.error\", \"peer.rst\"],\n fires: \"timer.connect-timeout\",\n note: \"Socket.connect with what remains of the budget of the attempt. The negotiating state reads the same budget for its SSLRequest\",\n },\n ssl_response_timeout: {\n duration: { expr: \"min(sslResponseTimeout, connectTimeout * 1000)\", unit: \"ms\" },\n lateness: { expr: \"min(min(sslResponseTimeout, connectTimeout * 1000), 100000) / 1000 + slack\", unit: \"ms\" },\n arms: [\"enter:negotiating\"],\n cancels: [\"rx.ssl-refused\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.ssl-response-timeout\",\n note: \"ConnectionFactoryImpl.java:660-670, :683: the smaller of sslResponseTimeout and the read timeout that the socket has. The connect budget of the attempt also bounds it\",\n },\n socket_timeout: {\n duration: { knob: \"socketTimeout\", unit: \"s\" },\n lateness: { expr: \"min(socketTimeout, 100) + slack\", unit: \"ms\" },\n arms: [\"enter:startup\", \"enter:querying\"],\n cancels: [\"local.connected\", \"rx.ready-for-query\", \"rx.error-response\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.socket-timeout\",\n note: \"SO_TIMEOUT: each read that gets data starts it again. No bound at the defaults. The JDK waits for the read in poll(), thus Linux can end the wait 0.1 % of its time late, at most 100 ms\",\n },\n validation_timeout: {\n duration: { knob: \"validationTimeout\", unit: \"ms\" },\n lateness: { expr: \"min(validationTimeout, 100000) / 1000 + slack\", unit: \"ms\" },\n arms: [\"enter:setup\", \"enter:checking\", \"enter:probing\"],\n cancels: [\"local.created\", \"rx.valid\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.validation-timeout\",\n note: \"PoolBase.java:157-192, :416-456: setNetworkTimeout(validationTimeout) is SO_TIMEOUT for each read of the check or of the setup\",\n },\n query_timeout: {\n duration: { knob: \"queryTimeout\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:querying\"],\n cancels: [\"rx.ready-for-query\", \"rx.error-response\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.query-timeout\",\n note: \"PgStatement.java:1032-1048: a task of java.util.Timer for each statement. No bound at the defaults\",\n },\n connection_timeout: {\n duration: { knob: \"connectionTimeout\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:waiting\"],\n cancels: [\"local.handout\"],\n fires: \"timer.connection-timeout\",\n note: \"HikariPool.java:152-193: one bound for the whole borrow, with each check and each wait in it. A check that fails takes its time from it\",\n },\n keepalive: {\n duration: { knob: \"keepaliveTime\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n early: { expr: \"keepaliveTime / 5\", unit: \"ms\" },\n arms: [\"local.created\", \"rx.valid\", \"timer.keepalive\"],\n fires: \"timer.keepalive\",\n note: \"HikariPool.java:498-504: a fixed delay from the creation, of keepaliveTime less a variance drawn one time for the connection. The next delay counts from the end of the last task, also when the task skipped a connection in use. A use of the connection does not move it. Thus the entry to a state does not arm it, and its first firing after a failure can come at any time in one delay: a cell times it from its empty query on the wire. The task of each connection runs on the one thread of the housekeeper (HikariPool.java:644-656, :879-891). A check that waits for its read timeout delays each task that comes due after it: behind a silent fault, the check of one connection can wait for the checks of the others\",\n },\n max_lifetime: {\n duration: { knob: \"maxLifetime\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n early: { expr: \"maxLifetime / lifeTimeVarianceFactor\", unit: \"ms\" },\n arms: [\"local.created\"],\n fires: \"timer.max-lifetime\",\n note: \"HikariPool.java:490-496: one time, at maxLifetime less a variance drawn one time for the connection: 22.5 to 30 min at the defaults\",\n },\n start_check: {\n duration: { const: 1000, unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:start-check\"],\n fires: \"timer.start-check\",\n note: \"HikariPool.java:592: quietlySleep of 1 s after each failed attempt of the check, on the thread that starts the pool\",\n },\n idle_timeout: {\n duration: { knob: \"idle_eviction\", unit: \"ms\" },\n lateness: { knob: \"housekeepingPeriodMs\", unit: \"ms\" },\n arms: [\"enter:pooled\"],\n cancels: [\"app.borrow\", \"timer.keepalive\", \"timer.max-lifetime\"],\n fires: \"timer.idle\",\n note: \"HikariPool.java:830-841: a run of the housekeeper closes a connection idle for longer than idleTimeout, thus up to one period late. Only when minimumIdle is below maximumPoolSize: at the defaults, no effect\",\n },\n },\n realizes: {\n \"systems.mechanism.connect-bound\": { timer: \"connect_timeout\" },\n \"systems.mechanism.pool-idle-expiry\": { timer: \"idle_timeout\" },\n \"systems.mechanism.request-timeout\": { timer: \"socket_timeout\" },\n \"systems.mechanism.max-connection-age\": { timer: \"max_lifetime\" },\n \"systems.mechanism.idle-refresh-interval\": {\n duration: { knob: \"keepaliveTime\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n early: { expr: \"keepaliveTime / 5\", unit: \"ms\" },\n note: \"The keepalive of the pool: an empty query on an idle connection, each 96 to 120 s at the defaults. A connection in use gets no keepalive\",\n },\n },\n transitions: [\n { id: \"hk.create\", from: \"[none]\", to: \"connecting\", on: \"local.create\", timer: \"connect_timeout\", source: \"HikariPool.java:745-787, PGStream.java:255-283\" },\n {\n id: \"hk.wait\",\n from: \"[none]\",\n to: \"waiting\",\n on: \"app.borrow\",\n timer: \"connection_timeout\",\n note: \"A borrow with an idle connection in the bag gets it at once, and the bag starts a creation when the borrow must wait\",\n source: \"HikariPool.java:152-193, ConcurrentBag.java:161-205\",\n },\n { id: \"hk.handout\", from: \"waiting\", to: \"held\", on: \"local.handout\", guard: \"the connection was idle for no more than aliveBypassWindowMs\", source: \"HikariPool.java:166-178\" },\n {\n id: \"hk.borrow-timed-out\",\n from: \"waiting\",\n to: \"ended\",\n on: \"timer.connection-timeout\",\n timer: \"connection_timeout\",\n errno: \"SQLTransientConnectionException\",\n note: \"'Connection is not available, request timed out after', with the SQLState of the last failed creation (08001 when the connects failed)\",\n source: \"HikariPool.java:183-184, :700-721\",\n },\n {\n id: \"hk.tcp-connected\",\n from: \"connecting\",\n to: \"negotiating\",\n on: \"socket.connect\",\n timer: \"ssl_response_timeout\",\n emits: [\"tx.ssl-request\"],\n source: \"ConnectionFactoryImpl.java:221-283, :646-720\",\n },\n {\n id: \"hk.refused\",\n from: \"connecting\",\n to: \"ended\",\n on: \"peer.rst\",\n errno: \"08001\",\n note: \"'Connection to … refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.' The creator tries again after its backoff\",\n source: \"ConnectionFactoryImpl.java:416-429, HikariPool.java:745-776\",\n },\n {\n id: \"hk.connect-timed-out\",\n from: \"connecting\",\n to: \"ended\",\n on: \"timer.connect-timeout\",\n timer: \"connect_timeout\",\n errno: \"08001\",\n note: \"At prefer, the SocketTimeoutException starts one more connect with SSL off, with 1 ms of the budget left. It fails: 'The connection attempt failed.'\",\n source: \"ConnectionFactoryImpl.java:141-159, :195-208, :378-382, :430-440\",\n },\n {\n id: \"hk.start-attempt-failed\",\n from: \"connecting\",\n to: \"start-check\",\n on: [\"peer.rst\", \"socket.error\", \"timer.connect-timeout\"],\n guard: \"the attempt is the check at the start of the pool, and initializationFailTimeout is 0 or more\",\n timer: \"start_check\",\n note: \"The attempt fails with 08001, and the start of the pool sleeps 1 s\",\n source: \"HikariPool.java:567-599, ConnectionFactoryImpl.java:365-455\",\n },\n {\n id: \"hk.start-failed\",\n from: \"start-check\",\n to: \"ended\",\n on: \"timer.start-check\",\n timer: \"start_check\",\n guard: \"initializationFailTimeout has passed, and it is above 0\",\n errno: \"PoolInitializationException\",\n note: \"'Failed to initialize pool:' with the error of the last attempt as its cause: 08001 for a connect. The constructor of HikariDataSource throws it\",\n source: \"HikariPool.java:592-598, :898-910\",\n },\n {\n id: \"hk.start-again\",\n from: \"start-check\",\n to: \"connecting\",\n on: \"timer.start-check\",\n timer: \"connect_timeout\",\n guard: \"initializationFailTimeout has not passed\",\n source: \"HikariPool.java:574-593\",\n },\n {\n id: \"hk.connect-failed\",\n from: \"connecting\",\n to: \"ended\",\n on: \"socket.error\",\n errno: \"08001\",\n note: \"'The connection attempt failed.': an ICMP error or a give-up of the kernel\",\n source: \"ConnectionFactoryImpl.java:430-440\",\n },\n { id: \"hk.plain\", from: \"negotiating\", to: \"startup\", on: \"rx.ssl-refused\", timer: \"socket_timeout\", source: \"ConnectionFactoryImpl.java:698-707, :290-309\" },\n {\n id: \"hk.ssl-timed-out\",\n from: \"negotiating\",\n to: \"connecting\",\n on: \"timer.ssl-response-timeout\",\n timer: \"connect_timeout\",\n note: \"A new socket, with SSL off, in what remains of the connect budget\",\n source: \"ConnectionFactoryImpl.java:141-159, :378-382\",\n },\n {\n id: \"hk.negotiation-failed\",\n from: \"negotiating\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\"],\n errno: \"08001\",\n source: \"ConnectionFactoryImpl.java:430-440\",\n },\n { id: \"hk.started\", from: \"startup\", to: \"setup\", on: \"local.connected\", timer: \"validation_timeout\", source: \"ConnectionFactoryImpl.java:398, :412, PoolBase.java:416-456\" },\n {\n id: \"hk.startup-failed\",\n from: \"startup\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\", \"rx.error-response\", \"timer.socket-timeout\"],\n errno: \"08001\",\n note: \"An ErrorResponse gives the SQLState of the server instead. At the defaults no timer bounds the startup: a server that stops answering holds it until the kernel gives up\",\n source: \"ConnectionFactoryImpl.java:365-455\",\n },\n { id: \"hk.created\", from: \"setup\", to: \"pooled\", on: \"local.created\", timer: \"keepalive\", source: \"PoolBase.java:416-456, HikariPool.java:490-504\" },\n {\n id: \"hk.setup-failed\",\n from: \"setup\",\n to: \"ended\",\n on: [\"timer.validation-timeout\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n errno: \"08006\",\n note: \"A ConnectionSetupException. At the start of the pool it ends the check of initializationFailTimeout at once (HikariPool.java:567-599)\",\n source: \"PoolBase.java:416-456, QueryExecutorImpl.java:471-475\",\n },\n {\n id: \"hk.borrow\",\n from: \"pooled\",\n to: \"held\",\n on: \"app.borrow\",\n guard: \"the connection was idle for no more than aliveBypassWindowMs\",\n note: \"No check: a dead connection goes out, and its first statement fails\",\n source: \"HikariPool.java:152-178\",\n },\n {\n id: \"hk.borrow-check\",\n from: \"pooled\",\n to: \"checking\",\n on: \"app.borrow\",\n guard: \"the connection was idle for more than aliveBypassWindowMs\",\n timer: \"validation_timeout\",\n emits: [\"tx.empty-query\"],\n source: \"HikariPool.java:166-169, PoolBase.java:157-192, PgConnection.java:1578-1621\",\n },\n { id: \"hk.checked\", from: \"checking\", to: \"held\", on: \"rx.valid\", source: \"PgConnection.java:1578-1621, HikariPool.java:170-178\" },\n {\n id: \"hk.check-failed\",\n from: \"checking\",\n to: \"ended\",\n on: [\"timer.validation-timeout\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n note: \"'(connection is dead)': the pool closes it, and the borrow takes another connection in what remains of connectionTimeout. The application sees no error\",\n source: \"HikariPool.java:166-169, PoolBase.java:157-192\",\n },\n {\n id: \"hk.keepalive\",\n from: \"pooled\",\n to: \"probing\",\n on: \"timer.keepalive\",\n timer: \"validation_timeout\",\n emits: [\"tx.empty-query\"],\n source: \"HikariPool.java:870-892, PoolBase.java:157-192\",\n },\n { id: \"hk.alive\", from: \"probing\", to: \"pooled\", on: \"rx.valid\", timer: \"keepalive\", source: \"HikariPool.java:886-890\" },\n {\n id: \"hk.probe-failed\",\n from: \"probing\",\n to: \"ended\",\n on: [\"timer.validation-timeout\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n note: \"'(connection is dead)': the pool closes it at once, and creates another to fill the pool\",\n source: \"HikariPool.java:879-885\",\n },\n {\n id: \"hk.keepalive-skipped\",\n from: \"held\",\n to: \"held\",\n on: \"timer.keepalive\",\n timer: \"keepalive\",\n note: \"The task cannot reserve a connection in use: it does nothing, and the next delay starts\",\n source: \"HikariPool.java:870-878\",\n },\n {\n id: \"hk.statement\",\n from: \"held\",\n to: \"querying\",\n on: \"app.statement\",\n timer: \"socket_timeout\",\n source: \"QueryExecutorImpl.java:471-475\",\n },\n { id: \"hk.replied\", from: \"querying\", to: \"held\", on: \"rx.ready-for-query\", source: \"QueryExecutorImpl.java:2880-2884\" },\n {\n id: \"hk.statement-failed\",\n from: \"querying\",\n to: \"held\",\n on: \"rx.error-response\",\n guard: \"the SQLState is not on the list of checkException\",\n errno: \"PSQLException\",\n note: \"The SQLState of the server, for example 57014 for a statement that the server cancelled. HikariCP keeps the connection\",\n source: \"QueryExecutorImpl.java:2654-2669, ProxyConnection.java:151-186\",\n },\n {\n id: \"hk.statement-fatal\",\n from: \"querying\",\n to: \"ended\",\n on: \"rx.error-response\",\n guard: \"the SQLState is of the class 08, or 57P01, 57P02 or 57P03\",\n errno: \"PSQLException\",\n note: \"HikariCP closes the connection at once and gives the exception to the application: an administrator or the server ended the session\",\n source: \"ProxyConnection.java:67-84, :151-186\",\n },\n {\n id: \"hk.statement-broken\",\n from: \"querying\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\", \"timer.socket-timeout\"],\n errno: \"08006\",\n note: \"'An I/O error occurred while sending to the backend.': pgjdbc closes the socket with no Terminate, and HikariCP closes the connection. The application gets the exception, and nothing sends the statement again\",\n source: \"QueryExecutorImpl.java:471-475, QueryExecutorCloseAction.java:42-54, ProxyConnection.java:151-186\",\n },\n {\n id: \"hk.query-timed-out\",\n from: \"querying\",\n to: \"cancelling\",\n on: \"timer.query-timeout\",\n timer: \"query_timeout\",\n emits: [\"tx.cancel\"],\n note: \"A server that is not reachable does not get the cancel: its connection fails in cancelSignalTimeout, and pgjdbc ignores the failure\",\n source: \"PgStatement.java:1032-1048, QueryExecutorBase.java:189-230\",\n },\n {\n id: \"hk.cancelled\",\n from: \"cancelling\",\n to: \"held\",\n on: [\"rx.error-response\", \"rx.ready-for-query\"],\n errno: \"57014\",\n note: \"The server ends the statement: 'canceling statement due to user request'. A reply that came first ends it with no error\",\n source: \"QueryExecutorImpl.java:2654-2669\",\n },\n {\n id: \"hk.cancel-broken\",\n from: \"cancelling\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\", \"timer.socket-timeout\"],\n errno: \"08006\",\n source: \"QueryExecutorImpl.java:471-475\",\n },\n {\n id: \"hk.return\",\n from: \"held\",\n to: \"pooled\",\n on: \"app.close\",\n guard: \"the pool did not mark the connection evicted\",\n timer: \"idle_timeout\",\n source: \"PoolEntry.java:77-83, HikariPool.java:434-439\",\n },\n {\n id: \"hk.return-evicted\",\n from: \"held\",\n to: \"ended\",\n on: \"app.close\",\n guard: \"the pool marked the connection evicted: its lifetime ended while it was in use\",\n emits: [\"tx.terminate\"],\n source: \"HikariPool.java:434-439, :626-635\",\n },\n {\n id: \"hk.lifetime-held\",\n from: \"held\",\n to: \"held\",\n on: \"timer.max-lifetime\",\n timer: \"max_lifetime\",\n note: \"The pool marks the connection evicted. It closes at its return\",\n source: \"HikariPool.java:853-868, :626-635\",\n },\n {\n id: \"hk.lifetime\",\n from: \"pooled\",\n to: \"ended\",\n on: \"timer.max-lifetime\",\n timer: \"max_lifetime\",\n emits: [\"tx.terminate\"],\n note: \"'(connection has passed maxLifetime)': the pool closes the idle connection at once, and creates another to fill the pool\",\n source: \"HikariPool.java:853-868, PoolBase.java:137-155\",\n },\n {\n id: \"hk.idle-evicted\",\n from: \"pooled\",\n to: \"ended\",\n on: \"timer.idle\",\n timer: \"idle_timeout\",\n guard: \"minimumIdle is below maximumPoolSize, and the pool has more than minimumIdle idle connections\",\n emits: [\"tx.terminate\"],\n note: \"'(connection has passed idleTimeout)'\",\n source: \"HikariPool.java:830-841\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: {\n connecting: \"SYN_SENT\",\n negotiating: \"ESTABLISHED\",\n startup: \"ESTABLISHED\",\n setup: \"ESTABLISHED\",\n pooled: \"ESTABLISHED\",\n checking: \"ESTABLISHED\",\n probing: \"ESTABLISHED\",\n held: \"ESTABLISHED\",\n querying: \"ESTABLISHED\",\n cancelling: \"ESTABLISHED\",\n },\n sets: {\n keepidle: { knob: \"keepalive_idle\", unit: \"s\" },\n },\n ends: \"socket.error\",\n note: \"Each socket of pgjdbc is a Linux TCP socket with TCP_NODELAY. At the defaults no socket has keepalive, thus keepidle has no bound. With tcpKeepAlive on, pgjdbc sets SO_KEEPALIVE only, thus the interval and the count of the namespace apply\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the JavaScript source of the npm packages pg at 8.23.1 (under\n// lib/), pg-pool at 3.14.0 and pg-protocol at 1.16.1 (under dist/), as npm publishes them. Each\n// line number is a line of that file in the package. Node's own facts are from the source of node\n// at the tag v24.21.0.\nconst AT = \"pg 8.23.1 lib\";\nconst POOL = \"pg-pool 3.14.0\";\nconst PROTOCOL = \"pg-protocol 1.16.1 dist\";\n\n/**\n * This document is node-postgres 8.23.1 (the npm package pg) with pg-pool 3.14.0, for one client\n * of a `pg.Pool`. It gives the states of the client, from its connect to its end, and the timers\n * that act on it. The pool hands out an idle client with no test of its connection. At the\n * defaults, the client turns no keepalive on and sends nothing on an idle connection. Neither\n * package sends a query again, and neither package connects again by itself.\n *\n * A knob of pg at 0 or false has no timer: give it as no bound (`infinite`). This is true of\n * `connectionTimeoutMillis`, `query_timeout`, `maxLifetimeSeconds` and `idleTimeoutMillis`. At the\n * defaults of a pool, only the idle timer of the pool runs, for 10000 ms. Thus no timer of pg\n * bounds the connect, the startup, a checkout from a full pool or a query.\n *\n * Three timeouts are not timers of the client: `statement_timeout`, `lock_timeout` and\n * `idle_in_transaction_session_timeout`. The client sends each one to the server in the startup\n * message, and only when it is set.\n *\n * The pool emits `error` when an idle client fails. A client that the application holds emits\n * `error` itself, and the pool does not listen to it. In Node, an `error` event with no listener\n * throws.\n */\nexport const NODE_POSTGRES: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"node-postgres\",\n title: \"node-postgres 8.23.1 with pg-pool 3.14.0: one client of a pg.Pool, its connect, its queries and its idle time\",\n layer: \"driver\",\n version: \"8.23.1\",\n conditions: {\n pg: \"8.23.1\",\n \"pg-pool\": \"3.14.0\",\n \"pg-protocol\": \"1.16.1\",\n node: \"24.21.0\",\n client: \"a pg.Pool with the defaults of pg-pool and pg, unless a knob says otherwise: the JavaScript client, not pg-native\",\n transport: \"TCP to a host and port, with no TLS (ssl false, and no PGSSLMODE) and no pipeline mode\",\n },\n sources: [\n { ref: `${POOL}/index.js:89-93 max 10, min 0, maxUses Infinity, allowExitOnIdle false, maxLifetimeSeconds 0, :98-100 idleTimeoutMillis 10000 when it is undefined`, rung: \"implemented\" },\n { ref: `${AT}/defaults.js:42 max 10 and :46 idleTimeoutMillis 30000: no line of pg or pg-pool reads them, thus a pool does not use them`, rung: \"implemented\" },\n { ref: `${AT}/defaults.js:65, :69, :73 and :76 statement_timeout, lock_timeout, idle_in_transaction_session_timeout and query_timeout are false`, rung: \"implemented\" },\n { ref: `${AT}/defaults.js:63-76 the comments of pg: each of the four is in milliseconds, false is no limit, and query_timeout is on the client side`, rung: \"documented\" },\n { ref: `${AT}/connection-parameters.js:9-23 val: the config, else the default of pg, :121-124 the three timeouts of the server and query_timeout, with no environment variable`, rung: \"implemented\" },\n { ref: `${AT}/client.js:89-98 the Connection gets keepAlive false and keepAliveInitialDelayMillis 0 when the config does not give them, :116 connectionTimeoutMillis 0`, rung: \"implemented\" },\n { ref: `${AT}/stream.js:20-24 and :78-83 outside Cloudflare Workers, the socket is a new net.Socket with no option`, rung: \"implemented\" },\n { ref: `${AT}/connection.js:40-52 setNoDelay(true) before the connect, and setKeepAlive(true, keepAliveInitialDelayMillis) at the connect only when keepAlive is true, :54-65 the error and the close of the socket`, rung: \"implemented\" },\n { ref: `${AT}/client.js:167-176 and :702-737 are the only timers of the client, and connection.js has none: the client sends nothing by itself on an idle connection`, rung: \"implemented\" },\n { ref: `${AT}/client.js:153-230 _connect: no second connect, the connect timer of the client ('timeout expired'), and 'Connection terminated unexpectedly' for an end that the client did not ask for`, rung: \"implemented\" },\n { ref: `${AT}/client.js:373-387 the first ReadyForQuery ends the connect and clears the timer, :398-423 an error before it goes to the connect callback, and an error after it makes the client unqueryable`, rung: \"implemented\" },\n { ref: `${AT}/client.js:426-442 an ErrorResponse fails the active query only, and with no active query it is an error of the client`, rung: \"implemented\" },\n { ref: `${AT}/connection.js:137-145 and ${PROTOCOL}/parser.js:142-144, :296-323 an ErrorResponse is a DatabaseError, with the severity and the code that the server gives`, rung: \"implemented\" },\n { ref: `${AT}/client.js:133-151 _errorAllQueries: each query of the client fails with the same error, on the next tick`, rung: \"implemented\" },\n { ref: `${AT}/query.js:122-150 a query gives its error or its result to its callback, at the error or at the ReadyForQuery`, rung: \"implemented\" },\n { ref: `${AT}/client.js:702-737 query_timeout: a Node timer for each query, 'Query read timeout'. The client sends no cancel, and it keeps the active query`, rung: \"implemented\" },\n { ref: `${AT}/client.js:616-641 the next query goes only after a ReadyForQuery, :765-777 a query on an unqueryable or ended client fails at once`, rung: \"implemented\" },\n { ref: `${AT}/client.js:799-836 end: a dead socket or an active query destroys the socket, else connection.js:217-227 sends Terminate and ends the socket`, rung: \"implemented\" },\n { ref: `${AT}/client.js:543-572 getStartupConf: statement_timeout, lock_timeout and idle_in_transaction_session_timeout go to the server only when they are set`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:190-238 connect: a checkout from a full pool waits in the queue with no bound at connectionTimeoutMillis 0, else 'timeout exceeded when trying to connect'`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:240-309 newClient: a connect timer of connectionTimeoutMillis destroys the socket, 'Connection terminated due to connection timeout', and the pool does not try again`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:127-170 _pulseQueue: the first waiter gets the last idle client (pop), with no test, :335-366 verify runs only on a new client`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:384-429 _release: an error, a client that is not queryable or ends, maxUses or an expired lifetime removes the client, else the idle timer arms above min`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:311-332 maxLifetimeSeconds: its timer marks the client expired, and an idle client goes at once`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:51-64 and :172-188 an idle client that emits error leaves the pool, and the pool emits error with it, :340-344 a checkout removes that listener`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:431-486 pool.query: an error of the checkout, of the client or of the query fails pool.query with no second try, and a release with that error ends the client`, rung: \"implemented\" },\n { ref: `${POOL}/README.md:224-240 the pool emits error for an idle client, and the application must listen for it`, rung: \"documented\" },\n { ref: \"systems.machine.linux-tcp: a reset of an established socket is ECONNRESET, and a give-up of the kernel is ETIMEDOUT. pg gives the error of the socket to the application as it is (connection.js:54-61)\", rung: \"derived\" },\n { ref: \"node v24.21.0 lib/net.js:846-888 (setKeepAlive truncates the delay to whole seconds), src/tcp_wrap.cc:204-221 (interval 1 s and count 10 when none is given), deps/uv/src/unix/tcp.c:468-480 (SO_KEEPALIVE first, then EINVAL and no other option for an idle time below 1 s)\", rung: \"implemented\" },\n { ref: \"node v24.21.0 lib/net.js:589 (a socket has no timeout until setTimeout), :828-843 and :1987-1989 (a setNoDelay before the connect applies at the connect)\", rung: \"implemented\" },\n { ref: \"node v24.21.0 lib/net.js:600-604, lib/internal/streams/readable.js:1752-1790 and lib/internal/streams/writable.js:951-973: a socket allows no half-open connection, thus a FIN from the peer ends it and it closes\", rung: \"implemented\" },\n { ref: \"node v24.21.0 lib/events.js:489-506 an error event with no listener throws\", rung: \"implemented\" },\n { ref: \"node v24.21.0 lib/internal/timers.js:426-446 the timers of one duration go in one list, in the order that they start\", rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"Before the pool makes the client, or before a checkout gets one\" },\n waiting: {\n note: \"A checkout of the application waits in the queue of the pool, because the pool is full or has an idle client (pg-pool index.js:200-232)\",\n },\n connecting: { note: \"The TCP connect of a new client, with TCP_NODELAY and no keepalive at the defaults (connection.js:40-52)\" },\n startup: { note: \"The startup message and the authentication, until the first ReadyForQuery (client.js:185-199, :373-387)\" },\n held: {\n note: \"A client that the application holds after a checkout, with no query in flight. The pool does not listen to its errors (pg-pool index.js:344)\",\n },\n querying: { note: \"A query in flight: the client waits for its ReadyForQuery, and sends no other query (client.js:616-641)\" },\n orphaned: {\n note: \"The query failed to the application on its timer, but it stays the active query of the client. The client sends no cancel, and waits for the ReadyForQuery of that query (client.js:702-737)\",\n },\n pooled: { note: \"An idle client in the pool, with the idle timer of the pool (pg-pool index.js:407-427)\" },\n ended: {\n final: true,\n note: \"The socket closes, the pool removes the client, or a checkout fails. The client does not connect again, and a query on it fails at once (client.js:158-164, :765-777)\",\n },\n },\n events: {\n \"app.checkout\": { kind: \"app\", note: \"The application calls pool.connect, or pool.query before its query\" },\n \"app.query\": { kind: \"app\", note: \"The application calls client.query, or pool.query sends its query\" },\n \"app.release\": { kind: \"app\", note: \"The application calls client.release() with no error, or pool.query releases the client after a reply\" },\n \"app.release-error\": { kind: \"app\", note: \"The application calls client.release(err), or pool.query releases the client after an error of the query or of the client\" },\n \"local.handout\": { kind: \"local\", note: \"The pool gives an idle client to the first waiter of its queue (pg-pool index.js:156-165)\" },\n \"local.slot\": { kind: \"local\", note: \"A removal frees a place in a full pool, and the first waiter gets a new client (pg-pool index.js:166-168)\" },\n \"socket.connect\": { kind: \"local\" },\n \"local.connected\": { kind: \"local\", note: \"The first ReadyForQuery of the server: the end of the connect, and the connect callback of the client\" },\n \"rx.ready-for-query\": { kind: \"rx\", note: \"The ReadyForQuery that ends a query\" },\n \"rx.error-response\": { kind: \"rx\", note: \"An ErrorResponse of the server: a DatabaseError, with the severity and the code of the server\" },\n \"peer.fin\": { kind: \"peer\", note: \"The server or a middlebox closes the connection. Node ends the socket, and its close is the end of the connection\" },\n \"peer.rst\": { kind: \"peer\", note: \"A reset of the connection: the socket fails with ECONNRESET\" },\n \"socket.error\": { kind: \"local\", note: \"The socket fails with its own error: a reset, or a give-up of the kernel (ETIMEDOUT)\" },\n \"tx.terminate\": { kind: \"tx\", note: \"The Terminate message, then the end of the socket of the client (connection.js:217-227)\" },\n \"timer.connect-timeout\": { kind: \"timer\", note: \"The pool destroys the socket: 'Connection terminated due to connection timeout'\" },\n \"timer.checkout-timeout\": { kind: \"timer\", note: \"The checkout fails: 'timeout exceeded when trying to connect'\" },\n \"timer.idle\": { kind: \"timer\", note: \"The pool removes the idle client\" },\n \"timer.query-timeout\": { kind: \"timer\", note: \"The query fails to the application: 'Query read timeout'\" },\n \"timer.max-lifetime\": { kind: \"timer\", note: \"The pool marks the client expired\" },\n },\n knobs: {\n connectionTimeoutMillis: {\n key: \"pg-pool connectionTimeoutMillis\",\n scope: \"client\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"client.js:116 and pg-pool index.js:206, :250. 0 is no timeout, for the connect and for a checkout\",\n },\n idleTimeoutMillis: {\n key: \"pg-pool idleTimeoutMillis\",\n scope: \"client\",\n unit: \"ms\",\n default: 10000,\n off: 0,\n note: \"pg-pool index.js:98-100: 10000 when it is undefined, not the 30000 of pg.defaults. 0 is no idle timer (index.js:409)\",\n },\n query_timeout: {\n key: \"pg query_timeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"defaults.js:76 and client.js:702-703: false at the defaults, thus no timer\",\n },\n maxLifetimeSeconds: {\n key: \"pg-pool maxLifetimeSeconds\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"pg-pool index.js:93 and :312. 0 is no limit\",\n },\n max: { key: \"pg-pool max\", scope: \"client\", unit: \"count\", default: 10, note: \"pg-pool index.js:89\" },\n min: {\n key: \"pg-pool min\",\n scope: \"client\",\n unit: \"count\",\n default: 0,\n note: \"pg-pool index.js:90: the idle timer arms only when the pool has more clients than min (index.js:409-415)\",\n },\n maxUses: { key: \"pg-pool maxUses\", scope: \"client\", unit: \"count\", default: null, note: \"pg-pool index.js:91: Infinity at the defaults, thus no limit\" },\n allowExitOnIdle: {\n key: \"pg-pool allowExitOnIdle\",\n scope: \"client\",\n unit: null,\n default: 0,\n note: \"pg-pool index.js:92: off. When it is on, the idle timer and the idle socket do not hold the event loop (index.js:417-425)\",\n },\n keepAlive: {\n key: \"pg keepAlive\",\n scope: \"client\",\n unit: null,\n default: 0,\n note: \"client.js:95: off. Then the client calls no setKeepAlive, and the socket has no keepalive (connection.js:48-50)\",\n },\n keepAliveInitialDelayMillis: {\n key: \"pg keepAliveInitialDelayMillis\",\n scope: \"client\",\n unit: \"ms\",\n default: 0,\n note: \"client.js:96. The client gives it to setKeepAlive only when keepAlive is on (connection.js:48-50)\",\n },\n keepalive_idle: {\n key: \"the keepalive idle time of the socket of pg\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"A value of this document, from keepAlive and keepAliveInitialDelayMillis. 0 is no keepalive, as at the defaults. With keepAlive on and a delay of 1000 ms or more, give floor(keepAliveInitialDelayMillis / 1000). Below 1000 ms, libuv sets no idle time: give tcp_keepalive_time, and the interval and count of the namespace to the two knobs below\",\n },\n node_keepalive_interval: {\n key: \"node net.Socket setKeepAlive interval\",\n scope: \"client\",\n unit: \"s\",\n default: 1,\n note: \"Node passes 1 s to libuv when setKeepAlive gets no interval, as pg gives none\",\n },\n node_keepalive_count: {\n key: \"node net.Socket setKeepAlive count\",\n scope: \"client\",\n unit: \"count\",\n default: 10,\n note: \"Node passes 10 to libuv when setKeepAlive gets no count, as pg gives none\",\n },\n statement_timeout: {\n key: \"pg statement_timeout\",\n scope: \"session\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"defaults.js:63-65 and client.js:558-560: false at the defaults. When it is set, the client sends it to the server in the startup message. The client has no timer for it\",\n },\n lock_timeout: {\n key: \"pg lock_timeout\",\n scope: \"session\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"defaults.js:67-69 and client.js:561-563: false at the defaults. When it is set, the client sends it to the server in the startup message. The client has no timer for it\",\n },\n idle_in_transaction_session_timeout: {\n key: \"pg idle_in_transaction_session_timeout\",\n scope: \"session\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"defaults.js:71-73 and client.js:564-566: false at the defaults. When it is set, the client sends it to the server in the startup message. The client has no timer for it\",\n },\n slack: {\n key: \"the lateness of the event loop of Node for one step\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of pg: a timer or a callback of Node that comes late\",\n },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"The build option of the kernel: the keepalive of pg is the kernel's, thus the timer wheel rounds its firings\",\n },\n },\n timers: {\n connect_timeout: {\n duration: { knob: \"connectionTimeoutMillis\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n // The timer starts one time, at the connect, and runs through the startup. The arm at the entry to startup\n // lets a reader of one state find it: there, the time that remains is less by the time of the TCP connect.\n arms: [\"enter:connecting\", \"enter:startup\"],\n cancels: [\"local.connected\", \"socket.error\", \"peer.rst\", \"peer.fin\", \"rx.error-response\"],\n fires: \"timer.connect-timeout\",\n // The pool arms its timer (pg-pool index.js:250-263), and then the client arms its own (client.js:167-176).\n // The two have the same duration, thus the timer of the pool fires first (lib/internal/timers.js:426-446).\n note: \"One timer for the TCP connect, the startup and the authentication, until the first ReadyForQuery. No bound at the defaults: the TCP connect waits for the kernel, and the startup waits with no bound\",\n },\n checkout_timeout: {\n duration: { knob: \"connectionTimeoutMillis\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:waiting\"],\n cancels: [\"local.handout\", \"local.connected\"],\n fires: \"timer.checkout-timeout\",\n note: \"pg-pool index.js:206-232: no bound at the defaults. A waiter that gets a new client keeps this timer through the connect of that client. When it fires then, the new client goes to the pool after its connect (index.js:359-364)\",\n },\n idle_timeout: {\n duration: { knob: \"idleTimeoutMillis\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:pooled\"],\n cancels: [\"app.checkout\", \"socket.error\", \"peer.rst\", \"peer.fin\", \"rx.error-response\", \"timer.max-lifetime\"],\n fires: \"timer.idle\",\n note: \"pg-pool index.js:407-421: each release arms it when the pool has more clients than min. A checkout or a removal clears it (index.js:159, :176)\",\n },\n query_timeout: {\n duration: { knob: \"query_timeout\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"app.query\", \"enter:querying\"],\n cancels: [\"rx.ready-for-query\", \"rx.error-response\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.query-timeout\",\n note: \"client.js:702-737: one timer for each query, from client.query, thus the wait in the queue of the client counts too. No bound at the defaults\",\n },\n max_lifetime: {\n duration: { knob: \"maxLifetimeSeconds\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"local.connected\"],\n cancels: [\"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.max-lifetime\",\n note: \"pg-pool index.js:311-332: one timer for the life of the client, from its connect. No limit at the defaults. A held client goes at its next release (index.js:400-405)\",\n },\n },\n realizes: {\n \"systems.mechanism.connect-bound\": { timer: \"connect_timeout\" },\n \"systems.mechanism.pool-idle-expiry\": { timer: \"idle_timeout\" },\n \"systems.mechanism.request-timeout\": { timer: \"query_timeout\" },\n \"systems.mechanism.idle-refresh-interval\": {\n duration: { knob: \"keepalive_idle\", unit: \"s\" },\n lateness: { model: \"linux.wheel\", knobs: [\"keepalive_idle\", \"hz\"], unit: \"s\" },\n early: { model: \"linux.jiffy\", knobs: [\"hz\"], unit: \"s\" },\n note: \"The first keepalive probe of an idle client. Keepalive is off at the defaults, thus no bound: the client sends nothing on an idle connection\",\n },\n },\n transitions: [\n {\n id: \"pg.open\",\n from: \"[none]\",\n to: \"connecting\",\n on: \"app.checkout\",\n guard: \"the pool is not full and has no idle client\",\n timer: \"connect_timeout\",\n source: \"pg-pool index.js:200, :235, :240-266\",\n },\n {\n id: \"pg.wait\",\n from: \"[none]\",\n to: \"waiting\",\n on: \"app.checkout\",\n guard: \"the pool is full, or it has an idle client\",\n timer: \"checkout_timeout\",\n note: \"With an idle client, the pool gives it on the next tick (index.js:202-204)\",\n source: \"pg-pool index.js:200-232\",\n },\n { id: \"pg.handout\", from: \"waiting\", to: \"held\", on: \"local.handout\", source: \"pg-pool index.js:156-165, :335-366\" },\n {\n id: \"pg.slot\",\n from: \"waiting\",\n to: \"connecting\",\n on: \"local.slot\",\n timer: \"connect_timeout\",\n note: \"The waiter keeps its checkout timer, and the new client has its own connect timer\",\n source: \"pg-pool index.js:166-168, :240-266\",\n },\n {\n id: \"pg.checkout-timed-out\",\n from: \"waiting\",\n to: \"ended\",\n on: \"timer.checkout-timeout\",\n timer: \"checkout_timeout\",\n errno: \"timeout exceeded when trying to connect\",\n source: \"pg-pool index.js:219-225\",\n },\n {\n id: \"pg.connected\",\n from: \"connecting\",\n to: \"startup\",\n on: \"socket.connect\",\n note: \"The client sends the startup message at once\",\n source: \"connection.js:47-52, client.js:185-195\",\n },\n {\n id: \"pg.ready\",\n from: \"startup\",\n to: \"held\",\n on: \"local.connected\",\n note: \"The first ReadyForQuery clears the connect timers, and the pool gives the client to the checkout\",\n source: \"client.js:373-387, pg-pool index.js:266-309, :335-366\",\n },\n {\n id: \"pg.connect-timed-out\",\n from: [\"connecting\", \"startup\"],\n to: \"ended\",\n on: \"timer.connect-timeout\",\n timer: \"connect_timeout\",\n errno: \"Connection terminated due to connection timeout\",\n note: \"The cause of the error is the error of the client. The checkout fails, and the pool does not try again\",\n source: \"pg-pool index.js:250-284\",\n },\n {\n id: \"pg.connect-failed\",\n from: [\"connecting\", \"startup\"],\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\", \"rx.error-response\"],\n note: \"The checkout fails with the error: the error of the socket, 'Connection terminated unexpectedly' for a close, or the DatabaseError of the server. The pool does not try again\",\n source: \"client.js:203-230, :398-411, pg-pool index.js:266-284\",\n },\n {\n id: \"pg.query\",\n from: \"held\",\n to: \"querying\",\n on: \"app.query\",\n timer: \"query_timeout\",\n source: \"client.js:668-785, :616-641\",\n },\n {\n id: \"pg.replied\",\n from: \"querying\",\n to: \"held\",\n on: \"rx.ready-for-query\",\n note: \"Then pool.query releases the client\",\n source: \"client.js:373-396, query.js:136-150, pg-pool index.js:467-478\",\n },\n {\n id: \"pg.statement-failed\",\n from: \"querying\",\n to: \"held\",\n on: \"rx.error-response\",\n errno: \"DatabaseError\",\n note: \"The query fails, and the client stays queryable. Then pool.query releases the client with the error, thus the pool ends it\",\n source: \"client.js:426-442, query.js:122-134, pg-pool index.js:467-477\",\n },\n {\n id: \"pg.query-timed-out\",\n from: \"querying\",\n to: \"orphaned\",\n on: \"timer.query-timeout\",\n timer: \"query_timeout\",\n errno: \"Query read timeout\",\n note: \"The query fails to the application. The client sends no cancel and stays queryable. Then pool.query releases the client with the error\",\n source: \"client.js:702-737, pg-pool index.js:467-477\",\n },\n {\n id: \"pg.orphan-ended\",\n from: \"orphaned\",\n to: \"held\",\n on: [\"rx.ready-for-query\", \"rx.error-response\"],\n note: \"The old query ends, and its result goes to no one. Then the client sends the next query of its queue\",\n source: \"client.js:373-396, :426-442, :717\",\n },\n {\n id: \"pg.query-abandoned\",\n from: \"orphaned\",\n to: \"ended\",\n on: \"app.release-error\",\n note: \"The pool ends the client, and the active query makes end destroy the socket. The server gets no cancel\",\n source: \"pg-pool index.js:392-398, :172-188, client.js:822-824\",\n },\n {\n id: \"pg.release-busy\",\n from: \"orphaned\",\n to: \"pooled\",\n on: \"app.release\",\n guard: \"the application releases the client with no error\",\n note: \"The pool keeps the client. The next query on it waits for the ReadyForQuery of the old query\",\n source: \"pg-pool index.js:392-429, client.js:616-641\",\n },\n {\n id: \"pg.orphan-failed\",\n from: \"orphaned\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\"],\n note: \"The old query has no callback left, thus only the error event of the client tells of the failure\",\n source: \"client.js:717, :133-151, :203-230, :416-423\",\n },\n {\n id: \"pg.query-reset\",\n from: \"querying\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\"],\n errno: \"ECONNRESET\",\n note: \"The error of the socket, with its own code: ECONNRESET for a reset, ETIMEDOUT for a give-up of the kernel. Each query of the client fails with it, and the client emits it\",\n source: \"connection.js:54-61, client.js:133-151, :416-423\",\n },\n {\n id: \"pg.query-closed\",\n from: \"querying\",\n to: \"ended\",\n on: \"peer.fin\",\n errno: \"Connection terminated unexpectedly\",\n note: \"Each query of the client fails with this error, and the client emits it\",\n source: \"connection.js:63-65, client.js:203-230\",\n },\n {\n id: \"pg.release\",\n from: \"held\",\n to: \"pooled\",\n on: \"app.release\",\n guard: \"the client is queryable and its end did not start, it has fewer uses than maxUses, and the pool did not mark it expired\",\n timer: \"idle_timeout\",\n source: \"pg-pool index.js:384-429\",\n },\n {\n id: \"pg.release-removed\",\n from: \"held\",\n to: \"ended\",\n on: \"app.release\",\n guard: \"the client is not queryable or its end started, it reached maxUses, or the pool marked it expired\",\n note: \"The pool removes the client. Its end sends Terminate, or destroys a dead socket\",\n source: \"pg-pool index.js:392-405, :172-188, client.js:799-836\",\n },\n {\n id: \"pg.release-error\",\n from: \"held\",\n to: \"ended\",\n on: \"app.release-error\",\n note: \"The pool removes the client. Its end sends Terminate, or destroys a dead socket\",\n source: \"pg-pool index.js:392-398, :172-188, client.js:799-836\",\n },\n {\n id: \"pg.held-failed\",\n from: \"held\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\", \"rx.error-response\"],\n note: \"The client emits error, and the pool does not listen. With no listener of the application, the error throws. After a socket error, the close of the socket emits a second error: 'Connection terminated unexpectedly'\",\n source: \"pg-pool index.js:340-344, client.js:203-230, :398-435, node lib/events.js:489-506\",\n },\n {\n id: \"pg.checkout\",\n from: \"pooled\",\n to: \"held\",\n on: \"app.checkout\",\n note: \"The last client that went back to the pool goes out first. The pool sends no test query, thus a dead connection goes out too\",\n source: \"pg-pool index.js:156-165, :335-366\",\n },\n {\n id: \"pg.idle-expired\",\n from: \"pooled\",\n to: \"ended\",\n on: \"timer.idle\",\n timer: \"idle_timeout\",\n guard: \"the pool has more clients than min\",\n emits: [\"tx.terminate\"],\n note: \"The pool emits remove only in the callback of the end of the client, when the socket closes (pg-pool index.js:181-187). Behind a black hole the FIN gets no answer, thus the socket stays open and remove does not come\",\n source: \"pg-pool index.js:409-416, :172-188, client.js:825-827, connection.js:217-227\",\n },\n {\n id: \"pg.lifetime-expired\",\n from: \"pooled\",\n to: \"ended\",\n on: \"timer.max-lifetime\",\n timer: \"max_lifetime\",\n emits: [\"tx.terminate\"],\n note: \"The pool checks out the idle client and releases it at once, thus it removes it\",\n source: \"pg-pool index.js:313-326, :400-405\",\n },\n {\n id: \"pg.idle-reset\",\n from: \"pooled\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\"],\n errno: \"ECONNRESET\",\n note: \"The pool removes the client, and emits error with the error of the socket and the client. With no listener of the pool, the error throws\",\n source: \"connection.js:54-61, client.js:416-423, pg-pool index.js:51-64, node lib/events.js:489-506\",\n },\n {\n id: \"pg.idle-closed\",\n from: \"pooled\",\n to: \"ended\",\n on: \"peer.fin\",\n errno: \"Connection terminated unexpectedly\",\n note: \"The pool removes the client and emits error with this error\",\n source: \"connection.js:63-65, client.js:203-230, pg-pool index.js:51-64\",\n },\n {\n id: \"pg.idle-fatal\",\n from: \"pooled\",\n to: \"ended\",\n on: \"rx.error-response\",\n errno: \"DatabaseError\",\n note: \"An ErrorResponse with no active query is an error of the client: the pool removes the client and emits error with the DatabaseError\",\n source: \"client.js:426-435, :416-423, pg-pool index.js:51-64\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: {\n connecting: \"SYN_SENT\",\n startup: \"ESTABLISHED\",\n held: \"ESTABLISHED\",\n querying: \"ESTABLISHED\",\n orphaned: \"ESTABLISHED\",\n pooled: \"ESTABLISHED\",\n },\n sets: {\n keepidle: { knob: \"keepalive_idle\", unit: \"s\" },\n keepintvl: { knob: \"node_keepalive_interval\", unit: \"s\" },\n keepcnt: { knob: \"node_keepalive_count\", unit: \"count\" },\n },\n ends: \"socket.error\",\n note: \"Each socket of pg is a Linux TCP socket with TCP_NODELAY. At the defaults pg turns keepalive on for no socket, thus keepidle has no bound. With keepAlive on and a delay of 1 s or more, Node gives libuv the delay in whole seconds, with 1 s and 10 probes. With a delay below 1 s, libuv sets SO_KEEPALIVE and no other option, thus the three keepalive sysctls of the namespace apply\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the C source of PgBouncer at the tag pgbouncer_1_26_1 (commit\n// f03e9bf263d7, the tarball of GitHub with SHA-256 2e659b12...a64ea6bc38). Each line number is a\n// line of that file at the tag. The tag holds libusual in lib/. A fact of libevent or of the kernel\n// is an assumption of this document, and its note says so.\nexport const PB = \"pgbouncer_1_26_1\";\n\n/** These are the sources of both documents: the defaults, the janitor and its clock. */\nexport const PB_COMMON: Machine[\"sources\"] = [\n { ref: `${PB} src/main.c:260-365 the defaults of the configuration: client_login_timeout 60 s, query_wait_timeout 120 s, client_idle_timeout 0, query_timeout 0, idle_transaction_timeout 0, transaction_timeout 0, server_connect_timeout 15 s, server_login_retry 15 s, server_idle_timeout 600 s, server_lifetime 3600 s, server_check_delay 30 s, server_check_query <empty>, pool_mode session, tcp_keepalive 1`, rung: \"implemented\" },\n { ref: `${PB} lib/usual/cfparser.c:530-556 a time of the configuration is seconds as a double, kept in microseconds. src/loader.c:349-358, :558-573 a setting of a database or a user takes whole seconds`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:27-28, :780-786 and src/main.c:1088 the janitor: a persistent libevent timer of USEC / 3, thus each 333.3 ms`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:694-777 each pass of the janitor: the maintenance of the servers and then of the clients of each pool, then the logins of the clients`, rung: \"implemented\" },\n { ref: `${PB} lib/usual/time.c:67-89 and src/main.c:868-889 the time of a pass is gettimeofday, cached for each loop of the events`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:307, :341, :343, :368, :416, :549, :552, :567, :619 each timer compares its age with > its limit: a timer fires at the first pass of the janitor after its limit`, rung: \"implemented\" },\n { ref: `${PB} src/util.c:162-236 and lib/usual/socket.c:78-147 each TCP socket gets SO_KEEPALIVE and TCP_NODELAY. TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT only when they are not 0, thus the values of the namespace apply at the defaults`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:267-292 the effective pool mode: of the user, then of the database, then the global one`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1451-1465, :1593-1600 and src/proto.c:260-275 a close of a client with a reason sends an ErrorResponse: severity FATAL, SQLSTATE 08P01, the reason as its message, and no ReadyForQuery`, rung: \"implemented\" },\n];\n\n/**\n * This document is PgBouncer 1.26.1 in transaction pooling, for one client connection. It gives the\n * states of the client, from its accept to its close, and the timers that act on it.\n *\n * In transaction pooling, a client holds a server connection only for a transaction. Between two\n * transactions the client is idle, and PgBouncer reads its socket: the end of the stream or a reset\n * closes it at once. A query that finds no idle server waits in a queue, and PgBouncer does not read\n * the socket of a waiting client. It finds a client that left the queue only when it serves it.\n *\n * Each timer of a client is a check of the janitor, which runs each 333.3 ms. A timer thus fires up\n * to one period after its limit, and a busy loop of events delays it more. At the defaults only two\n * timers act on a client: client_login_timeout (60 s) and query_wait_timeout (120 s). A timer that\n * fires, and the failure of the linked server, close the client with a FATAL error of SQLSTATE 08P01.\n */\nexport const PGBOUNCER_CLIENT: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"pgbouncer-client\",\n title: \"PgBouncer 1.26.1 in transaction pooling: one client connection, its login, its queue and its transactions\",\n layer: \"proxy\",\n version: \"1.26.1\",\n conditions: {\n pgbouncer: \"1.26.1\",\n pool_mode: \"transaction, set for the database or the user, or globally\",\n client: \"a PostgreSQL client over TCP, with no TLS\",\n server: \"one PostgreSQL server for the database of the client\",\n },\n sources: [\n ...PB_COMMON,\n { ref: `${PB} include/bouncer.h:69-89 and src/objects.c:222-289 the states of a client, each a list: CL_LOGIN, CL_WAITING, CL_WAITING_LOGIN, CL_ACTIVE`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:272-275 a client that waits goes to the end of the queue, and it gets the time of its wait`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:606-622 client_login_timeout: a client in CL_LOGIN for longer than it, from its accept, is closed: 'client_login_timeout'`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:2077-2085 and src/janitor.c:361-371 a client that logs in before the pool has a welcome message waits for it. client_login_timeout from its accept closes it: 'client_login_timeout (server down)'`, rung: \"implemented\" },\n { ref: `${PB} src/client.c:1639-1662 each packet of the client: the start of the query and of the transaction, then find_server. The server is no longer ready`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:915-988 find_server: the first idle server, else check_fast_fail and a wait in the queue`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:805-817 and src/sbuf.c:218-229 a client that waits is paused: its socket is not read`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:838-850 and src/sbuf.c:232-257, :494-506 an active client keeps the read of its socket`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:116-170 and src/objects.c:994-1014 the first waiting client gets the next idle server: first in, first out`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:313-347 query_wait_timeout: a waiting client for longer than it, from the start of its query, is closed: 'query_wait_timeout'. query_timeout acts there first: 'query_timeout'`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:293-310 client_idle_timeout acts only on an active client with no server: 'client_idle_timeout'`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:500-556 on each active server: query_timeout from the start of the query, the queue included, then idle_transaction_timeout, then transaction_timeout. Each closes the server and the client`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:433-455, :642-668 ReadyForQuery I makes the server ready and ends the query and the transaction. T or E keeps the server linked, idle in a transaction`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:861-921 and src/objects.c:1213-1322 the release: a ready server whose data the client got goes back to the pool`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:869-900 check_fast_fail: when the last login of the pool failed and it has no server outside a login, a client that needs one is closed at once: 'server login has been failing, cached error: ... (server_login_retry)'`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:808-813 and src/objects.c:1324-1344, :1375-1379 a linked server whose socket fails: the client gets 'server conn crashed?' and is closed`, rung: \"implemented\" },\n { ref: `${PB} src/client.c:1789-1800 the end of the stream or an error of the socket of a client closes it: 'client unexpected eof'. A send to its server that fails: 'server connection closed'`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1493-1534 a client that goes while linked: its server is closed when it was not ready, else it goes back to the pool`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:788-813 and src/admin.c:1202-1244 KILL closes each client of the database: 'database removed'`, rung: \"implemented\" },\n { ref: `${PB} src/admin.c:1017-1045 and src/objects.c:920-921 during PAUSE a new query gets no server, thus it waits. The janitor still runs query_wait_timeout (src/janitor.c:722-728)`, rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"Before PgBouncer accepts the connection\" },\n login: { note: \"CL_LOGIN: the startup packet and the authentication. PgBouncer reads the socket\" },\n welcome: {\n note: \"CL_WAITING_LOGIN: the client logged in before any server of the pool logged in, and it waits for the parameters of the server. Its socket is not read (src/objects.c:2077-2085)\",\n },\n idle: { note: \"CL_ACTIVE with no server: between two transactions. PgBouncer reads the socket, thus it notices a close at once\" },\n waiting: { note: \"CL_WAITING: a query found no idle server, and the client waits in the queue. PgBouncer does not read its socket\" },\n linked: { note: \"CL_ACTIVE with a server: a query or a transaction in flight. PgBouncer forwards each packet both ways\" },\n ended: { final: true, note: \"PgBouncer closed the client, with a FATAL ErrorResponse for a reason, or the client went\" },\n },\n events: {\n \"local.accept\": { kind: \"local\", note: \"PgBouncer accepts the TCP connection\" },\n \"local.logged-in\": { kind: \"local\", note: \"The authentication of the client ends\" },\n \"local.welcome\": { kind: \"local\", note: \"The first server of the pool logs in: the pool has its welcome message\" },\n \"rx.query\": { kind: \"rx\", note: \"The first packet of a query of the client\" },\n \"local.attached\": { kind: \"local\", note: \"The client gets an idle server of the pool\" },\n \"rx.ready-in-transaction\": { kind: \"rx\", note: \"The server sends ReadyForQuery with the status T or E: the client keeps the server\" },\n \"local.released\": { kind: \"local\", note: \"The server sends ReadyForQuery with the status I, and the client got all of its data: the server goes back to the pool\" },\n \"server.crashed\": { kind: \"peer\", note: \"The socket of the linked server fails: the end of the stream, a reset, or an error\" },\n \"server.send-failed\": { kind: \"peer\", note: \"A send of a packet of the client to its server fails\" },\n \"peer.fin\": { kind: \"peer\", note: \"The client closes its connection: a read gets the end of the stream\" },\n \"peer.rst\": { kind: \"peer\", note: \"A reset of the connection of the client\" },\n \"socket.error\": { kind: \"local\", note: \"The socket of the client fails with its own error\" },\n \"rx.terminate\": { kind: \"rx\", note: \"The Terminate message of the client\" },\n \"admin.kill\": { kind: \"app\", note: \"The KILL command of the console, for the database of the client\" },\n \"tx.fatal\": { kind: \"tx\", note: \"An ErrorResponse with severity FATAL and SQLSTATE 08P01, then the close of the socket\" },\n \"timer.login\": { kind: \"timer\", note: \"A pass of the janitor finds the login older than client_login_timeout\" },\n \"timer.query-wait\": { kind: \"timer\", note: \"A pass of the janitor finds the wait older than query_wait_timeout\" },\n \"timer.idle\": { kind: \"timer\", note: \"A pass of the janitor finds the idle client older than client_idle_timeout\" },\n \"timer.query\": { kind: \"timer\", note: \"A pass of the janitor finds the query older than query_timeout\" },\n \"timer.idle-transaction\": { kind: \"timer\", note: \"A pass of the janitor finds the server idle in the transaction for longer than idle_transaction_timeout\" },\n \"timer.transaction\": { kind: \"timer\", note: \"A pass of the janitor finds the transaction older than transaction_timeout\" },\n },\n knobs: {\n client_login_timeout: { key: \"pgbouncer client_login_timeout\", scope: \"proxy\", unit: \"s\", default: 60, off: 0, note: \"src/main.c:273\" },\n query_wait_timeout: {\n key: \"pgbouncer query_wait_timeout\",\n scope: \"proxy\",\n unit: \"s\",\n default: 120,\n off: 0,\n note: \"src/main.c:316. A setting of the database, then of the user, replaces it (src/janitor.c:328-337)\",\n },\n client_idle_timeout: { key: \"pgbouncer client_idle_timeout\", scope: \"proxy\", unit: \"s\", default: 0, off: 0, note: \"src/main.c:272\" },\n query_timeout: { key: \"pgbouncer query_timeout\", scope: \"proxy\", unit: \"s\", default: 0, off: 0, note: \"src/main.c:314\" },\n idle_transaction_timeout: { key: \"pgbouncer idle_transaction_timeout\", scope: \"proxy\", unit: \"s\", default: 0, off: 0, note: \"src/main.c:289\" },\n transaction_timeout: { key: \"pgbouncer transaction_timeout\", scope: \"proxy\", unit: \"s\", default: 0, off: 0, note: \"src/main.c:356\" },\n janitor: {\n key: \"the period of the janitor of PgBouncer\",\n scope: \"process\",\n unit: \"ms\",\n default: 333.333,\n note: \"src/janitor.c:27-28: USEC / 3 in whole microseconds, 333333 µs. Each timer of a client is a check of a pass, thus it is up to one period late\",\n },\n slack: {\n key: \"the lateness of the loop of events of PgBouncer for one pass\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of PgBouncer: libevent runs the janitor in the one thread of the loop, thus a busy loop delays it\",\n },\n },\n timers: {\n client_login_timeout: {\n duration: { knob: \"client_login_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:login\", \"enter:welcome\"],\n cancels: [\"local.logged-in\", \"local.welcome\"],\n fires: \"timer.login\",\n note: \"src/janitor.c:361-371, :606-622: it counts from the accept of the client in both states, thus the time of the login comes before the wait for the welcome message\",\n },\n query_wait_timeout: {\n duration: { knob: \"query_wait_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:waiting\"],\n cancels: [\"local.attached\"],\n fires: \"timer.query-wait\",\n note: \"src/janitor.c:316-347: from the start of the query, which is the entry to the queue. PAUSE does not stop it\",\n },\n client_idle_timeout: {\n duration: { knob: \"client_idle_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:idle\"],\n cancels: [\"rx.query\"],\n fires: \"timer.idle\",\n note: \"src/janitor.c:293-310: from the last packet of the client. No bound at the defaults\",\n },\n query_timeout: {\n duration: { knob: \"query_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:waiting\", \"enter:linked\"],\n cancels: [\"local.released\", \"rx.ready-in-transaction\"],\n fires: \"timer.query\",\n note: \"src/client.c:1640-1656, src/janitor.c:341-342, :545-546: from the arrival of the query, thus its time in the queue counts. PgBouncer sends no CancelRequest: it closes the server and the client. No bound at the defaults\",\n },\n idle_transaction_timeout: {\n duration: { knob: \"idle_transaction_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"rx.ready-in-transaction\"],\n cancels: [\"rx.query\", \"local.released\"],\n fires: \"timer.idle-transaction\",\n note: \"src/janitor.c:547-550, src/server.c:452-454: from the last packet of the server, while the client sends nothing in its transaction. No bound at the defaults\",\n },\n transaction_timeout: {\n duration: { knob: \"transaction_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:linked\"],\n cancels: [\"local.released\"],\n fires: \"timer.transaction\",\n note: \"src/janitor.c:526, :551-553, src/client.c:1646-1649: from the first query of the transaction. No bound at the defaults\",\n },\n },\n realizes: {\n \"systems.mechanism.server-idle-close\": { timer: \"client_idle_timeout\" },\n \"systems.mechanism.request-timeout\": { timer: \"query_timeout\" },\n },\n transitions: [\n { id: \"pbc.accept\", from: \"[none]\", to: \"login\", on: \"local.accept\", timer: \"client_login_timeout\", source: \"src/objects.c:2025\" },\n { id: \"pbc.logged-in\", from: \"login\", to: \"idle\", on: \"local.logged-in\", guard: \"the pool has its welcome message: a server of the pool logged in before\", source: \"src/objects.c:2077-2085\" },\n {\n id: \"pbc.wait-welcome\",\n from: \"login\",\n to: \"welcome\",\n on: \"local.logged-in\",\n guard: \"no server of the pool logged in yet\",\n note: \"The client is paused, and the pool starts a connection to the server\",\n source: \"src/objects.c:2077-2085\",\n },\n { id: \"pbc.welcome\", from: \"welcome\", to: \"idle\", on: \"local.welcome\", source: \"src/objects.c:1246-1248\" },\n {\n id: \"pbc.login-timed-out\",\n from: \"login\",\n to: \"ended\",\n on: \"timer.login\",\n timer: \"client_login_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'client_login_timeout'\",\n source: \"src/janitor.c:606-622\",\n },\n {\n id: \"pbc.welcome-timed-out\",\n from: \"welcome\",\n to: \"ended\",\n on: \"timer.login\",\n timer: \"client_login_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'client_login_timeout (server down)': no server of the pool logged in\",\n source: \"src/janitor.c:361-371\",\n },\n {\n id: \"pbc.attach\",\n from: \"idle\",\n to: \"linked\",\n on: \"rx.query\",\n guard: \"an idle server is in the pool, and the pool is not paused\",\n timer: \"query_timeout\",\n source: \"src/objects.c:915-975\",\n },\n {\n id: \"pbc.queue\",\n from: \"idle\",\n to: \"waiting\",\n on: \"rx.query\",\n guard: \"no idle server, and no failed login of the pool, or the pool is paused\",\n timer: \"query_wait_timeout\",\n note: \"The client goes to the end of the queue, and its socket is no longer read. The pool starts a connection when it can\",\n source: \"src/objects.c:805-817, :947-988\",\n },\n {\n id: \"pbc.fast-fail\",\n from: \"idle\",\n to: \"ended\",\n on: \"rx.query\",\n guard: \"the last login of the pool failed, and the pool has no server outside a login\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'server login has been failing, cached error: <reason> (server_login_retry)', at once\",\n source: \"src/objects.c:869-900\",\n },\n {\n id: \"pbc.attached\",\n from: \"waiting\",\n to: \"linked\",\n on: \"local.attached\",\n note: \"A server becomes idle or logs in, and the first waiting client gets it. The client then reads its socket again\",\n source: \"src/janitor.c:116-170, src/objects.c:994-1014\",\n },\n {\n id: \"pbc.wait-timed-out\",\n from: \"waiting\",\n to: \"ended\",\n on: \"timer.query-wait\",\n timer: \"query_wait_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'query_wait_timeout'\",\n source: \"src/janitor.c:343-344\",\n },\n {\n id: \"pbc.queued-query-timed-out\",\n from: \"waiting\",\n to: \"ended\",\n on: \"timer.query\",\n timer: \"query_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'query_timeout', before query_wait_timeout\",\n source: \"src/janitor.c:341-342\",\n },\n { id: \"pbc.released\", from: \"linked\", to: \"idle\", on: \"local.released\", timer: \"client_idle_timeout\", source: \"src/server.c:861-921, src/objects.c:1213-1322\" },\n { id: \"pbc.in-transaction\", from: \"linked\", to: \"linked\", on: \"rx.ready-in-transaction\", timer: \"idle_transaction_timeout\", source: \"src/server.c:433-455\" },\n {\n id: \"pbc.server-crashed\",\n from: \"linked\",\n to: \"ended\",\n on: \"server.crashed\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'server conn crashed?'. An ErrorResponse that the server sent before its close reaches the client first\",\n source: \"src/server.c:808-813, src/objects.c:1324-1344, :1375-1379\",\n },\n {\n id: \"pbc.server-send-failed\",\n from: \"linked\",\n to: \"ended\",\n on: \"server.send-failed\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'server connection closed'\",\n source: \"src/client.c:1799-1800\",\n },\n {\n id: \"pbc.query-timed-out\",\n from: \"linked\",\n to: \"ended\",\n on: \"timer.query\",\n timer: \"query_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'query timeout': PgBouncer sends Terminate to the server and closes it\",\n source: \"src/janitor.c:545-546\",\n },\n {\n id: \"pbc.idle-transaction-timed-out\",\n from: \"linked\",\n to: \"ended\",\n on: \"timer.idle-transaction\",\n timer: \"idle_transaction_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'idle transaction timeout'\",\n source: \"src/janitor.c:547-550\",\n },\n {\n id: \"pbc.transaction-timed-out\",\n from: \"linked\",\n to: \"ended\",\n on: \"timer.transaction\",\n timer: \"transaction_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'transaction timeout'\",\n source: \"src/janitor.c:551-553\",\n },\n {\n id: \"pbc.idle-timed-out\",\n from: \"idle\",\n to: \"ended\",\n on: \"timer.idle\",\n timer: \"client_idle_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'client_idle_timeout'\",\n source: \"src/janitor.c:307-308\",\n },\n {\n id: \"pbc.gone\",\n from: [\"login\", \"idle\", \"linked\"],\n to: \"ended\",\n on: [\"peer.fin\", \"peer.rst\", \"socket.error\", \"rx.terminate\"],\n note: \"'client unexpected eof', or 'client close request' for a Terminate. A linked server that was not ready is closed too\",\n source: \"src/client.c:1558-1560, :1789-1798, src/objects.c:1493-1534\",\n },\n {\n id: \"pbc.killed\",\n from: [\"login\", \"welcome\", \"idle\", \"waiting\", \"linked\"],\n to: \"ended\",\n on: \"admin.kill\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'database removed'\",\n source: \"src/janitor.c:788-813\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { login: \"ESTABLISHED\", welcome: \"ESTABLISHED\", idle: \"ESTABLISHED\", waiting: \"ESTABLISHED\", linked: \"ESTABLISHED\" },\n sets: {},\n ends: \"socket.error\",\n note: \"Each socket has TCP_NODELAY and SO_KEEPALIVE. At the defaults PgBouncer sets no time of the keepalive, thus the keepidle, the interval and the count of the namespace apply. A waiting client is not read: the kernel takes its FIN, and PgBouncer does not see it\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { PB, PB_COMMON } from \"./pgbouncer.ts\";\n\n/**\n * This document is PgBouncer 1.26.1 in transaction pooling, for one server connection of a pool:\n * from its launch to its close. It also gives the wait of the pool before its next connection after\n * a failed login.\n *\n * PgBouncer reads the socket of each idle server, thus the end of the stream or a reset of an idle\n * server closes it at once. A black hole stops nothing that PgBouncer reads. Only a check of the\n * server, a timer of the kernel, server_idle_timeout or server_lifetime removes such a server. The\n * check is the empty query before a reuse, when the server was idle for longer than\n * server_check_delay (30 s). It acts at the defaults, and no timer bounds its reply. Thus behind a\n * black hole, the client that waits for the check stays in the queue until its query_wait_timeout.\n *\n * The TCP connect has a timer of libevent of server_connect_timeout, in whole seconds. The janitor\n * also bounds the whole login by server_connect_timeout, from the launch. After a failed login the\n * pool starts no connection for server_login_retry from the launch of the failed one. In that time\n * each client that needs a server fails at once, and a waiting client stays in the queue.\n */\nexport const PGBOUNCER_SERVER: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"pgbouncer-server\",\n title: \"PgBouncer 1.26.1 in transaction pooling: one server connection of a pool, its login, its checks and its close\",\n layer: \"proxy\",\n version: \"1.26.1\",\n conditions: {\n pgbouncer: \"1.26.1\",\n pool_mode: \"transaction, set for the database or the user, or globally\",\n server: \"one PostgreSQL server over TCP, with no TLS, at an address that the configuration gives\",\n },\n sources: [\n ...PB_COMMON,\n { ref: `${PB} include/bouncer.h:69-89 and src/objects.c:292-369 the states of a server, each a list: SV_LOGIN, SV_IDLE, SV_ACTIVE, SV_USED, SV_TESTED. An idle server goes to the head of its list`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1876-1897 launch_new_connection: one connect of a pool at a time, and none for server_login_retry from the launch of a failed one`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1990-2008 the launch sets the time of the connect, before the DNS lookup and the TCP connect`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1638-1641 and src/sbuf.c:163-203, :1064-1102 the TCP connect waits for EV_WRITE with a timeout of libevent of server_connect_timeout in whole seconds. A timeout or an error is 'connect failed' (src/server.c:851-853)`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:558-570 the janitor closes a server in SV_LOGIN that is older than server_connect_timeout, from its launch: 'connect timeout'`, rung: \"implemented\" },\n {\n ref: \"run 39160356281 of mark1russell7/systems: with server_connect_timeout 128 s, the connect timer closed the socket 127.998993 s after its SYN in 1 of 11 runs, 1.007 ms before 128 s. libevent 2.1 counts a timeout from its cached time of the pass (event.c event_add_nolock, gettime with tv_cache)\",\n rung: \"observed\",\n },\n { ref: `${PB} src/objects.c:1385-1393, :1246-1248 a server in a login that closes marks the pool as failing, with the reason. A login that ends clears it`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:74-119, :176-199 an ErrorResponse at the login closes each waiting client of a pool with no server, except for 57P03`, rung: \"implemented\" },\n { ref: `${PB} src/sbuf.c:494-506, :965-973 the socket of a server is always read: an idle server is not paused`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:806-815 the end of the stream or an error of the socket of a server: 'server conn crashed?', with no Terminate`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:394-431, :469-478 the unused servers: server_idle_timeout from the last packet of the server, then server_lifetime from the launch, then server_check_delay, which makes an idle server SV_USED`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:59-99 launch_recheck: a client that finds only SV_USED servers makes the pool send the check query, SV_TESTED. The default <empty> sends the empty query (src/main.c:490-492), and only an empty string turns the check off (src/janitor.c:77-78, :426)`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:888-914 the reply of the check makes the server idle again`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1186-1210, :1268-1273 server_lifetime also closes a server at its release, one at a time each server_lifetime / pool_size`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1213-1322 the release: the server goes back to the head of the idle list, and the first waiting client gets it at once`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1498-1532 a client that goes while linked: a server that was not ready is closed with Terminate, else it goes back to the pool`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:177-192, :424-425 PAUSE closes each idle server: 'pause mode'`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:2311-2424 and src/loader.c:394-419 RECONNECT, or a RELOAD that changes the connection of a database, marks each server: an idle one closes at the next pass, a linked one at its release`, rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"No connection: the pool starts one for a waiting client, or for min_pool_size\" },\n connecting: { note: \"SV_LOGIN: the TCP connect, with the timer of libevent\" },\n login: { note: \"SV_LOGIN: the startup, the authentication and the first ReadyForQuery. The janitor bounds it from the launch\" },\n idle: { note: \"SV_IDLE: in the pool, ready for a client. PgBouncer reads its socket, thus it notices a close at once\" },\n used: { note: \"SV_USED: idle for longer than server_check_delay. A client that finds it waits for its check\" },\n tested: { note: \"SV_TESTED: the check query in flight. No timer bounds the wait for its reply\" },\n active: { note: \"SV_ACTIVE: linked to a client, for a query or a transaction\" },\n backoff: { note: \"The last login of the pool failed: no new connection for server_login_retry from the launch of that one\" },\n ended: { final: true, note: \"PgBouncer closed the server, with Terminate for a timer, or with no message after an error of the socket\" },\n },\n events: {\n \"local.launch\": { kind: \"local\", note: \"The pool starts a connection to the server\" },\n \"socket.connect\": { kind: \"local\", note: \"The TCP connect ends\" },\n \"rx.error-response\": { kind: \"rx\", note: \"An ErrorResponse of the server at the login\" },\n \"rx.ready-for-query\": { kind: \"rx\", note: \"A ReadyForQuery of the server\" },\n \"local.attached\": { kind: \"local\", note: \"A client gets the server\" },\n \"local.check\": { kind: \"local\", note: \"A client finds only servers that need a check\" },\n \"local.released\": { kind: \"local\", note: \"The server sends ReadyForQuery with the status I, and its data has gone to the client\" },\n \"client.gone\": { kind: \"peer\", note: \"The linked client closes or fails\" },\n \"client.timed-out\": { kind: \"local\", note: \"query_timeout, idle_transaction_timeout or transaction_timeout of the linked client\" },\n \"peer.fin\": { kind: \"peer\", note: \"The server closes the connection: a read gets the end of the stream\" },\n \"peer.rst\": { kind: \"peer\", note: \"A reset of the connection of the server\" },\n \"socket.error\": { kind: \"local\", note: \"The socket of the server fails with its own error\" },\n \"admin.pause\": { kind: \"app\", note: \"The PAUSE command of the console\" },\n \"admin.reconnect\": { kind: \"app\", note: \"RECONNECT, or a RELOAD that changes the connection of the database\" },\n \"tx.check\": { kind: \"tx\", note: \"The check query: the empty query at the defaults\" },\n \"tx.terminate\": { kind: \"tx\", note: \"The Terminate message, then the close of the socket\" },\n \"timer.connect-timeout\": { kind: \"timer\", note: \"The timer of libevent of the TCP connect fires\" },\n \"timer.login-timeout\": { kind: \"timer\", note: \"A pass of the janitor finds the login older than server_connect_timeout\" },\n \"timer.login-retry\": { kind: \"timer\", note: \"server_login_retry has passed since the launch of the failed connection\" },\n \"timer.idle\": { kind: \"timer\", note: \"A pass of the janitor finds the server idle for longer than server_idle_timeout\" },\n \"timer.lifetime\": { kind: \"timer\", note: \"A pass of the janitor finds the server older than server_lifetime\" },\n \"timer.check-delay\": { kind: \"timer\", note: \"A pass of the janitor finds the server idle for longer than server_check_delay\" },\n },\n knobs: {\n server_connect_timeout: {\n key: \"pgbouncer server_connect_timeout\",\n scope: \"proxy\",\n unit: \"s\",\n default: 15,\n off: 0,\n note: \"src/main.c:324. The TCP connect gets it in whole seconds (src/objects.c:1640-1641). At 0 the janitor does not bound the login (src/janitor.c:559)\",\n },\n server_login_retry: { key: \"pgbouncer server_login_retry\", scope: \"proxy\", unit: \"s\", default: 15, note: \"src/main.c:328\" },\n server_idle_timeout: {\n key: \"pgbouncer server_idle_timeout\",\n scope: \"proxy\",\n unit: \"s\",\n default: 600,\n off: 0,\n note: \"src/main.c:326. It has no effect while the pool is at min_pool_size or below (src/janitor.c:417)\",\n },\n server_lifetime: { key: \"pgbouncer server_lifetime\", scope: \"proxy\", unit: \"s\", default: 3600, note: \"src/main.c:327. At 0 a server is used one time (src/objects.c:1195-1207)\" },\n server_check_delay: {\n key: \"pgbouncer server_check_delay\",\n scope: \"proxy\",\n unit: \"s\",\n default: 30,\n note: \"src/main.c:322. The check needs a server_check_query that is not the empty string. Its default, the literal <empty>, sends the empty query, thus the check acts at the defaults (src/main.c:323, :490-492, src/janitor.c:77-91, :426)\",\n },\n janitor: { key: \"the period of the janitor of PgBouncer\", scope: \"process\", unit: \"ms\", default: 333.333, note: \"src/janitor.c:27-28: USEC / 3 in whole microseconds, 333333 µs\" },\n slack: {\n key: \"the lateness of the loop of events of PgBouncer for one pass\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of PgBouncer, as for the client\",\n },\n },\n timers: {\n connect_timeout: {\n duration: { knob: \"server_connect_timeout\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n early: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:connecting\"],\n cancels: [\"socket.connect\", \"socket.error\", \"peer.rst\"],\n fires: \"timer.connect-timeout\",\n note: \"src/objects.c:1640-1641, src/sbuf.c:163-203: a timeout of libevent on the wait for EV_WRITE, in whole seconds. Which clock libevent reads is an assumption of this document: the monotonic one. libevent counts the timeout from the time that it caches for the callbacks of one pass of its loop, thus from up to one pass before the connect: the timer can fire up to that pass early\",\n },\n login_timeout: {\n duration: { knob: \"server_connect_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:login\"],\n cancels: [\"rx.ready-for-query\", \"rx.error-response\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.login-timeout\",\n note: \"src/janitor.c:558-570: from the launch, thus the DNS lookup and the TCP connect come first. In the connect the timer of libevent fires first\",\n },\n login_retry: {\n duration: { knob: \"server_login_retry\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:backoff\"],\n fires: \"timer.login-retry\",\n note: \"src/objects.c:1889-1897: from the launch of the failed connection, not from its failure. A pool with a waiting client starts the next connection at the first loop after it\",\n },\n server_idle_timeout: {\n duration: { knob: \"server_idle_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:idle\"],\n cancels: [\"local.attached\"],\n fires: \"timer.idle\",\n note: \"src/janitor.c:408, :416-418: from the last packet of the server\",\n },\n server_lifetime: {\n duration: { knob: \"server_lifetime\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"local.launch\"],\n fires: \"timer.lifetime\",\n note: \"src/janitor.c:419-423, src/objects.c:1186-1210: from the launch, on an unused server. A linked server is not closed for its lifetime until its release\",\n },\n check_delay: {\n duration: { knob: \"server_check_delay\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:idle\"],\n cancels: [\"local.attached\"],\n fires: \"timer.check-delay\",\n note: \"src/janitor.c:426-428: at the defaults, the check of the empty query. A server_check_query of the empty string turns it off\",\n },\n },\n realizes: {\n \"systems.mechanism.connect-bound\": { timer: \"connect_timeout\" },\n \"systems.mechanism.pool-idle-expiry\": { timer: \"server_idle_timeout\" },\n \"systems.mechanism.max-connection-age\": { timer: \"server_lifetime\" },\n },\n transitions: [\n {\n id: \"pbs.launch\",\n from: \"[none]\",\n to: \"connecting\",\n on: \"local.launch\",\n guard: \"no connect of the pool is in progress\",\n timer: \"connect_timeout\",\n source: \"src/objects.c:1876-1887, :1990-2008\",\n },\n { id: \"pbs.connected\", from: \"connecting\", to: \"login\", on: \"socket.connect\", timer: \"login_timeout\", source: \"src/sbuf.c:1064-1102, src/server.c:851-858\" },\n {\n id: \"pbs.connect-failed\",\n from: \"connecting\",\n to: \"backoff\",\n on: [\"socket.error\", \"peer.rst\", \"timer.connect-timeout\"],\n timer: \"login_retry\",\n errno: \"connect failed\",\n note: \"The pool caches the reason. A client that needs a server and finds none then fails at once\",\n source: \"src/server.c:851-853, src/objects.c:1385-1393, :869-900\",\n },\n {\n id: \"pbs.login-timed-out\",\n from: \"login\",\n to: \"backoff\",\n on: \"timer.login-timeout\",\n timer: \"login_retry\",\n errno: \"connect timeout\",\n source: \"src/janitor.c:558-570, src/objects.c:1385-1393\",\n },\n {\n id: \"pbs.login-failed\",\n from: \"login\",\n to: \"backoff\",\n on: [\"rx.error-response\", \"peer.fin\", \"peer.rst\", \"socket.error\"],\n timer: \"login_retry\",\n note: \"An ErrorResponse closes each waiting client of a pool with no server, with the SQLSTATE of the server, except 57P03\",\n source: \"src/server.c:74-119, :176-199\",\n },\n { id: \"pbs.retry\", from: \"backoff\", to: \"connecting\", on: \"timer.login-retry\", guard: \"a client waits for a server\", timer: \"connect_timeout\", source: \"src/objects.c:1889-1897, src/janitor.c:166-170\" },\n {\n id: \"pbs.logged-in\",\n from: \"login\",\n to: \"idle\",\n on: \"rx.ready-for-query\",\n timer: \"server_idle_timeout\",\n note: \"The pool gets its welcome message, and the first waiting client gets the server at once\",\n source: \"src/objects.c:1246-1248, :994-1014\",\n },\n { id: \"pbs.attach\", from: \"idle\", to: \"active\", on: \"local.attached\", source: \"src/objects.c:934-975\" },\n {\n id: \"pbs.release\",\n from: \"active\",\n to: \"idle\",\n on: \"local.released\",\n guard: \"the server is younger than server_lifetime and has no close_needed\",\n timer: \"server_idle_timeout\",\n source: \"src/server.c:861-921, src/objects.c:1213-1322\",\n },\n {\n id: \"pbs.close-at-release\",\n from: \"active\",\n to: \"ended\",\n on: \"local.released\",\n guard: \"the server is older than server_lifetime, or has close_needed\",\n emits: [\"tx.terminate\"],\n note: \"'server lifetime over' or 'close_needed'\",\n source: \"src/objects.c:1268-1291\",\n },\n {\n id: \"pbs.crashed\",\n from: [\"login\", \"idle\", \"used\", \"tested\", \"active\"],\n to: \"ended\",\n on: [\"peer.fin\", \"peer.rst\", \"socket.error\"],\n note: \"'server conn crashed?'. A linked client gets it as FATAL 08P01 and is closed. An idle server goes with no effect on a client\",\n source: \"src/server.c:806-815, src/objects.c:1375-1384\",\n },\n { id: \"pbs.idle-timed-out\", from: [\"idle\", \"used\", \"tested\"], to: \"ended\", on: \"timer.idle\", emits: [\"tx.terminate\"], note: \"'server idle timeout'\", source: \"src/janitor.c:416-418\" },\n { id: \"pbs.lifetime-over\", from: [\"idle\", \"used\", \"tested\"], to: \"ended\", on: \"timer.lifetime\", emits: [\"tx.terminate\"], note: \"'server lifetime over'\", source: \"src/janitor.c:419-423\" },\n { id: \"pbs.check-due\", from: \"idle\", to: \"used\", on: \"timer.check-delay\", guard: \"server_check_query is not the empty string: its default <empty> is the empty query\", source: \"src/janitor.c:426-428, src/main.c:490-492\" },\n { id: \"pbs.check\", from: \"used\", to: \"tested\", on: \"local.check\", emits: [\"tx.check\"], source: \"src/janitor.c:59-99\" },\n { id: \"pbs.checked\", from: \"tested\", to: \"idle\", on: \"rx.ready-for-query\", timer: \"server_idle_timeout\", source: \"src/server.c:888-914\" },\n {\n id: \"pbs.client-gone-dirty\",\n from: \"active\",\n to: \"ended\",\n on: \"client.gone\",\n guard: \"the server was not ready: a query or a transaction in flight\",\n emits: [\"tx.terminate\"],\n note: \"'client disconnect while server was not ready'\",\n source: \"src/objects.c:1498-1512\",\n },\n { id: \"pbs.client-gone-clean\", from: \"active\", to: \"idle\", on: \"client.gone\", guard: \"the server was ready\", timer: \"server_idle_timeout\", source: \"src/objects.c:1529-1532\" },\n { id: \"pbs.client-timed-out\", from: \"active\", to: \"ended\", on: \"client.timed-out\", emits: [\"tx.terminate\"], note: \"The timer of the client closes the server too\", source: \"src/janitor.c:545-553\" },\n { id: \"pbs.paused\", from: [\"idle\", \"used\"], to: \"ended\", on: \"admin.pause\", emits: [\"tx.terminate\"], note: \"'pause mode'. A linked server stays until its release\", source: \"src/janitor.c:177-192\" },\n {\n id: \"pbs.reconnect\",\n from: [\"idle\", \"used\"],\n to: \"ended\",\n on: \"admin.reconnect\",\n emits: [\"tx.terminate\"],\n note: \"'database configuration changed'. A linked server closes at its release\",\n source: \"src/janitor.c:410-411, src/objects.c:1287-1291\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { connecting: \"SYN_SENT\", login: \"ESTABLISHED\", idle: \"ESTABLISHED\", used: \"ESTABLISHED\", tested: \"ESTABLISHED\", active: \"ESTABLISHED\" },\n sets: {},\n ends: \"socket.error\",\n note: \"As for the client: TCP_NODELAY and SO_KEEPALIVE, with the times of the keepalive of the namespace at the defaults. PgBouncer reads each server socket, thus the kernel's end of a socket reaches it at once\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the C source of Pgpool-II at the tag V4_7_3 (commit\n// 07d24655e42dfdbfe2e7549df6166e057b99b622, the tarball of GitHub with SHA-256 e48ff26f...e2acd2).\n// Each line number is a line of that file at the tag. A fact of the kernel is an assumption of this\n// document, and its note says so.\nexport const PP = \"V4_7_3\";\n\n/**\n * This document is Pgpool-II 4.7.3 with one backend, for one session of a client. It gives the states\n * of the session in its child process, from the accept of the client to its close. It also gives the\n * timers that act on it.\n *\n * A child process serves one client at a time. Between two queries it waits in one select() on the\n * client and on the backend. Thus the close of either side ends the session at once. At the defaults\n * no timer bounds an idle session: client_idle_limit is 0.\n *\n * While a query is in flight, the child waits on the backend only. It does not read the client, and\n * no timer of Pgpool-II ends the query. Each 30 s of that wait, it writes a dummy ParameterStatus to\n * the client, and a failed write ends the session.\n *\n * An error of a session reaches the client as an ErrorResponse, with the SQLSTATE of Pgpool-II or\n * XX000. The FIN of the backend ends the session with a FATAL error. A failed read of the backend,\n * for example a reset, and a failed connect to the backend ask the main process for a failover\n * (failover_on_backend_error).\n */\nexport const PGPOOL_SESSION: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"pgpool-session\",\n title: \"Pgpool-II 4.7.3 with one backend: one session of a client in its child process\",\n layer: \"proxy\",\n version: \"4.7.3\",\n conditions: {\n pgpool: \"4.7.3\",\n backend_clustering_mode: \"streaming_replication, the default, with one backend\",\n client: \"a PostgreSQL client over TCP, with no TLS\",\n backend: \"one PostgreSQL server\",\n },\n sources: [\n {\n ref: `${PP} src/config/pool_config_variables.c:570-607, :1661-1761, :2003-2121, :2388-2396 the defaults: connection_cache on, failover_on_backend_error on, failover_on_backend_shutdown off, health_check_period 0, health_check_timeout 20 s, connect_timeout 10000 ms, num_init_children 32, child_life_time 300 s, client_idle_limit 0, connection_life_time 0, authentication_timeout 60 s, max_pool 4, backend_clustering_mode streaming_replication`,\n rung: \"implemented\",\n },\n { ref: `${PP} src/protocol/pool_connection_pool.c:849 and src/protocol/child.c:1789, :1981 each socket to the backend and to the client gets TCP_NODELAY. Only the watchdog sets SO_KEEPALIVE (src/watchdog/watchdog.c:961, :1089)`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/child.c:163-516 do_child: wait for a client, check that a backend is up, connect or reuse the backend, then the loop of pool_process_query until the session ends`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/child.c:617-632, :800, :1281-1310 authentication_timeout: an alarm over the read of the startup packet. Its expiry exits the child`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/child.c:2016-2170 get_backend_connection: the startup packet, then a connection of the pool of the child for the same user, database and startup packet, else a new connect. With enable_pool_hba off, the backend does the authentication`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/child.c:344-353, :1670-1691 child_life_time counts the 1 s timeouts of a child that waits for a client: it never ends a session`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/pool_connection_pool.c:590-669 the connect to the backend is non-blocking, and one select() bounds it by connect_timeout. At 0 it has no bound`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/pool_connection_pool.c:953-1012 a failed connect to the backend: with failover_on_backend_error, a request of failover, then FATAL 'failed to create a backend connection'`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/pool_process_query.c:4867-5002 between two queries: one select() on the client and on each backend. With client_idle_limit, its timeout is 1 s, and more than client_idle_limit timeouts end the session with 57000`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/pool_process_query.c:5004-5146 a backend that is readable between two queries: its error or its end is read at once`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/pool_process_query.c:539-627 and src/context/pool_query_context.c:658-693, :877-911 each query waits for its backend in steps of 30 s. After each step with no data, a dummy ParameterStatus goes to the client, and a failed flush ends the session`, rung: \"implemented\" },\n { ref: `${PP} src/utils/pool_stream.c:1303-1387 pool_check_fd: one select() with the timeout of the step, or none`, rung: \"implemented\" },\n { ref: `${PP} src/utils/pool_stream.c:225-248 a failed read of the backend: with failover_on_backend_error, a request of failover, then the child exits`, rung: \"implemented\" },\n { ref: `${PP} src/utils/pool_stream.c:263-276 a read of 0 bytes from the backend, its FIN: FATAL 'unable to read data from DB node', and no failover`, rung: \"implemented\" },\n { ref: `${PP} src/utils/error/elog.c:1888-2007 an error of the session goes to the client as an ErrorResponse: its severity, the SQLSTATE of Pgpool-II or XX000, and the message`, rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"Before the child accepts the connection\" },\n login: { note: \"The read of the startup packet. The alarm of authentication_timeout runs\" },\n connecting: { note: \"The connect to the backend and its authentication, when the pool of the child has no connection for the user and the database. The select() of the connect is bounded by connect_timeout\" },\n idle: { note: \"Between two queries: one select() on the client and on the backend, thus a close of either side is read at once\" },\n waiting: { note: \"A query in flight: the child waits on the backend only, in steps of 30 s. It does not read the client\" },\n ended: { final: true, note: \"The child closed the client, after an ErrorResponse for an error, or the client went\" },\n },\n events: {\n \"local.accept\": { kind: \"local\", note: \"The child accepts the TCP connection\" },\n \"rx.startup\": { kind: \"rx\", note: \"The startup packet of the client\" },\n \"local.cached\": { kind: \"local\", note: \"The pool of the child has a connection for the user and the database: no connect\" },\n \"local.connected\": { kind: \"local\", note: \"The connect to the backend succeeds\" },\n \"rx.query\": { kind: \"rx\", note: \"The first packet of a query of the client\" },\n \"rx.ready-for-query\": { kind: \"rx\", note: \"The backend sends ReadyForQuery: the end of the query\" },\n \"backend.eof\": { kind: \"peer\", note: \"A read of the backend gets 0 bytes: its FIN\" },\n \"backend.error\": { kind: \"peer\", note: \"A read or a select() of the backend fails: a reset, or an error of the socket\" },\n \"frontend.eof\": { kind: \"peer\", note: \"The client closes its connection, or a write to it fails\" },\n \"timer.auth\": { kind: \"timer\", note: \"The alarm of authentication_timeout\" },\n \"timer.connect\": { kind: \"timer\", note: \"The select() of the connect to the backend times out\" },\n \"timer.idle\": { kind: \"timer\", note: \"More than client_idle_limit timeouts of 1 s of the select() between two queries\" },\n \"timer.probe\": { kind: \"timer\", note: \"A step of 30 s of the wait for the backend ends with no data\" },\n \"tx.error\": { kind: \"tx\", note: \"An ErrorResponse: its severity, the SQLSTATE of Pgpool-II or XX000, and the message\" },\n \"tx.probe\": { kind: \"tx\", note: \"A dummy ParameterStatus to the client: pgpool_dummy_param = pgpool_dummy_value\" },\n \"tx.failover\": { kind: \"local\", note: \"A request of failover for the backend to the main process\" },\n },\n knobs: {\n authentication_timeout: { key: \"pgpool authentication_timeout\", scope: \"proxy\", unit: \"s\", default: 60, off: 0, note: \"src/config/pool_config_variables.c:2102-2110\" },\n connect_timeout: { key: \"pgpool connect_timeout\", scope: \"proxy\", unit: \"ms\", default: 10000, off: 0, note: \"src/config/pool_config_variables.c:1745-1761. It bounds the connect to the backend\" },\n client_idle_limit: { key: \"pgpool client_idle_limit\", scope: \"proxy\", unit: \"s\", default: 0, off: 0, note: \"src/config/pool_config_variables.c:2069-2077\" },\n tick: {\n key: \"the timeout of the select() between two queries when client_idle_limit is set\",\n scope: \"process\",\n unit: \"s\",\n default: 1,\n note: \"src/protocol/pool_process_query.c:4938-4947: a constant of the source, not a setting\",\n },\n probe: {\n key: \"the step of the wait for the backend of a query\",\n scope: \"process\",\n unit: \"s\",\n default: 30,\n note: \"src/protocol/pool_process_query.c:561: a constant of the source, not a setting\",\n },\n slack: {\n key: \"the lateness of the loop of the child for one step\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of Pgpool-II: the child does each step in one process with no other work\",\n },\n },\n timers: {\n authentication_timeout: {\n duration: { knob: \"authentication_timeout\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:login\"],\n cancels: [\"rx.startup\"],\n fires: \"timer.auth\",\n note: \"src/protocol/child.c:617-632, :1281-1310: alarm() in whole seconds\",\n },\n connect_timeout: {\n duration: { knob: \"connect_timeout\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:connecting\"],\n cancels: [\"local.connected\", \"backend.error\"],\n fires: \"timer.connect\",\n note: \"src/protocol/pool_connection_pool.c:645-669\",\n },\n client_idle_limit: {\n duration: { expr: \"client_idle_limit + tick\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:idle\"],\n cancels: [\"rx.query\"],\n fires: \"timer.idle\",\n note: \"src/protocol/pool_process_query.c:4962-4976: each timeout of 1 s counts, and the count must exceed client_idle_limit, thus the session ends one tick after the limit. Each packet starts the count again. No bound at the defaults\",\n },\n probe: {\n duration: { knob: \"probe\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:waiting\"],\n cancels: [\"rx.ready-for-query\"],\n fires: \"timer.probe\",\n backoff: { resets: [\"enter:waiting\"] },\n note: \"src/protocol/pool_process_query.c:558-595: each wait is 30 s, the same each time. It does not end the query: it checks the client\",\n },\n },\n transitions: [\n { id: \"pps.accept\", from: \"[none]\", to: \"login\", on: \"local.accept\", timer: \"authentication_timeout\", source: \"src/protocol/child.c:342-398\" },\n { id: \"pps.reuse\", from: \"login\", to: \"idle\", on: \"local.cached\", guard: \"the pool of the child has a connection for the user, the database and the same startup packet (connection_cache)\", timer: \"client_idle_limit\", source: \"src/protocol/child.c:2112-2166\" },\n { id: \"pps.connect\", from: \"login\", to: \"connecting\", on: \"rx.startup\", guard: \"no connection in the pool of the child\", timer: \"connect_timeout\", source: \"src/protocol/child.c:2153-2160, src/protocol/pool_connection_pool.c:907-955\" },\n { id: \"pps.connected\", from: \"connecting\", to: \"idle\", on: \"local.connected\", timer: \"client_idle_limit\", source: \"src/protocol/pool_connection_pool.c:1013-1019\" },\n {\n id: \"pps.connect-failed\",\n from: \"connecting\",\n to: \"ended\",\n on: [\"timer.connect\", \"backend.error\"],\n errno: \"XX000\",\n emits: [\"tx.failover\", \"tx.error\"],\n note: \"FATAL 'failed to create a backend connection', 'executing failover on backend'\",\n source: \"src/protocol/pool_connection_pool.c:953-969\",\n },\n {\n id: \"pps.auth-timed-out\",\n from: \"login\",\n to: \"ended\",\n on: \"timer.auth\",\n timer: \"authentication_timeout\",\n note: \"The child exits\",\n source: \"src/protocol/child.c:1281-1287\",\n },\n { id: \"pps.query\", from: \"idle\", to: \"waiting\", on: \"rx.query\", timer: \"probe\", source: \"src/context/pool_query_context.c:658-693, :877-911\" },\n { id: \"pps.reply\", from: \"waiting\", to: \"idle\", on: \"rx.ready-for-query\", timer: \"client_idle_limit\", source: \"src/protocol/pool_process_query.c:558-626\" },\n { id: \"pps.probe\", from: \"waiting\", to: \"waiting\", on: \"timer.probe\", timer: \"probe\", emits: [\"tx.probe\"], note: \"The dummy ParameterStatus, each 30 s of the wait\", source: \"src/protocol/pool_process_query.c:570-595\" },\n {\n id: \"pps.idle-timed-out\",\n from: \"idle\",\n to: \"ended\",\n on: \"timer.idle\",\n timer: \"client_idle_limit\",\n errno: \"57000\",\n emits: [\"tx.error\"],\n note: \"'child connection forced to terminate due to client_idle_limit:%d is reached'\",\n source: \"src/protocol/pool_process_query.c:4965-4976\",\n },\n {\n id: \"pps.backend-eof\",\n from: [\"idle\", \"waiting\"],\n to: \"ended\",\n on: \"backend.eof\",\n errno: \"XX000\",\n emits: [\"tx.error\"],\n note: \"FATAL 'unable to read data from DB node', 'EOF encountered with backend', with no request of failover\",\n source: \"src/utils/pool_stream.c:263-276, src/protocol/pool_process_query.c:5021-5146\",\n },\n {\n id: \"pps.backend-error\",\n from: [\"idle\", \"waiting\"],\n to: \"ended\",\n on: \"backend.error\",\n emits: [\"tx.failover\"],\n note: \"The child exits before it reports the error, thus the client gets the close only\",\n source: \"src/utils/pool_stream.c:225-248\",\n },\n {\n id: \"pps.gone\",\n from: [\"login\", \"idle\", \"waiting\"],\n to: \"ended\",\n on: \"frontend.eof\",\n note: \"Between two queries the child reads the close at once. In a wait it finds it only at the write of a probe or of the reply\",\n source: \"src/protocol/pool_process_query.c:570-595, :4895-4933\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { login: \"ESTABLISHED\", connecting: \"ESTABLISHED\", idle: \"ESTABLISHED\", waiting: \"ESTABLISHED\" },\n sets: {},\n ends: \"frontend.eof\",\n note: \"The socket of the client. It has TCP_NODELAY and no SO_KEEPALIVE. In a wait the child does not read it: the kernel takes its FIN, and Pgpool-II finds it at the next write\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the source of PostgreSQL at the tag REL_17_11. Each line number\n// is a line of that file at that tag. A ref under doc/ is the documentation at the same tag.\nconst AT = \"postgresql REL_17_11 src\";\nconst DOC = \"postgresql REL_17_11 doc/src/sgml\";\n\n/**\n * This document is the hold of a PostgreSQL 17.11 backend on one client connection, over its TCP\n * socket on Linux. The backend turns on SO_KEEPALIVE for each TCP socket. At the defaults of its\n * four TCP GUCs, it changes no keepalive option and no user timeout. Thus the namespace sysctls\n * give the idle time, the interval and the count. A GUC above 0 sets its socket option.\n *\n * Each timer of a backend is a SIGALRM timeout. At startup, the handler ends the process at once.\n * After the startup packet, each handler sets a flag and the latch, directly or by a signal. The\n * backend then acts at its next CHECK_FOR_INTERRUPTS. An idle timer and the transaction timer end\n * the session with FATAL. The statement timer and the lock timer end the statement with ERROR.\n *\n * A send to a slow or a lost client waits for the socket with no timeout. In that wait the\n * backend acts on SIGTERM and on the death of the postmaster only. A timer that fires there takes\n * effect after the send. Thus PostgreSQL gives no bound to a send: the kernel ends it, or SIGTERM\n * does.\n *\n * A timeout knob at 0 has no timer: give it as no bound (`infinite`). This is true of\n * `statement_timeout`, `lock_timeout`, `transaction_timeout`, `idle_in_transaction_session_timeout`,\n * `idle_session_timeout` and `client_connection_check_interval`.\n */\nexport const POSTGRES_SESSION: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"postgres-session\",\n title: \"A client connection as a PostgreSQL 17.11 backend holds it, over its Linux socket\",\n layer: \"server\",\n version: \"17.11\",\n conditions: {\n postgresql: \"17.11\",\n os: \"linux\",\n image: \"postgres:17.11 (Debian trixie), index sha256:2d2b8998d31037bf721cfdf764d76ba74171b4fab3431b7f72c27c56ddbdf9e3\",\n socket: \"TCP: on a Unix-domain socket the backend sets no keepalive option\",\n },\n sources: [\n { ref: \"postgresql REL_17_11 meson.build:11 version 17.11\", rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/backend_startup.c:157-161 BackendInitialize calls pq_init in the backend, before the startup packet`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:793-817 AcceptConnection in the postmaster, :180 the Port starts at zeros, :195-220 TCP_NODELAY and SO_KEEPALIVE on each socket that is not AF_UNIX, a failure is FATAL, :264-274 then the four TCP GUCs, a failure is a LOG only`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:1663-1711 pq_setkeepalivesidle: no call at a value equal to the Port's, and 0 sets the value that getsockopt read first; :1748-1795, :1827-1870 and :1902-1945 the same for TCP_KEEPINTVL, TCP_KEEPCNT and TCP_USER_TIMEOUT`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:87-90 TCP_KEEPIDLE on Linux, :1947-2047 an assign hook sets the socket of the session at once, and a show hook reads the kernel`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/misc/guc_tables.c:3452-3461 tcp_keepalives_idle 0 s, :3463-3472 tcp_keepalives_interval 0 s, :3485-3495 tcp_keepalives_count 0, :3587-3596 tcp_user_timeout 0 ms: each PGC_USERSET, 0 to INT_MAX, 0 is the system default`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/misc/guc_tables.c:2611-2620 statement_timeout, :2622-2631 lock_timeout, :2633-2642 idle_in_transaction_session_timeout, :2644-2653 transaction_timeout, :2655-2664 idle_session_timeout: each 0 ms, 0 to INT_MAX, PGC_USERSET, 0 turns it off`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/misc/guc_tables.c:2774-2783 authentication_timeout 60 s, 1 to 600, PGC_SIGHUP; :3632-3641 client_connection_check_interval 0 ms, 0 to INT_MAX, PGC_USERSET`, rung: \"implemented\" },\n { ref: `${AT}/backend/storage/lmgr/proc.c:58-62, backend/tcop/postgres.c:106 and backend/postmaster/postmaster.c:228 the C defaults agree: 0 ms for each timeout, 0 ms for the client check, 60 s for authentication`, rung: \"implemented\" },\n { ref: `${AT}/include/utils/timeout.h:3-4 and :23-43 one SIGALRM for each timeout id, STARTUP_PACKET_TIMEOUT to CLIENT_CONNECTION_CHECK_TIMEOUT`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/misc/timeout.c:559-575 enable_timeout_after: the deadline is the current time + the delay in ms, :209-350 schedule_alarm: setitimer(ITIMER_REAL) for the nearest deadline, :363-453 handle_sig_alarm sets the latch and calls each handler that is due`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/init/postinit.c:770-782 the handlers of a backend, :1374-1407 the statement timer sends SIGINT, or SIGTERM in authentication, and the lock timer sends SIGINT, :1409-1447 each other handler sets a flag and the latch`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:2999-3023 die (SIGTERM) sets ProcDiePending, :3029-3043 StatementCancelHandler (SIGINT) sets QueryCancelPending, :4292-4294 the two handlers`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:3271-3319 ProcessInterrupts acts on a die request first: FATAL 57014 \"canceling authentication due to timeout\" in authentication, else FATAL 57P01 \"terminating connection due to administrator command\"`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:3321-3350 then the client check, then a lost connection: FATAL 08006 \"connection to client lost\", with no message to the client`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:3372-3430 a cancel: ERROR 55P03 \"canceling statement due to lock timeout\", ERROR 57014 \"canceling statement due to statement timeout\"`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:3435-3477 FATAL 25P03 \"terminating connection due to idle-in-transaction timeout\", FATAL 25P04 \"terminating connection due to transaction timeout\", FATAL 57P05 \"terminating connection due to idle-session timeout\"`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/errcodes.txt:106-107 08003 and 08006, :111 08P01, :254-255 25P03 and 25P04, :421 55P03, :428-429 57014 and 57P01, :433 57P05`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:4618-4706 at ReadyForQuery the backend arms idle_in_transaction_session_timeout in a transaction block, open or aborted, and idle_session_timeout outside one; :4714-4750 after a message it disarms them, then checks for interrupts`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:2770-2796 start_xact_command arms statement_timeout and the client check, each only when not active, :2798-2802 finish_xact_command disarms statement_timeout, :5251-5278 no statement timer when statement_timeout >= transaction_timeout > 0`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/adt/misc.c:391-412 pg_sleep: CHECK_FOR_INTERRUPTS before each WaitLatch on the latch of the backend, thus the SIGALRM of a timeout ends its wait`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:4446-4502 an ERROR: disable_all_timeouts, the error to the client, AbortCurrentTransaction; :4562-4563 then ReadyForQuery`, rung: \"implemented\" },\n { ref: `${AT}/backend/access/transam/xact.c:2174-2176 StartTransaction arms transaction_timeout, :2315-2317, :2592-2594 and :2768-2770 commit, prepare and abort disarm it, :3472-3477 an error in a transaction block aborts the transaction and keeps the block`, rung: \"implemented\" },\n { ref: `${AT}/backend/storage/lmgr/proc.c:1292-1307 ProcSleep arms lock_timeout with the deadlock timer, :1652-1666 and disarms it after the wait`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:3652-3661 a client_connection_check_interval above 0 needs a wait set that reports a close`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:2049-2084 pq_check_connection: a wait of 0 ms for WL_SOCKET_CLOSED`, rung: \"implemented\" },\n { ref: `${AT}/backend/storage/ipc/latch.c:72-85 epoll where sys/epoll.h exists, :1131-1156 WL_SOCKET_CLOSED adds EPOLLRDHUP, and EPOLLERR and EPOLLHUP are always on, :1661-1680 EPOLLERR or EPOLLHUP make the socket readable, writable and closed, :2253-2263 epoll can report a close`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/be-secure.c:174-261 secure_read and :300-370 secure_write: a wait for the socket or the latch with no timeout; at the latch, ProcessClientReadInterrupt or ProcessClientWriteInterrupt; :234-237 and :343-346 FATAL 57P01 at the death of the postmaster`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:513-548 ProcessClientReadInterrupt: each interrupt in the wait for a command, a die request in another read; :559-600 ProcessClientWriteInterrupt: a die request only, with no message to the client`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:287-297 the socket has O_NONBLOCK, and the latch gives the waits; :896-956 pq_recvbuf: 0 bytes or an error is EOF, and an error logs COMMERROR \"could not receive data from client: %m\"`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:364-396 SocketBackend: EOF in a transaction logs COMMERROR 08006 \"unexpected EOF on client connection with an open transaction\", else DEBUG1 08003; :4988-5016 EOF or Terminate: proc_exit(0)`, rung: \"implemented\" },\n { ref: `${AT}/backend/access/transam/xact.c:383-396 IsTransactionState is TRANS_INPROGRESS only; backend/utils/init/postinit.c:1360-1371 ShutdownPostgres aborts the transaction at exit`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:1275-1336 a full buffer flushes, and the flush waits for the socket, :1358-1423 internal_flush_buffer: an error logs COMMERROR \"could not send data to client: %m\" once for each errno, drops the buffer and sets ClientConnectionLost`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:4310-4316 the backend ignores SIGPIPE`, rung: \"implemented\" },\n { ref: `${AT}/include/utils/elog.h:31-38 COMMERROR is LOG_SERVER_ONLY; backend/utils/error/elog.c:205-228 it goes to the log at log_min_messages WARNING (guc_tables.c:534), and DEBUG1 does not`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/error/elog.c:245-262 and :1726-1732 an error goes to the client while the output is DestRemote, :3643-3651 the backend flushes it, :559-590 FATAL ends the process with proc_exit(1)`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:347-392 socket_close keeps the socket open until the process exits`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/backend_startup.c:237-253 the startup timer: authentication_timeout, after the DNS lookup, :311-314 the end of the startup packet disarms it, :895-922 its handler and SIGTERM call _exit(1), with no log and no message`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/backend_startup.c:460-519 ProcessStartupPacket: no byte is a silent end, a part of a packet logs COMMERROR 08P01 \"incomplete startup packet\"; :328-333 proc_exit(0)`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/init/postinit.c:235-251 PerformAuthentication arms the statement timer at authentication_timeout * 1000 ms, :305 ClientAuthInProgress ends after it, :1210-1215 the GUCs of the startup packet apply after it`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/auth.c:260-271 an EOF from the client in authentication: proc_exit(0), with no log; :714-744 recv_password_packet gives an EOF as NULL`, rung: \"implemented\" },\n { ref: `${DOC}/config.sgml:961-972, :984-995, :1007-1016 and :1027-1037 a value of 0 selects the default of the OS; :1047-1073 the client check polls the socket, and without it the server sees a loss only at its next read or send`, rung: \"documented\" },\n { ref: `${DOC}/config.sgml:9474-9482 statement_timeout counts from the arrival of a command, :9501-9504 transaction_timeout is for a transaction block and for the transaction of one statement, :9510-9512 a transaction_timeout at or below another timeout makes the server ignore the other one, :9521-9525 a prepared transaction has no transaction timer`, rung: \"documented\" },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n STARTUP: { note: \"The backend reads the startup packet. Its timer is authentication_timeout (backend_startup.c:237-253)\" },\n AUTHENTICATING: { note: \"The authentication exchange, with a second timer of authentication_timeout (postinit.c:235-251)\" },\n IDLE: { note: \"The backend waits for a message, outside a transaction block (postgres.c:4648-4699)\" },\n IDLE_IN_TRANSACTION: { note: \"The backend waits for a message in a transaction block, open or aborted (postgres.c:4620-4647)\" },\n RUNNING: {\n note: \"The backend runs a command. Without the client check, it sees a loss of the client only at its next read or send (config.sgml:1059-1063)\",\n },\n SENDING: {\n note: \"A send gives EAGAIN, and the backend waits for the socket with no timeout (be-secure.c:331-361). In this wait it acts on SIGTERM and on the death of the postmaster only (postgres.c:559-600, be-secure.c:343-346). A timer that fires here sets its flag, and the backend acts on it after the send\",\n },\n GONE: { final: true, note: \"The backend exits, and the socket closes with the process (pqcomm.c:380-390)\" },\n },\n events: {\n accept: { kind: \"local\", note: \"The postmaster accepts the connection. The backend sets TCP_NODELAY and SO_KEEPALIVE in pq_init\" },\n \"rx.startup\": { kind: \"rx\", note: \"The startup packet of the client, with its GUCs\" },\n \"local.authenticated\": { kind: \"local\", note: \"ClientAuthentication returns, and InitPostgres continues to ReadyForQuery\" },\n \"rx.message\": { kind: \"rx\", note: \"A message of a command: Query, Parse, Bind, Execute or another\" },\n \"rx.terminate\": { kind: \"rx\", note: \"A Terminate message: the client ends the session\" },\n \"tx.ready-for-query\": { kind: \"tx\", note: \"ReadyForQuery: the backend waits for the next message\" },\n \"tx.error\": { kind: \"tx\", note: \"An ErrorResponse: the backend aborts the transaction, then sends ReadyForQuery\" },\n \"local.statement-done\": { kind: \"local\", note: \"finish_xact_command at the end of a statement\" },\n \"local.lock-wait\": { kind: \"local\", note: \"ProcSleep: the backend waits for a heavyweight lock\" },\n \"local.lock-granted\": { kind: \"local\" },\n \"local.transaction-start\": { kind: \"local\", note: \"StartTransaction, for a transaction block or for one statement\" },\n \"local.transaction-end\": { kind: \"local\", note: \"A commit, a prepare or an abort\" },\n \"local.send-blocked\": { kind: \"local\", note: \"The send buffer is full, and send gives EAGAIN\" },\n \"local.writable\": { kind: \"local\", note: \"The socket takes bytes again\" },\n \"local.die\": { kind: \"local\", note: \"SIGTERM: the die handler sets ProcDiePending\" },\n \"peer.fin\": { kind: \"peer\", note: \"A read gives 0 bytes: the client closed\" },\n \"peer.rst\": { kind: \"peer\" },\n \"socket.error\": { kind: \"local\", note: \"A read or a send fails with the error of the socket: the machine below ended it\" },\n \"timer.startup-packet\": { kind: \"timer\" },\n \"timer.authentication\": { kind: \"timer\" },\n \"timer.statement\": { kind: \"timer\" },\n \"timer.lock\": { kind: \"timer\" },\n \"timer.transaction\": { kind: \"timer\" },\n \"timer.idle-in-transaction\": { kind: \"timer\" },\n \"timer.idle-session\": { kind: \"timer\" },\n \"timer.client-check\": { kind: \"timer\", note: \"A poll of 0 ms for a close of the socket\" },\n },\n knobs: {\n tcp_keepalive_time: { key: \"net.ipv4.tcp_keepalive_time\", scope: \"netns\", unit: \"s\", default: 7200, note: \"The value of a new socket, which the backend keeps at tcp_keepalives_idle 0\" },\n tcp_keepalive_intvl: { key: \"net.ipv4.tcp_keepalive_intvl\", scope: \"netns\", unit: \"s\", default: 75, note: \"The value of a new socket, which the backend keeps at tcp_keepalives_interval 0\" },\n tcp_keepalive_probes: { key: \"net.ipv4.tcp_keepalive_probes\", scope: \"netns\", unit: \"count\", default: 9, note: \"The value of a new socket, which the backend keeps at tcp_keepalives_count 0\" },\n tcp_keepalives_idle: {\n key: \"postgresql tcp_keepalives_idle\",\n scope: \"session\",\n unit: \"s\",\n default: 0,\n note: \"guc_tables.c:3452-3461. At 0 the backend makes no call, and the socket keeps tcp_keepalive_time (pqcomm.c:1671-1672). Above 0 it sets TCP_KEEPIDLE\",\n },\n tcp_keepalives_interval: {\n key: \"postgresql tcp_keepalives_interval\",\n scope: \"session\",\n unit: \"s\",\n default: 0,\n note: \"guc_tables.c:3463-3472. At 0 the socket keeps tcp_keepalive_intvl (pqcomm.c:1755-1756). Above 0 the backend sets TCP_KEEPINTVL\",\n },\n tcp_keepalives_count: {\n key: \"postgresql tcp_keepalives_count\",\n scope: \"session\",\n unit: \"count\",\n default: 0,\n note: \"guc_tables.c:3485-3495. At 0 the socket keeps tcp_keepalive_probes (pqcomm.c:1834-1835). Above 0 the backend sets TCP_KEEPCNT\",\n },\n tcp_user_timeout: {\n key: \"postgresql tcp_user_timeout\",\n scope: \"session\",\n unit: \"ms\",\n default: 0,\n note: \"guc_tables.c:3587-3596. At 0 the backend makes no call, and the socket keeps its own value (pqcomm.c:1909-1910). Above 0 it sets TCP_USER_TIMEOUT\",\n },\n statement_timeout: { key: \"postgresql statement_timeout\", scope: \"session\", unit: \"ms\", default: 0, off: 0, note: \"guc_tables.c:2611-2620. 0 is no timeout (postgres.c:5257-5258)\" },\n lock_timeout: { key: \"postgresql lock_timeout\", scope: \"session\", unit: \"ms\", default: 0, off: 0, note: \"guc_tables.c:2622-2631. 0 is no timeout (proc.c:1294)\" },\n transaction_timeout: { key: \"postgresql transaction_timeout\", scope: \"session\", unit: \"ms\", default: 0, off: 0, note: \"guc_tables.c:2644-2653, new in 17. 0 is no timeout (xact.c:2175)\" },\n idle_in_transaction_session_timeout: {\n key: \"postgresql idle_in_transaction_session_timeout\",\n scope: \"session\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"guc_tables.c:2633-2642. 0 is no timeout (postgres.c:4626)\",\n },\n idle_session_timeout: { key: \"postgresql idle_session_timeout\", scope: \"session\", unit: \"ms\", default: 0, off: 0, note: \"guc_tables.c:2655-2664. 0 is no timeout (postgres.c:4693)\" },\n client_connection_check_interval: {\n key: \"postgresql client_connection_check_interval\",\n scope: \"session\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"guc_tables.c:3632-3641. 0 is no check (postgres.c:2790, :3331)\",\n },\n authentication_timeout: {\n key: \"postgresql authentication_timeout\",\n scope: \"server\",\n unit: \"s\",\n default: 60,\n note: \"guc_tables.c:2774-2783: 1 s to 600 s, PGC_SIGHUP. It bounds the startup packet and then the authentication, each on its own (backend_startup.c:243-246)\",\n },\n hz: { key: \"CONFIG_HZ\", scope: \"global\", unit: \"Hz\", default: null, note: \"The build option of the kernel: the timer wheel rounds the keepalive of the socket\" },\n alarm_slack: {\n key: \"the lateness of a SIGALRM timeout of a backend\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document: the source gives no bound. setitimer(ITIMER_REAL) raises SIGALRM (timeout.c:338-339), and the backend acts at its next CHECK_FOR_INTERRUPTS. The handler sets the latch of the backend (timeout.c:364-377), thus a wait on the latch ends at once. pg_sleep waits on the latch, and it calls CHECK_FOR_INTERRUPTS before each wait (adt/misc.c:391-412)\",\n },\n },\n timers: {\n startup_packet: {\n duration: { knob: \"authentication_timeout\", unit: \"s\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"enter:STARTUP\"],\n cancels: [\"rx.startup\"],\n fires: \"timer.startup-packet\",\n note: \"backend_startup.c:252-253 and :314. Its handler calls _exit(1) from the SIGALRM handler (backend_startup.c:918-922, timeout.c:413-414)\",\n },\n authentication: {\n duration: { knob: \"authentication_timeout\", unit: \"s\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"enter:AUTHENTICATING\"],\n cancels: [\"local.authenticated\"],\n fires: \"timer.authentication\",\n note: \"postinit.c:240 and :251: the statement timer, which sends SIGTERM while ClientAuthInProgress (postinit.c:1386-1387)\",\n },\n statement_timeout: {\n duration: { knob: \"statement_timeout\", unit: \"ms\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"rx.message\"],\n cancels: [\"local.statement-done\", \"tx.error\"],\n fires: \"timer.statement\",\n note: \"postgres.c:2787 and :2802. A timer that is active keeps its deadline across Parse, Bind and Execute (postgres.c:2780-2786). No timer when statement_timeout >= transaction_timeout > 0 (postgres.c:5257-5267)\",\n },\n lock_timeout: {\n duration: { knob: \"lock_timeout\", unit: \"ms\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"local.lock-wait\"],\n cancels: [\"local.lock-granted\", \"tx.error\"],\n fires: \"timer.lock\",\n note: \"proc.c:1294-1304 and :1654-1662: each wait for a lock has its own timer\",\n },\n transaction_timeout: {\n duration: { knob: \"transaction_timeout\", unit: \"ms\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"local.transaction-start\"],\n cancels: [\"local.transaction-end\", \"tx.error\"],\n fires: \"timer.transaction\",\n note: \"xact.c:2174-2176 and :2768-2770. An ERROR in a transaction block aborts the transaction, and the block stays (xact.c:3472-3477). Thus an aborted block has no transaction timer\",\n },\n idle_in_transaction: {\n duration: { knob: \"idle_in_transaction_session_timeout\", unit: \"ms\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"enter:IDLE_IN_TRANSACTION\"],\n cancels: [\"rx.message\"],\n fires: \"timer.idle-in-transaction\",\n note: \"postgres.c:4626-4646 and :4729-4733. No timer when idle_in_transaction_session_timeout >= transaction_timeout > 0. A timeout at the arrival of the message still ends the session (postgres.c:4721-4749)\",\n },\n idle_session: {\n duration: { knob: \"idle_session_timeout\", unit: \"ms\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"enter:IDLE\"],\n cancels: [\"rx.message\"],\n fires: \"timer.idle-session\",\n note: \"postgres.c:4693-4698 and :4734-4738\",\n },\n client_check: {\n duration: { knob: \"client_connection_check_interval\", unit: \"ms\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"rx.message\", \"timer.client-check\"],\n cancels: [\"tx.error\"],\n fires: \"timer.client-check\",\n note: \"postgres.c:2790-2795: a command arms it when it is not active. A check that passes arms it again. When it fires in the wait for a command, it does nothing and does not arm again (postgres.c:3331-3338)\",\n },\n },\n realizes: {\n \"systems.mechanism.idle-refresh-interval\": {\n duration: { knob: \"tcp_keepalive_time\", unit: \"s\" },\n lateness: { model: \"linux.wheel\", knobs: [\"tcp_keepalive_time\", \"hz\"], unit: \"s\" },\n early: { model: \"linux.jiffy\", knobs: [\"hz\"], unit: \"s\" },\n note: \"The first probe of an idle connection. At tcp_keepalives_idle 0 the backend keeps the idle time of the namespace\",\n },\n \"systems.mechanism.keepalive-detection-window\": { timer: \"keepalive\" },\n },\n transitions: [\n { id: \"pg.accept\", from: \"ABSENT\", to: \"STARTUP\", on: \"accept\", source: \"backend_startup.c:157-161, pqcomm.c:195-274\" },\n { id: \"pg.startup\", from: \"STARTUP\", to: \"AUTHENTICATING\", on: \"rx.startup\", source: \"backend_startup.c:255-314\" },\n {\n id: \"pg.startup-timed-out\",\n from: \"STARTUP\",\n to: \"GONE\",\n on: \"timer.startup-packet\",\n timer: \"startup_packet\",\n note: \"The backend calls _exit(1). It writes no log and sends no message\",\n source: \"backend_startup.c:895-922\",\n },\n {\n id: \"pg.startup-ended\",\n from: \"STARTUP\",\n to: \"GONE\",\n on: [\"peer.fin\", \"peer.rst\", \"socket.error\"],\n note: \"When no byte arrives, the backend writes no log. A part of a packet logs COMMERROR 08P01 \\\"incomplete startup packet\\\". Then proc_exit(0)\",\n source: \"backend_startup.c:460-519, :328-333\",\n },\n {\n id: \"pg.authenticated\",\n from: \"AUTHENTICATING\",\n to: \"IDLE\",\n on: \"local.authenticated\",\n note: \"The GUCs of the startup packet apply here (postinit.c:1210-1215). Thus a keepalive GUC of the client reaches the socket only after the authentication\",\n source: \"postinit.c:246-251, postgres.c:4618-4706\",\n },\n {\n id: \"pg.auth-timed-out\",\n from: \"AUTHENTICATING\",\n to: \"GONE\",\n on: \"timer.authentication\",\n timer: \"authentication\",\n errno: \"57014\",\n note: \"SIGTERM, then FATAL \\\"canceling authentication due to timeout\\\". The backend does not send it to the client\",\n source: \"postinit.c:1374-1394, postgres.c:3279-3290\",\n },\n {\n id: \"pg.auth-ended\",\n from: \"AUTHENTICATING\",\n to: \"GONE\",\n on: [\"peer.fin\", \"peer.rst\", \"socket.error\"],\n note: \"An EOF in the password exchange ends the backend with proc_exit(0). It writes no log for the EOF\",\n source: \"auth.c:260-271, :714-744\",\n },\n {\n id: \"pg.command\",\n from: [\"IDLE\", \"IDLE_IN_TRANSACTION\"],\n to: \"RUNNING\",\n on: \"rx.message\",\n note: \"The backend disarms the idle timers. Then it arms statement_timeout and the client check\",\n source: \"postgres.c:4719-4738, :2770-2796\",\n },\n { id: \"pg.ready\", from: \"RUNNING\", to: \"IDLE\", on: \"tx.ready-for-query\", guard: \"no transaction block\", source: \"postgres.c:4648-4704\" },\n {\n id: \"pg.ready-in-transaction\",\n from: \"RUNNING\",\n to: \"IDLE_IN_TRANSACTION\",\n on: \"tx.ready-for-query\",\n guard: \"a transaction block, open or aborted\",\n source: \"postgres.c:4620-4647\",\n },\n {\n id: \"pg.statement-timed-out\",\n from: \"RUNNING\",\n to: \"RUNNING\",\n on: \"timer.statement\",\n timer: \"statement_timeout\",\n errno: \"57014\",\n emits: [\"tx.error\"],\n note: \"ERROR \\\"canceling statement due to statement timeout\\\". The session stays\",\n source: \"postgres.c:3403-3409, :4446-4502\",\n },\n {\n id: \"pg.lock-timed-out\",\n from: \"RUNNING\",\n to: \"RUNNING\",\n on: \"timer.lock\",\n timer: \"lock_timeout\",\n errno: \"55P03\",\n emits: [\"tx.error\"],\n note: \"ERROR \\\"canceling statement due to lock timeout\\\". The session stays\",\n source: \"postgres.c:3396-3402\",\n },\n {\n id: \"pg.transaction-timed-out\",\n from: [\"RUNNING\", \"IDLE_IN_TRANSACTION\"],\n to: \"GONE\",\n on: \"timer.transaction\",\n timer: \"transaction_timeout\",\n guard: \"from IDLE_IN_TRANSACTION, the block is open: an aborted block has no transaction timer\",\n errno: \"25P04\",\n note: \"FATAL \\\"terminating connection due to transaction timeout\\\". The backend sends it to the client, then exits\",\n source: \"postgres.c:3453-3464, elog.c:1726-1732, :3643-3651\",\n },\n {\n id: \"pg.idle-in-transaction-timed-out\",\n from: \"IDLE_IN_TRANSACTION\",\n to: \"GONE\",\n on: \"timer.idle-in-transaction\",\n timer: \"idle_in_transaction\",\n errno: \"25P03\",\n note: \"FATAL \\\"terminating connection due to idle-in-transaction timeout\\\". The backend sends it to the client, then exits\",\n source: \"postgres.c:3435-3451\",\n },\n {\n id: \"pg.idle-timed-out\",\n from: \"IDLE\",\n to: \"GONE\",\n on: \"timer.idle-session\",\n timer: \"idle_session\",\n errno: \"57P05\",\n note: \"FATAL \\\"terminating connection due to idle-session timeout\\\". The backend sends it to the client, then exits\",\n source: \"postgres.c:3466-3477\",\n },\n {\n id: \"pg.client-check\",\n from: \"RUNNING\",\n to: \"RUNNING\",\n on: \"timer.client-check\",\n timer: \"client_check\",\n guard: \"the poll reports no close\",\n source: \"postgres.c:3321-3339\",\n },\n {\n id: \"pg.client-gone\",\n from: \"RUNNING\",\n to: \"GONE\",\n on: \"timer.client-check\",\n timer: \"client_check\",\n guard: \"the poll reports WL_SOCKET_CLOSED: EPOLLRDHUP, EPOLLERR or EPOLLHUP\",\n errno: \"08006\",\n note: \"FATAL \\\"connection to client lost\\\". The backend does not send it\",\n source: \"postgres.c:3333-3350, pqcomm.c:2053-2084, latch.c:1675-1680\",\n },\n { id: \"pg.send-blocked\", from: \"RUNNING\", to: \"SENDING\", on: \"local.send-blocked\", source: \"pqcomm.c:1275-1300, be-secure.c:331-340\" },\n { id: \"pg.send-resumed\", from: \"SENDING\", to: \"RUNNING\", on: \"local.writable\", source: \"be-secure.c:331-361\" },\n {\n id: \"pg.send-failed\",\n from: [\"RUNNING\", \"SENDING\"],\n to: \"GONE\",\n on: \"socket.error\",\n errno: \"08006\",\n note: \"COMMERROR \\\"could not send data to client: %m\\\" and ClientConnectionLost. At the next CHECK_FOR_INTERRUPTS: FATAL \\\"connection to client lost\\\", not sent. SIGPIPE has no effect (postgres.c:4310-4316)\",\n source: \"pqcomm.c:1396-1413, postgres.c:3341-3350\",\n },\n {\n id: \"pg.client-eof\",\n from: [\"IDLE\", \"IDLE_IN_TRANSACTION\"],\n to: \"GONE\",\n on: [\"peer.fin\", \"peer.rst\", \"socket.error\"],\n note: \"The read gives EOF, and the backend calls proc_exit(0), which aborts the transaction. A read error first logs COMMERROR \\\"could not receive data from client: %m\\\". In an open transaction the backend logs COMMERROR 08006 \\\"unexpected EOF on client connection with an open transaction\\\". Else, and in an aborted block, it logs DEBUG1 08003, which the default log level hides\",\n source: \"pqcomm.c:896-956, postgres.c:364-396, :4988-5016, postinit.c:1360-1371, xact.c:383-396, elog.c:205-228\",\n },\n { id: \"pg.terminate\", from: [\"IDLE\", \"IDLE_IN_TRANSACTION\"], to: \"GONE\", on: \"rx.terminate\", source: \"postgres.c:4988-5016\" },\n {\n id: \"pg.die\",\n from: [\"IDLE\", \"IDLE_IN_TRANSACTION\", \"RUNNING\", \"SENDING\"],\n to: \"GONE\",\n on: \"local.die\",\n errno: \"57P01\",\n note: \"FATAL \\\"terminating connection due to administrator command\\\". From SENDING the backend does not send it (postgres.c:589-590)\",\n source: \"postgres.c:2999-3023, :559-600, :3315-3318\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: {\n STARTUP: \"ESTABLISHED\",\n AUTHENTICATING: \"ESTABLISHED\",\n IDLE: \"ESTABLISHED\",\n IDLE_IN_TRANSACTION: \"ESTABLISHED\",\n RUNNING: \"ESTABLISHED\",\n SENDING: \"ESTABLISHED\",\n },\n sets: {\n keepidle: { knob: \"tcp_keepalive_time\", unit: \"s\" },\n keepintvl: { knob: \"tcp_keepalive_intvl\", unit: \"s\" },\n keepcnt: { knob: \"tcp_keepalive_probes\", unit: \"count\" },\n tcp_user_timeout: { knob: \"tcp_user_timeout\", unit: \"ms\" },\n },\n ends: \"socket.error\",\n note: \"These sets hold at the GUC defaults: the backend turns on SO_KEEPALIVE and keeps each keepalive option of the namespace. A keepalive GUC above 0 replaces its sysctl here. In SENDING no timer of PostgreSQL acts. Thus the timers of the machine below end a send to a lost client, or SIGTERM does\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the Elixir source of Supavisor at the tag v2.9.13 of\n// github.com/supabase/supavisor. Each line number is a line of that file at the tag. A fact of the\n// kernel or of the BEAM is an assumption of this document, and its note says so.\nexport const SV = \"v2.9.13\";\n\n/**\n * This document is Supavisor 2.9.13 in transaction mode, for one client connection. It gives the\n * states of the client handler (a gen_statem) from the accept to the close, and the timers that act\n * on it.\n *\n * Between two transactions the client holds no server connection. A message of the client checks one\n * out of the pool of the tenant, and ReadyForQuery of the server checks it in. Thus a fault of the\n * server reaches an idle client only through the pool. Its next query meets the pool, or the pool\n * shuts down and closes it, as after 57P03 at a login of the pool.\n *\n * At the defaults the handler writes a heartbeat to an idle client each 60 s: a ParameterStatus of\n * application_name. A failed write ends the client. client_idle_timeout does not end a session in\n * 2.9.13: its timer fires an event that no clause handles. Each client socket has SO_KEEPALIVE.\n */\nexport const SUPAVISOR_CLIENT: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"supavisor-client\",\n title: \"Supavisor 2.9.13 in transaction mode: one client connection, its checkout of a server and its heartbeat\",\n layer: \"proxy\",\n version: \"2.9.13\",\n conditions: {\n supavisor: \"2.9.13\",\n mode: \"transaction, the mode of the user of the tenant\",\n client: \"a PostgreSQL client over TCP, with no TLS, as the user <db_user>.<tenant>\",\n tenant: \"one tenant with one user and one server, client_heartbeat_interval 60 s and client_idle_timeout 0 at the defaults\",\n },\n sources: [\n { ref: `${SV} lib/supavisor/tenants/tenant.ex:28-32 the defaults of a tenant: default_pool_size 15, default_max_clients 1000, client_idle_timeout 0, client_heartbeat_interval 60 s`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/tenants/user.ex:16-19 a user: mode_type transaction or session, pool_size, pool_checkout_timeout 60_000 ms, max_clients`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/application.ex:71-83 each listener is ranch_tcp with keepalive true: each client socket has SO_KEEPALIVE`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:21-23, :123, :198 a state_timeout of 5_000 ms in :handshake, and 2_500 ms for a TLS handshake`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:315, :600, :627 an event timeout of 15_000 ms on each wait of the authentication`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:901-911 handle_actions arms the event timeout of client_idle_timeout, then the event timeout of the heartbeat. A gen_statem has one event timeout: the second action replaces the first`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:430-433, :734-744 the timer of client_idle_timeout fires :idle_timeout, but the clause matches :idle_terminate. The catch-all clause logs 'Undefined msg' and keeps the state`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:435-445, :1006 the heartbeat writes the ParameterStatus application_name each client_heartbeat_interval, and a failed write ends the client`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:705-716, :836-870, :966-971 a message in :idle checks out a server: poolboy with pool_checkout_timeout, then DbHandler.checkout with its call timeout of 15 s (lib/supavisor/db_handler.ex:101-110). A server connection that connects postpones the call (db_handler.ex:500-516)`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/errors/checkout_timeout_error.ex and lib/supavisor/error.ex:83-84 a checkout timeout reaches the client as FATAL XX000 'unable to check out connection from the pool after <ms>ms in Transaction mode'`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:523-537, :872-876 ReadyForQuery of the server: the client checks the server in and goes to :idle, and handle_actions arms the heartbeat`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:697-703 a Sync of the client in :busy goes to the server, and handle_actions arms the heartbeat in :busy too`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:90, :485-497 and lib/supavisor/errors/db_handler_exited_error.ex:15-25 the handler traps exits. The exit of its server connection ends the client: after a fatal error of the server that the client got, or with no ErrorResponse for the close of the server (db_termination)`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:556-566, :1016-1022 a close or an error of the client socket ends the client`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:545-556 and lib/supavisor/protocol/server.ex:183-190 the graceful shutdown of the pool: a client outside a transaction gets FATAL 57P01 'terminating connection due to administrator command' and its close, and a client in a transaction waits for its end (postpone)`, rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"Before ranch accepts the connection\" },\n handshake: { note: \"The startup packet, with a state timeout of 5 s\" },\n auth: { note: \"The authentication of the client by the password of its user, with a timeout of 15 s on each wait\" },\n idle: { note: \"Between two transactions: no server connection. The heartbeat runs\" },\n checkout: { note: \"A message of the client waits for a server connection of the pool. The handler does nothing else in this wait\" },\n busy: { note: \"A transaction: the client holds a server connection, and the server connection sends the replies to the client\" },\n ended: { final: true, note: \"The handler closed the client, with an ErrorResponse when it has one\" },\n },\n events: {\n \"local.accept\": { kind: \"local\", note: \"ranch accepts the TCP connection\" },\n \"rx.startup\": { kind: \"rx\", note: \"The startup packet of the client\" },\n \"local.authenticated\": { kind: \"local\", note: \"The password of the client matches, and the pool of the tenant serves\" },\n \"rx.query\": { kind: \"rx\", note: \"A message of the client between two transactions\" },\n \"local.checked-out\": { kind: \"local\", note: \"The pool gives a server connection, and it takes the client\" },\n \"server.ready\": { kind: \"local\", note: \"The server connection reads ReadyForQuery: the end of the transaction\" },\n \"server.exit\": { kind: \"peer\", note: \"The server connection of the client ends: the server closed it, reset it, or sent a fatal error\" },\n \"client.gone\": { kind: \"peer\", note: \"The client closes its connection, or a read or a write of its socket fails\" },\n \"pool.shutdown\": { kind: \"local\", note: \"The pool of the tenant shuts down gracefully, for example after 57P03 at a login of the pool\" },\n \"timer.handshake\": { kind: \"timer\", note: \"The state timeout of the handshake\" },\n \"timer.auth\": { kind: \"timer\", note: \"The timeout of a wait of the authentication\" },\n \"timer.heartbeat\": { kind: \"timer\", note: \"client_heartbeat_interval with no event of the handler\" },\n \"timer.checkout\": { kind: \"timer\", note: \"The pool gives no server connection in pool_checkout_timeout, or the server connection does not take the client in 15 s\" },\n \"tx.heartbeat\": { kind: \"tx\", note: \"The ParameterStatus application_name to the client\" },\n \"tx.error\": { kind: \"tx\", note: \"An ErrorResponse: FATAL with the SQLSTATE of the error, XX000 for an error of Supavisor\" },\n },\n knobs: {\n client_heartbeat_interval: { key: \"supavisor client_heartbeat_interval of the tenant\", scope: \"proxy\", unit: \"s\", default: 60, off: 0, note: \"lib/supavisor/tenants/tenant.ex:32\" },\n client_idle_timeout: {\n key: \"supavisor client_idle_timeout of the tenant\",\n scope: \"proxy\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"lib/supavisor/tenants/tenant.ex:31. It ends no session in 2.9.13, thus this document gives it no timer. Its event timeout is armed only when the heartbeat is off, and it fires :idle_timeout, which goes to the catch-all clause (lib/supavisor/client_handler.ex:430-433, :734-744, :901-911)\",\n },\n pool_checkout_timeout: { key: \"supavisor pool_checkout_timeout of the user\", scope: \"proxy\", unit: \"ms\", default: 60000, note: \"lib/supavisor/tenants/user.ex:18\" },\n handshake: { key: \"the state timeout of the handshake\", scope: \"process\", unit: \"ms\", default: 5000, note: \"lib/supavisor/client_handler.ex:23: a constant of the source\" },\n auth: { key: \"the timeout of a wait of the authentication\", scope: \"process\", unit: \"ms\", default: 15000, note: \"lib/supavisor/client_handler.ex:315: a constant of the source\" },\n checkout_call: { key: \"the call timeout of DbHandler.checkout\", scope: \"process\", unit: \"ms\", default: 15000, note: \"lib/supavisor/db_handler.ex:106: a constant of the source\" },\n slack: {\n key: \"the lateness of the scheduler of the BEAM for one timer of a gen_statem\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of Supavisor\",\n },\n },\n timers: {\n handshake_timeout: {\n duration: { knob: \"handshake\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:handshake\"],\n cancels: [\"rx.startup\"],\n fires: \"timer.handshake\",\n note: \"lib/supavisor/client_handler.ex:123, :198: a state timeout\",\n },\n auth_timeout: {\n duration: { knob: \"auth\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:auth\"],\n cancels: [\"local.authenticated\"],\n fires: \"timer.auth\",\n note: \"lib/supavisor/client_handler.ex:315, :600, :627\",\n },\n heartbeat: {\n duration: { knob: \"client_heartbeat_interval\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:idle\"],\n cancels: [\"rx.query\"],\n fires: \"timer.heartbeat\",\n backoff: { resets: [\"enter:idle\"] },\n note: \"lib/supavisor/client_handler.ex:435-445, :901-911: an event timeout, thus any event of the handler cancels it. Each heartbeat arms the next, the same each time. A Sync in a transaction arms it too\",\n },\n checkout_timeout: {\n duration: { knob: \"checkout_call\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:checkout\"],\n cancels: [\"local.checked-out\"],\n fires: \"timer.checkout\",\n note: \"lib/supavisor/client_handler.ex:848-851, lib/supavisor/db_handler.ex:101-110: poolboy gives a worker of the pool at once while the pool has one, and the call to that worker waits up to 15 s while it connects. With each worker checked out, poolboy waits up to pool_checkout_timeout\",\n },\n },\n transitions: [\n { id: \"scl.accept\", from: \"[none]\", to: \"handshake\", on: \"local.accept\", timer: \"handshake_timeout\", source: \"lib/supavisor/client_handler.ex:89-125\" },\n { id: \"scl.startup\", from: \"handshake\", to: \"auth\", on: \"rx.startup\", timer: \"auth_timeout\", source: \"lib/supavisor/client_handler.ex:211-315\" },\n { id: \"scl.handshake-timed-out\", from: \"handshake\", to: \"ended\", on: \"timer.handshake\", source: \"lib/supavisor/client_handler.ex:198-200\" },\n { id: \"scl.auth-timed-out\", from: \"auth\", to: \"ended\", on: \"timer.auth\", errno: \"XX000\", emits: [\"tx.error\"], source: \"lib/supavisor/client_handler.ex:627-635\" },\n { id: \"scl.authenticated\", from: \"auth\", to: \"idle\", on: \"local.authenticated\", timer: \"heartbeat\", source: \"lib/supavisor/client_handler.ex:340-410\" },\n { id: \"scl.heartbeat\", from: [\"idle\", \"busy\"], to: \"idle\", on: \"timer.heartbeat\", guard: \"the write of the heartbeat succeeds\", timer: \"heartbeat\", emits: [\"tx.heartbeat\"], source: \"lib/supavisor/client_handler.ex:435-440\" },\n { id: \"scl.query\", from: \"idle\", to: \"checkout\", on: \"rx.query\", timer: \"checkout_timeout\", source: \"lib/supavisor/client_handler.ex:705-716\" },\n { id: \"scl.checked-out\", from: \"checkout\", to: \"busy\", on: \"local.checked-out\", source: \"lib/supavisor/client_handler.ex:708-711, :851-856\" },\n {\n id: \"scl.checkout-timed-out\",\n from: \"checkout\",\n to: \"ended\",\n on: \"timer.checkout\",\n errno: \"XX000\",\n emits: [\"tx.error\"],\n note: \"FATAL 'unable to check out connection from the pool after <ms>ms in Transaction mode'\",\n source: \"lib/supavisor/client_handler.ex:712-714, :966-971, lib/supavisor/errors/checkout_timeout_error.ex\",\n },\n { id: \"scl.ready\", from: \"busy\", to: \"idle\", on: \"server.ready\", timer: \"heartbeat\", source: \"lib/supavisor/client_handler.ex:523-537\" },\n {\n id: \"scl.server-gone\",\n from: \"busy\",\n to: \"ended\",\n on: \"server.exit\",\n note: \"A fatal error of the server reaches the client first. A close or a reset of the server has no ErrorResponse: the client gets the close only\",\n source: \"lib/supavisor/client_handler.ex:485-497, lib/supavisor/errors/db_handler_exited_error.ex:15-25\",\n },\n { id: \"scl.gone\", from: [\"handshake\", \"auth\", \"idle\", \"checkout\", \"busy\"], to: \"ended\", on: \"client.gone\", source: \"lib/supavisor/client_handler.ex:556-566, :1016-1022\" },\n {\n id: \"scl.pool-shutdown\",\n from: \"idle\",\n to: \"ended\",\n on: \"pool.shutdown\",\n errno: \"57P01\",\n emits: [\"tx.error\"],\n note: \"FATAL 57P01 'terminating connection due to administrator command', then the close. A client in a transaction gets it at the end of the transaction\",\n source: \"lib/supavisor/client_handler.ex:545-556, lib/supavisor/protocol/server.ex:183-190\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { handshake: \"ESTABLISHED\", auth: \"ESTABLISHED\", idle: \"ESTABLISHED\", checkout: \"ESTABLISHED\", busy: \"ESTABLISHED\" },\n sets: {},\n ends: \"client.gone\",\n note: \"The socket of the client. ranch sets SO_KEEPALIVE and no other keepalive option, thus the three keepalive sysctls of the namespace apply\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { SV } from \"./supavisor-client.ts\";\n\n/**\n * This document is Supavisor 2.9.13 in transaction mode, for one server connection of the pool of a\n * tenant. It is one DbHandler, a gen_statem, from its start by the pool to its end.\n *\n * The connect to the server has a timeout of 5 s, and the authentication 15 s. A failed connect ends the\n * DbHandler with FATAL 08006 'Failed to connect to database'. A client that waits for this connection gets\n * that error at once. The pool then starts a new DbHandler, which waits the rest of 2.5 s from the last\n * failure before it connects.\n *\n * The DbHandler reads its socket in each state. Thus a close or a reset of the server ends it at once, idle\n * or with a client. A client that holds the connection then gets the close. The server socket has\n * TCP_NODELAY and no keepalive, and no timer of Supavisor bounds a query.\n */\nexport const SUPAVISOR_SERVER: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"supavisor-server\",\n title: \"Supavisor 2.9.13 in transaction mode: one server connection of the pool of a tenant\",\n layer: \"proxy\",\n version: \"2.9.13\",\n conditions: {\n supavisor: \"2.9.13\",\n mode: \"transaction, the mode of the user of the tenant\",\n server: \"one PostgreSQL server over TCP, with no TLS, at the address of the tenant\",\n },\n sources: [\n { ref: `${SV} lib/supavisor/tenant_supervisor.ex:72-80 the pool of a tenant: poolboy, worker DbHandler, size min_size, max_overflow pool_size, lifo, an overflow worker stops after 5 min idle`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:66, :205-224, :1111-1119 a new DbHandler waits the rest of 2.5 s from the last failed connect of its pool (connect_cooldown)`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:226-289 the connect: gen_tcp with nodelay and no keepalive, and a timeout of 5_000 ms (1_000 ms in proxy mode). Then the startup message, and a state timeout of 15_000 ms on the authentication`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:1072-1085, :292-321 a failed connect: the circuit breaker and the backoff of the pool record it, FATAL 08006 'Failed to connect to database', and the DbHandler goes to terminating_with_error, then stops`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:480-516 a checkout in :idle or :busy links the client and gives it the socket. In another state the call waits (postpone), and in terminating_with_error it gets the error`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:551-574 a close of the server socket: in the authentication a failed connect, else the DbHandler stops with db_termination`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:575-585 the exit of the client that holds the connection: Terminate to the server, close, stop`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/circuit_breaker.ex:28-35 100 failed connects of a tenant in 150 s block its new connections for 30 s`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:69-76, :362-372, :297-301 an ErrorResponse at the authentication: 57P03 (the server shuts down) shuts the pool down gracefully, 3D000, 42501 and 22023 shut it down, and 28P01 and 28000 keep it`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/manager.ex:107-118, lib/supavisor/client_handler.ex:545-556 the graceful shutdown of a pool: each client outside a transaction gets FATAL 57P01 'terminating connection due to administrator command' and its close. A client in a transaction gets it after the transaction`, rung: \"implemented\" },\n {\n ref: `${SV} run 39164922565 of mark1russell7/systems: the server stopped, and the next connect of the pool got 57P03 in 6 of 11 runs. Each idle client then got FATAL 57P01 and its close, 8 to 10 ms after the server closed its connections. In 5 runs the connect came after the server, and the pool stayed`,\n rung: \"observed\",\n },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"The pool starts a DbHandler\" },\n cooldown: { note: \"The pool had a failed connect in the last 2.5 s: the DbHandler waits for the rest\" },\n connecting: { note: \"The TCP connect, with its timeout of 5 s\" },\n authentication: { note: \"The startup message and the authentication, with a state timeout of 15 s\" },\n idle: { note: \"In the pool, ready for a client. The DbHandler reads the socket\" },\n busy: { note: \"Checked out by a client for a transaction: the DbHandler sends each message of the server to the client\" },\n ended: { final: true, note: \"The DbHandler stopped, and the pool starts a new one\" },\n },\n events: {\n \"local.start\": { kind: \"local\", note: \"The pool starts the DbHandler\" },\n \"socket.connect\": { kind: \"local\", note: \"The TCP connect ends\" },\n \"rx.ready-for-query\": { kind: \"rx\", note: \"ReadyForQuery of the server: the end of the authentication or of a transaction\" },\n \"local.checkout\": { kind: \"local\", note: \"A client checks the connection out of the pool\" },\n \"client.gone\": { kind: \"peer\", note: \"The client that holds the connection ends\" },\n \"peer.fin\": { kind: \"peer\", note: \"The server closes the connection\" },\n \"peer.rst\": { kind: \"peer\", note: \"A reset of the connection of the server\" },\n \"socket.error\": { kind: \"local\", note: \"The socket of the server fails with its own error\" },\n \"rx.shutting-down\": { kind: \"rx\", note: \"An ErrorResponse 57P03 at the authentication: the server shuts down\" },\n \"timer.cooldown\": { kind: \"timer\", note: \"The rest of 2.5 s from the last failed connect of the pool\" },\n \"timer.connect\": { kind: \"timer\", note: \"The timeout of gen_tcp.connect\" },\n \"timer.auth\": { kind: \"timer\", note: \"The state timeout of the authentication\" },\n \"tx.terminate\": { kind: \"tx\", note: \"The Terminate message, then the close of the socket\" },\n \"tx.error\": { kind: \"tx\", note: \"FATAL 08006 'Failed to connect to database' to the client that waits for the connection\" },\n \"tx.pool-shutdown\": { kind: \"local\", note: \"The graceful shutdown of the pool: FATAL 57P01 and the close of each client outside a transaction\" },\n },\n knobs: {\n cooldown: { key: \"the cooldown of the pool after a failed connect\", scope: \"process\", unit: \"ms\", default: 2500, note: \"lib/supavisor/db_handler.ex:66: a constant of the source\" },\n connect: { key: \"the timeout of the TCP connect to the server\", scope: \"process\", unit: \"ms\", default: 5000, note: \"lib/supavisor/db_handler.ex:240: a constant of the source, 1_000 ms in proxy mode\" },\n auth: { key: \"the state timeout of the authentication to the server\", scope: \"process\", unit: \"ms\", default: 15000, note: \"lib/supavisor/db_handler.ex:67: a constant of the source\" },\n keepalive_idle: {\n key: \"the keepalive idle time of the server socket of Supavisor\",\n scope: \"proxy\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"lib/supavisor/db_handler.ex:229-236: Supavisor sets no SO_KEEPALIVE on a server socket, thus no bound\",\n },\n slack: {\n key: \"the lateness of the scheduler of the BEAM for one timer of a gen_statem\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of Supavisor\",\n },\n },\n timers: {\n cooldown: {\n duration: { knob: \"cooldown\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:cooldown\"],\n fires: \"timer.cooldown\",\n note: \"lib/supavisor/db_handler.ex:205-224, :1111-1119: the rest of 2.5 s from the last failure, thus at most 2.5 s\",\n },\n connect_timeout: {\n duration: { knob: \"connect\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:connecting\"],\n cancels: [\"socket.connect\", \"socket.error\", \"peer.rst\"],\n fires: \"timer.connect\",\n note: \"lib/supavisor/db_handler.ex:240-248: the timeout of gen_tcp.connect. Its end closes the socket in SYN_SENT\",\n },\n authentication_timeout: {\n duration: { knob: \"auth\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:authentication\"],\n cancels: [\"rx.ready-for-query\", \"peer.fin\", \"peer.rst\", \"socket.error\"],\n fires: \"timer.auth\",\n note: \"lib/supavisor/db_handler.ex:272, :329-331\",\n },\n },\n transitions: [\n { id: \"ssv.start\", from: \"[none]\", to: \"connecting\", on: \"local.start\", guard: \"no failed connect of the pool in the last 2.5 s\", timer: \"connect_timeout\", source: \"lib/supavisor/db_handler.ex:205-228\" },\n { id: \"ssv.start-late\", from: \"[none]\", to: \"cooldown\", on: \"local.start\", guard: \"a failed connect of the pool in the last 2.5 s\", timer: \"cooldown\", source: \"lib/supavisor/db_handler.ex:205-211\" },\n { id: \"ssv.cooldown-over\", from: \"cooldown\", to: \"connecting\", on: \"timer.cooldown\", timer: \"connect_timeout\", source: \"lib/supavisor/db_handler.ex:222-224\" },\n { id: \"ssv.connected\", from: \"connecting\", to: \"authentication\", on: \"socket.connect\", timer: \"authentication_timeout\", source: \"lib/supavisor/db_handler.ex:248-273\" },\n {\n id: \"ssv.connect-failed\",\n from: [\"connecting\", \"authentication\"],\n to: \"ended\",\n on: [\"timer.connect\", \"socket.error\", \"peer.rst\", \"peer.fin\", \"timer.auth\"],\n errno: \"08006\",\n emits: [\"tx.error\"],\n note: \"FATAL 'Failed to connect to database: <reason>' to a client that waits for the connection, then the DbHandler stops\",\n source: \"lib/supavisor/db_handler.ex:282-289, :329-331, :551-555, :1072-1085, :292-321\",\n },\n { id: \"ssv.authenticated\", from: \"authentication\", to: \"idle\", on: \"rx.ready-for-query\", source: \"lib/supavisor/db_handler.ex:380-390\" },\n {\n id: \"ssv.server-shutting-down\",\n from: \"authentication\",\n to: \"ended\",\n on: \"rx.shutting-down\",\n emits: [\"tx.pool-shutdown\"],\n note: \"57P03 at the login: Supavisor shuts the whole pool down gracefully, thus a server that shuts down can end each idle client of the tenant\",\n source: \"lib/supavisor/db_handler.ex:69-76, :362-372, :297-301\",\n },\n { id: \"ssv.checkout\", from: \"idle\", to: \"busy\", on: \"local.checkout\", source: \"lib/supavisor/db_handler.ex:500-512\" },\n { id: \"ssv.release\", from: \"busy\", to: \"idle\", on: \"rx.ready-for-query\", source: \"lib/supavisor/db_handler.ex:415-425\" },\n {\n id: \"ssv.closed\",\n from: [\"idle\", \"busy\"],\n to: \"ended\",\n on: [\"peer.fin\", \"peer.rst\", \"socket.error\"],\n note: \"db_termination: a client that holds the connection gets the close, with no ErrorResponse\",\n source: \"lib/supavisor/db_handler.ex:557-574\",\n },\n { id: \"ssv.client-gone\", from: \"busy\", to: \"ended\", on: \"client.gone\", emits: [\"tx.terminate\"], source: \"lib/supavisor/db_handler.ex:575-585\" },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { connecting: \"SYN_SENT\", authentication: \"ESTABLISHED\", idle: \"ESTABLISHED\", busy: \"ESTABLISHED\" },\n sets: { keepidle: { knob: \"keepalive_idle\", unit: \"s\" } },\n ends: \"socket.error\",\n note: \"The server socket, with TCP_NODELAY and no SO_KEEPALIVE. The DbHandler reads it in each state, thus the end of the socket reaches it at once\",\n },\n});\n","import type { Expr, Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { NODE_TIMER_EARLY, nodeTimerLateness } from \"./http/timers.ts\";\n\n/**\n * This module holds the machine documents of the WebSocket transport of `@procedures/client`\n * 0.3.0, the release on npm. Each fact comes from the files of that release, from\n * `@mark1russell7/service` 0.4.0, or from Node v24.21.0 and its undici 7.29.1. The comments and the\n * sources give the file and the line.\n *\n * The client repository has a document of the connection at commit 1f50f47:\n * `WEBSOCKET_CONNECTION_MACHINE` in `packages/client/src/machines.ts`. This document takes its\n * states and its events, and the code of 0.3.0 gives the timers.\n */\n\n/** This function gives the arithmetic of a duration in ms. */\nconst arithmetic = (duration: Expr): string => {\n if (!(\"expr\" in duration) || duration.unit !== \"ms\") throw new Error(\"not arithmetic in ms\");\n return duration.expr;\n};\n\n/** This text is the backoff of try n + 1 of the reconnect, in ms: `fired` is n. It reads the arithmetic of `backoffDelay`. */\nconst RECONNECT_WAIT = \"min(reconnect_initial_delay * pow(reconnect_backoff_multiplier, fired), reconnect_max_delay)\";\n\n/** This text is the late bound of one Node timer, in ms, for a time in ms. */\nconst late = (ms: string): string => arithmetic(nodeTimerLateness(ms));\n/** This text is the early bound of one Node timer, in ms. */\nconst EARLY = arithmetic(NODE_TIMER_EARLY);\n\n/**\n * This document is the connection of the WebSocket client of `@procedures/client` 0.3.0\n * (`WebSocketTransport`), over its socket class and its Linux TCP socket.\n *\n * - The heartbeat is `heartbeat()` of `@mark1russell7/service` 0.4.0. A tick each interval sends a\n * ping only when no pong is awaited. The timeout of the ping starts before its send. A\n * ping without a pong at its timeout is a miss, and `misses` misses in sequence drop the\n * connection. With a timeout below the interval, each tick after a miss sends the next ping.\n * Thus the drop comes (misses − 1) intervals and one timeout after the first ping without an answer.\n * - A drop ends the socket with `terminate()` when its class has it: the `ws` package. The global\n * `WebSocket` of Node has only `close()`, which writes a close frame and destroys nothing.\n * - Each end of a socket starts the reconnect. The wait of try n is the backoff\n * min(initialDelay × multiplier^(n − 1), maxDelay), less a random part: jitter × backoff × r.\n * - The handshake has a time limit (`connectionTimeout`), and a failed handshake drops at once.\n * - The heartbeat refreshes an idle flow. Each tick writes a ping, whatever data the connection\n * carries, and the pong comes back. Thus the ping timer realizes the idle refresh of O03.\n */\nexport const PROCEDURES_WS_CLIENT: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"procedures-ws-client\",\n title: \"The connection of the WebSocket client of @procedures/client 0.3.0\",\n layer: \"driver\",\n version: \"0.3.0\",\n conditions: { \"@procedures/client\": \"0.3.0\", \"@mark1russell7/service\": \"0.4.0\", node: \"24.21.0\", undici: \"7.29.1\", ws: \"8.22.0\", kernel: \"Linux 6.6\" },\n sources: [\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/client/transport.js:161-193 (the options: each time a duration; the misses of the heartbeat, the jitter of the reconnect, the class of the sockets)\",\n rung: \"implemented\",\n },\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/client/transport.js:379-399 startHeartbeat: heartbeat() of @mark1russell7/service with the interval, the timeout and the misses; a tick sends a ping only when CONNECTED\",\n rung: \"implemented\",\n },\n {\n ref: \"@mark1russell7/service 0.4.0 src/heartbeat.ts:129-135 (each tick starts the next one first), :96-125 (the timeout starts before the send of the ping; a send that throws is a miss), :81-94 (misses in sequence)\",\n rung: \"implemented\",\n },\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/client/transport.js:302-325 dropConnection: the handlers go, terminate() when the class has it, else close(), and handleClose at once\",\n rung: \"implemented\",\n },\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/client/transport.js:120-127 and :357-377: reconnectDelay is backoffDelay of @mark1russell7/service, with a subtracted jitter; an open sets the attempts to 0\",\n rung: \"implemented\",\n },\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/client/transport.js:221-236 and :283-289: the time limit of the handshake, and a failed handshake drops at once\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 deps/undici/src/lib/web/websocket/connection.js:227-296 closeWebSocketConnection: close() on an open socket writes a close frame and destroys nothing\",\n rung: \"implemented\",\n },\n {\n ref: \"ws 8.22.0 lib/websocket.js:505-517 terminate(): the socket is destroyed at once\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 deps/undici/src/lib/core/connect.js:120-129 setKeepAlive(true, 60000); deps/uv/src/unix/tcp.c:591-593 uv_tcp_keepalive: 1 s and 10 probes. The ws package sets no keepalive on its socket.\",\n rung: \"implemented\",\n },\n {\n ref: \"client main 1f50f47 packages/client/src/machines.ts WEBSOCKET_CONNECTION_MACHINE: the states and the events of this document\",\n rung: \"documented\",\n },\n ],\n states: {\n DISCONNECTED: { initial: true, note: \"no socket\" },\n CONNECTING: { note: \"the handshake, with its time limit\" },\n CONNECTED: { note: \"the calls; no pong is awaited\" },\n AWAITING_PONG: { note: \"a ping went out and its timeout runs: a tick of the interval sends nothing\" },\n RECONNECTING: { note: \"the wait before the next try\" },\n DISCONNECTING: { note: \"close() of the application ends the socket and the calls\" },\n },\n events: {\n connect: { kind: \"app\", note: \"the transport starts\" },\n open: { kind: \"rx\", note: \"the handshake ends: the attempts go back to 0\" },\n \"handshake-timeout\": { kind: \"timer\" },\n \"ping-due\": { kind: \"timer\", note: \"a tick of the interval\" },\n pong: { kind: \"rx\" },\n \"pong-timeout\": { kind: \"timer\", note: \"the last miss of `misses` in sequence\" },\n drop: { kind: \"local\", note: \"the close event of the socket: a FIN, a reset, a give-up of the kernel, or a failed handshake\" },\n \"reconnect-due\": { kind: \"timer\" },\n \"give-up\": { kind: \"local\", note: \"an end without reconnect, or without tries left\" },\n \"tx.request\": { kind: \"tx\", note: \"the transport writes a call\" },\n \"rx.reply\": { kind: \"rx\", note: \"the first frame of the reply to a call\" },\n \"request-timeout\": { kind: \"timer\" },\n close: { kind: \"app\", note: \"close() of the application\" },\n closed: { kind: \"local\" },\n },\n knobs: {\n heartbeat_interval: { key: \"heartbeat.interval\", scope: \"client\", unit: \"ms\", default: 20000 },\n heartbeat_timeout: { key: \"heartbeat.timeout\", scope: \"client\", unit: \"ms\", default: 5000 },\n heartbeat_misses: { key: \"heartbeat.misses\", scope: \"client\", unit: \"count\", default: 1 },\n reconnect_initial_delay: { key: \"reconnect.initialDelay\", scope: \"client\", unit: \"ms\", default: 1000 },\n reconnect_backoff_multiplier: { key: \"reconnect.backoffMultiplier\", scope: \"client\", unit: \"count\", default: 1.5 },\n reconnect_max_delay: { key: \"reconnect.maxDelay\", scope: \"client\", unit: \"ms\", default: 30000 },\n reconnect_max_attempts: { key: \"reconnect.maxAttempts\", scope: \"client\", unit: \"count\", default: null, note: \"Infinity at the default\" },\n reconnect_jitter: {\n key: \"reconnect.jitter\",\n scope: \"client\",\n unit: \"count\",\n default: 1,\n note: \"the random part of each wait, from 0 to 1: a wait is the backoff less jitter × backoff × r\",\n },\n request_timeout: { key: \"requestTimeout\", scope: \"client\", unit: \"ms\", default: 30000 },\n connection_timeout: { key: \"connectionTimeout\", scope: \"client\", unit: \"ms\", default: 10000, note: \"the time limit of the handshake, and the wait of a call for a connection\" },\n socket_keepidle: {\n key: \"the keepalive of the socket class\",\n scope: \"client\",\n unit: \"s\",\n default: 60,\n note: \"undici sets 60 s on the socket of the global WebSocket. The ws package sets none: a reader gives no bound\",\n },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"the HZ of the kernel, for the step of the coarse loop clock of libuv (http/timers.ts)\",\n },\n },\n timers: {\n ping: {\n duration: { knob: \"heartbeat_interval\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"heartbeat_interval\"),\n early: NODE_TIMER_EARLY,\n arms: [\"enter:CONNECTED\"],\n cancels: [\"drop\", \"close\"],\n fires: \"ping-due\",\n backoff: { resets: [\"open\"] },\n note: \"each tick starts the next one first, from the loop clock of that tick: a late tick moves each later tick. The data of the connection does not move a tick (service src/heartbeat.ts:129-135), thus an idle flow gets a ping and a pong each interval\",\n },\n pong: {\n duration: { expr: \"(heartbeat_misses - 1) * heartbeat_interval + heartbeat_timeout\", unit: \"ms\" },\n lateness: { expr: `(heartbeat_misses - 1) * (${late(\"heartbeat_interval\")}) + ${late(\"heartbeat_timeout\")}`, unit: \"ms\" },\n early: { expr: `heartbeat_misses * (${EARLY})`, unit: \"ms\" },\n arms: [\"enter:AWAITING_PONG\"],\n cancels: [\"pong\", \"drop\", \"close\"],\n fires: \"pong-timeout\",\n note: \"from the first ping without an answer: (misses − 1) ticks, then the timeout of the last ping. The timeout starts before the send of its ping\",\n },\n reconnect: {\n duration: { expr: RECONNECT_WAIT, unit: \"ms\" },\n lateness: nodeTimerLateness(RECONNECT_WAIT),\n early: { expr: `reconnect_jitter * ${RECONNECT_WAIT} + ${EARLY}`, unit: \"ms\" },\n arms: [\"enter:RECONNECTING\"],\n cancels: [\"close\"],\n fires: \"reconnect-due\",\n backoff: { resets: [\"open\"] },\n note: \"the jitter subtracts a random part of the backoff: its early bound\",\n },\n handshake: {\n duration: { knob: \"connection_timeout\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"connection_timeout\"),\n early: NODE_TIMER_EARLY,\n arms: [\"enter:CONNECTING\"],\n cancels: [\"open\", \"drop\", \"close\"],\n fires: \"handshake-timeout\",\n },\n request: {\n duration: { knob: \"request_timeout\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"request_timeout\"),\n early: NODE_TIMER_EARLY,\n arms: [\"tx.request\"],\n cancels: [\"rx.reply\", \"drop\", \"close\"],\n fires: \"request-timeout\",\n note: \"one timer for each call: it fails the call, and the connection stays\",\n },\n },\n realizes: {\n // each ping and its pong refresh the flow at a middlebox: O03 reads the interval at its latest\n \"systems.mechanism.idle-refresh-interval\": { timer: \"ping\" },\n },\n transitions: [\n { id: \"pw.connect\",from: \"DISCONNECTED\", on: \"connect\", to: \"CONNECTING\" },\n { id: \"pw.open\", from: \"CONNECTING\", on: \"open\", to: \"CONNECTED\", source: \"transport.js:237-262\" },\n {\n id: \"pw.handshake-timeout\",\n from: \"CONNECTING\",\n on: \"handshake-timeout\",\n to: \"RECONNECTING\",\n timer: \"handshake\",\n source: \"transport.js:229-236\",\n },\n {\n id: \"pw.ping\",\n from: \"CONNECTED\",\n on: \"ping-due\",\n to: \"AWAITING_PONG\",\n timer: \"ping\",\n emits: [\"tx.ping\"],\n source: \"transport.js:379-399\",\n },\n {\n id: \"pw.skip\",\n from: \"AWAITING_PONG\",\n on: \"ping-due\",\n to: \"AWAITING_PONG\",\n timer: \"ping\",\n note: \"one ping at a time: the tick sends nothing\",\n source: \"service src/heartbeat.ts:129-133\",\n },\n { id: \"pw.pong\", from: \"AWAITING_PONG\", on: \"pong\", to: \"CONNECTED\", source: \"transport.js:449-452\" },\n {\n id: \"pw.pong-timeout\",\n from: \"AWAITING_PONG\",\n on: \"pong-timeout\",\n to: \"RECONNECTING\",\n timer: \"pong\",\n emits: [\"tx.close-frame\"],\n note: \"dropConnection: terminate() destroys the socket of ws at once; close() of the global WebSocket writes a close frame, and its socket stays open below\",\n source: \"transport.js:302-325\",\n },\n {\n id: \"pw.drop\",\n from: [\"CONNECTING\", \"CONNECTED\", \"AWAITING_PONG\"],\n on: \"drop\",\n to: \"RECONNECTING\",\n guard: \"the reconnect is on, and tries are left\",\n source: \"transport.js:269-273, :336-355\",\n },\n {\n id: \"pw.give-up\",\n from: [\"CONNECTING\", \"CONNECTED\", \"AWAITING_PONG\"],\n on: \"give-up\",\n to: \"DISCONNECTED\",\n source: \"transport.js:341-343\",\n },\n {\n id: \"pw.reconnect\",\n from: \"RECONNECTING\",\n on: \"reconnect-due\",\n to: \"CONNECTING\",\n timer: \"reconnect\",\n source: \"transport.js:357-377\",\n },\n {\n id: \"pw.request-timeout\",\n from: \"CONNECTED\",\n on: \"request-timeout\",\n to: \"CONNECTED\",\n timer: \"request\",\n errno: \"TIMEOUT\",\n source: \"transport.js:598-607\",\n },\n {\n id: \"pw.request-timeout-pinged\",\n from: \"AWAITING_PONG\",\n on: \"request-timeout\",\n to: \"AWAITING_PONG\",\n timer: \"request\",\n errno: \"TIMEOUT\",\n source: \"transport.js:598-607\",\n },\n {\n id: \"pw.close\",\n from: [\"DISCONNECTED\", \"CONNECTING\", \"CONNECTED\", \"AWAITING_PONG\", \"RECONNECTING\"],\n on: \"close\",\n to: \"DISCONNECTING\",\n },\n { id: \"pw.closed\", from: \"DISCONNECTING\", on: \"closed\", to: \"DISCONNECTED\" },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { CONNECTING: \"SYN_SENT\", CONNECTED: \"ESTABLISHED\", AWAITING_PONG: \"ESTABLISHED\" },\n sets: {\n keepidle: { knob: \"socket_keepidle\", unit: \"s\" },\n keepintvl: { const: 1, unit: \"s\" },\n keepcnt: { const: 10, unit: \"count\" },\n },\n ends: \"drop\",\n note: \"The connector of undici turns keepalive on with a delay of 60 s, and libuv adds 1 s and 10 probes. The ws package turns no keepalive on. Thus the keepalive sysctls of the namespace do not reach the socket.\",\n },\n} satisfies Machine);\n\n/**\n * This document is one connection as the WebSocket server of `@procedures/client` 0.3.0 holds it\n * (`WebSocketServerTransport` on the `ws` package), over its Linux TCP socket.\n *\n * The heartbeat of the server (roadmap R3) is a `setInterval`. Each beat pings each connection,\n * and the server ends a connection after `misses` beats without a pong (`terminate()`). Thus the\n * drop comes `misses` beats after the first ping without an answer, and the lateness of each beat\n * adds. Its `http.Server` sets no SO_KEEPALIVE when `keepAlive` is off, the default of Node.\n */\nexport const PROCEDURES_WS_SERVER: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"procedures-ws-server\",\n title: \"One connection as the WebSocket server of @procedures/client 0.3.0 holds it\",\n layer: \"server\",\n version: \"0.3.0\",\n conditions: { \"@procedures/client\": \"0.3.0\", ws: \"8.22.0\", node: \"24.21.0\", kernel: \"Linux 6.6\" },\n sources: [\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/server/transport.js:81-87 (the heartbeat: interval and misses, or false), :93-111 beat(): terminate after misses, or count a miss and ping; :147-149 setInterval of the interval; :240 a pong sets the misses to 0\",\n rung: \"implemented\",\n },\n {\n ref: \"@procedures/client 0.3.0 dist/timers.js:29 webSocketServer: heartbeatIntervalMs 15000, heartbeatMisses 2\",\n rung: \"implemented\",\n },\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/server/transport.js:318-322: a ping of a client gets a pong\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_server.js:646-651 and lib/net.js:2753-2756: keepAlive of http.Server is off at the default, thus an accepted socket has no SO_KEEPALIVE\",\n rung: \"implemented\",\n },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n OPEN: { note: \"each beat pings the connection\" },\n MISSING: { note: \"a ping got no pong: each beat counts a miss\" },\n CLOSED: { final: true },\n },\n events: {\n accept: { kind: \"local\" },\n \"beat.unanswered\": { kind: \"timer\", note: \"a beat after a ping that got no pong\" },\n \"rx.pong\": { kind: \"rx\" },\n \"rx.ping\": { kind: \"rx\", note: \"a ping of the heartbeat of the client\" },\n \"misses-reached\": { kind: \"timer\" },\n close: { kind: \"peer\", note: \"the close event of the socket of ws\" },\n \"socket.error\": { kind: \"local\", note: \"the kernel beneath gave up on the socket, or a reset arrived\" },\n },\n knobs: {\n heartbeat_interval: { key: \"heartbeat.interval\", scope: \"server\", unit: \"ms\", default: 15000, note: \"no bound when the heartbeat is off\" },\n heartbeat_misses: { key: \"heartbeat.misses\", scope: \"server\", unit: \"count\", default: 2 },\n tcp_keepalive: {\n key: \"keepAlive of http.Server (server-ws --tcp-keepalive)\",\n scope: \"server\",\n unit: null,\n default: 0,\n note: \"off: a reader gives the keepalive of the kernel no bound\",\n },\n hz: { key: \"CONFIG_HZ\", scope: \"global\", unit: \"Hz\", default: null },\n },\n timers: {\n heartbeat: {\n duration: { expr: \"heartbeat_misses * heartbeat_interval\", unit: \"ms\" },\n lateness: { expr: `heartbeat_misses * (${late(\"heartbeat_interval\")})`, unit: \"ms\" },\n early: { expr: `heartbeat_misses * (${EARLY})`, unit: \"ms\" },\n arms: [\"enter:MISSING\"],\n cancels: [\"rx.pong\"],\n fires: \"misses-reached\",\n note: \"from the first ping without an answer: misses beats of the interval, then terminate()\",\n },\n },\n transitions: [\n { id: \"ps.accept\", from: \"ABSENT\", on: \"accept\", to: \"OPEN\" },\n { id: \"ps.miss\", from: \"OPEN\", on: \"beat.unanswered\", to: \"MISSING\" },\n { id: \"ps.pong\", from: \"MISSING\", on: \"rx.pong\", to: \"OPEN\" },\n { id: \"ps.ping\", from: [\"OPEN\", \"MISSING\"], on: \"rx.ping\", to: \"OPEN\", emits: [\"tx.pong\"], source: \"transport.js:318-322\" },\n { id: \"ps.terminate\", from: \"MISSING\", on: \"misses-reached\", to: \"CLOSED\", timer: \"heartbeat\", emits: [\"tx.fin\"], source: \"transport.js:97-101\" },\n { id: \"ps.close\", from: [\"OPEN\", \"MISSING\"], on: [\"close\", \"socket.error\"], to: \"CLOSED\" },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { OPEN: \"ESTABLISHED\", MISSING: \"ESTABLISHED\" },\n sets: {},\n ends: \"socket.error\",\n },\n} satisfies Machine);\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is src/sentinel.c of Valkey at the tag 9.1.2, unless a line names\n// src/server.c or src/server.h. Each line number is a line of that file at that tag.\nconst AT = \"valkey 9.1.2 src/sentinel.c\";\n\n/**\n * This document is the Sentinel of Valkey 9.1.2. It gives the view of one Sentinel on the primary\n * of a group that it monitors, and the failover that it can lead. The states are the down states\n * and the states of the failover. The timers are the periods and the timeouts of the Sentinel.\n * Each timer of a period checks at the next tick of the Sentinel, thus its lateness is one tick.\n */\nexport const SENTINEL: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"valkey-sentinel\",\n title: \"Valkey 9.1 Sentinel: one Sentinel's view of its primary, and the failover it leads\",\n layer: \"server\",\n version: \"9.1.2\",\n conditions: { valkey: \"9.1.2\", image: \"valkey/valkey:9.1 (Debian 13)\" },\n sources: [\n { ref: `${AT}:84-98 (the periods and timeouts of a Sentinel)`, rung: \"implemented\" },\n { ref: `${AT}:5465-5479 sentinelTimer, and src/server.c:1673 and :1724 (the tick at 1000 / hz ms, hz = 10 + rand() % 10)`, rung: \"implemented\" },\n { ref: `${AT}:3012-3071 sentinelSendPeriodicCommands (PING, INFO, hello)`, rung: \"implemented\" },\n { ref: `${AT}:4443-4540 the subjective and the objective down`, rung: \"implemented\" },\n { ref: `${AT}:4581-4760 the asks, the votes and the leader`, rung: \"implemented\" },\n { ref: `${AT}:4938-5357 the failover state machine`, rung: \"implemented\" },\n { ref: `${AT}:2440-2690 sentinelRefreshInstanceInfo (the promotion, the conversion of an old primary)`, rung: \"implemented\" },\n { ref: `${AT}:2772-2876 sentinelProcessHelloMessage (a newer configuration switches the other Sentinels)`, rung: \"implemented\" },\n { ref: \"measured by @mark1russell7/harness on 2026-10-16: one planned failover, its events 52-100 ms apart\", rung: \"observed\" },\n ],\n states: {\n up: { initial: true, note: \"the primary answers PING; no failover\" },\n sdown: { note: \"subjectively down: no PONG for down-after-milliseconds (sentinel.c:4482-4491)\" },\n odown: { note: \"objectively down: quorum Sentinels say it is down (sentinel.c:4508-4540)\" },\n \"wait-start\": { note: \"SENTINEL_FAILOVER_STATE_WAIT_START: the election (sentinel.c:5090-5119)\" },\n \"select-replica\": { note: \"SENTINEL_FAILOVER_STATE_SELECT_REPLICA (sentinel.c:5121-5137)\" },\n \"send-replicaof-noone\": { note: \"SENTINEL_FAILOVER_STATE_SEND_REPLICAOF_NOONE (sentinel.c:5171-5196)\" },\n \"wait-promotion\": { note: \"SENTINEL_FAILOVER_STATE_WAIT_PROMOTION: INFO of the replica tells its new role (sentinel.c:5198-5205)\" },\n \"reconf-replicas\": { note: \"SENTINEL_FAILOVER_STATE_RECONF_REPLICAS: the other replicas follow the new primary (sentinel.c:5269-5321)\" },\n \"update-config\": { note: \"SENTINEL_FAILOVER_STATE_UPDATE_CONFIG: +switch-master, then the new primary is the primary (sentinel.c:5324-5332)\" },\n },\n events: {\n \"timer.tick\": { kind: \"timer\", note: \"sentinelTimer, from serverCron (server.c:1673)\" },\n \"tx.ping\": { kind: \"tx\", note: \"a PING to the primary; act_ping_time is its time until a PONG (sentinel.c:2994-3008)\" },\n \"rx.pong\": { kind: \"rx\", note: \"a PONG; act_ping_time goes to 0 (sentinel.c:2731-2732)\" },\n \"timer.down-after\": { kind: \"timer\" },\n \"tx.ask\": { kind: \"tx\", note: \"SENTINEL is-master-down-by-addr to each other Sentinel (sentinel.c:4581-4624)\" },\n \"rx.down-reply\": { kind: \"rx\", note: \"another Sentinel says that the primary is down\" },\n \"local.quorum\": { kind: \"local\", note: \"quorum Sentinels say down, this one too (sentinel.c:4512-4524)\" },\n \"local.start\": { kind: \"local\", note: \"+try-failover: ODOWN, no failover in progress, none in 2 × failover-timeout (sentinel.c:4961-4985)\" },\n \"app.failover\": { kind: \"app\", note: \"SENTINEL FAILOVER <group>: no ODOWN, and no election (sentinel.c:3949-3962)\" },\n \"rx.votes\": { kind: \"rx\", note: \"a majority of the Sentinels and quorum votes for this one (sentinel.c:4744-4745)\" },\n \"timer.election\": { kind: \"timer\" },\n \"local.selected\": { kind: \"local\", note: \"+selected-slave: the best replica (sentinel.c:5047-5087)\" },\n \"local.no-replica\": { kind: \"local\" },\n \"tx.replicaof-noone\": { kind: \"tx\", note: \"MULTI, REPLICAOF NO ONE, CONFIG REWRITE, CLIENT KILL, EXEC (sentinel.c:4868-4936)\" },\n \"rx.info-master\": { kind: \"rx\", note: \"INFO of the promoted replica says role:master (sentinel.c:2610-2630)\" },\n \"timer.promotion\": { kind: \"timer\" },\n \"rx.info-reconfigured\": { kind: \"rx\", note: \"INFO of each other replica says that it follows the new primary, with its link up (sentinel.c:2664-2683)\" },\n \"timer.reconf\": { kind: \"timer\" },\n \"rx.hello-newer\": { kind: \"rx\", note: \"a hello with a newer configuration epoch (sentinel.c:2848-2862)\" },\n \"local.switch\": { kind: \"local\", note: \"+switch-master (sentinel.c:5324-5332, :2857)\" },\n \"tx.info\": { kind: \"tx\" },\n \"rx.info\": { kind: \"rx\" },\n \"tx.hello\": { kind: \"tx\", note: \"PUBLISH to __sentinel__:hello of each instance (sentinel.c:2917-2958)\" },\n \"timer.convert\": { kind: \"timer\" },\n \"tx.convert\": { kind: \"tx\", note: \"+convert-to-slave: REPLICAOF and CLIENT KILL to an old primary that came back (sentinel.c:2631-2643)\" },\n \"timer.retry\": { kind: \"timer\" },\n \"timer.low-activity\": { kind: \"timer\" },\n },\n knobs: {\n down_after: { key: \"sentinel down-after-milliseconds\", scope: \"group\", unit: \"ms\", default: 30000, note: \"sentinel.c:90\" },\n failover_timeout: { key: \"sentinel failover-timeout\", scope: \"group\", unit: \"ms\", default: 180000, note: \"sentinel.c:98\" },\n parallel_syncs: { key: \"sentinel parallel-syncs\", scope: \"group\", unit: \"count\", default: 1, note: \"sentinel.c:102\" },\n quorum: { key: \"sentinel monitor <quorum>\", scope: \"group\", unit: \"count\", default: null },\n config_hz: {\n key: \"CONFIG_DEFAULT_HZ\",\n scope: \"build\",\n unit: \"Hz\",\n default: 10,\n note: \"server.h:139. Sentinel sets hz to 10 + rand() % 10 after each tick (sentinel.c:5478), so a tick is 52 to 100 ms\",\n },\n ping_period: { key: \"SENTINEL DEBUG ping-period\", scope: \"process\", unit: \"ms\", default: 1000, note: \"sentinel.c:84, :87\" },\n info_period: { key: \"SENTINEL DEBUG info-period\", scope: \"process\", unit: \"ms\", default: 10000, note: \"sentinel.c:86\" },\n info_period_failover: {\n key: \"the INFO period of a replica of a primary in ODOWN or in a failover\",\n scope: \"build\",\n unit: \"ms\",\n default: 1000,\n note: \"sentinel.c:3037-3039\",\n },\n ask_period: { key: \"SENTINEL DEBUG ask-period\", scope: \"process\", unit: \"ms\", default: 1000, note: \"sentinel.c:88\" },\n publish_period: { key: \"SENTINEL DEBUG publish-period\", scope: \"process\", unit: \"ms\", default: 2000, note: \"sentinel.c:89\" },\n tilt_trigger: { key: \"SENTINEL DEBUG tilt-trigger\", scope: \"process\", unit: \"ms\", default: 2000, note: \"sentinel.c:91\" },\n tilt_period: { key: \"SENTINEL DEBUG tilt-period\", scope: \"process\", unit: \"ms\", default: 30000, note: \"sentinel.c:92\" },\n replica_reconf_timeout: { key: \"SENTINEL DEBUG slave-reconf-timeout\", scope: \"process\", unit: \"ms\", default: 10000, note: \"sentinel.c:93\" },\n min_link_reconnect_period: {\n key: \"SENTINEL DEBUG min-link-reconnect-period\",\n scope: \"process\",\n unit: \"ms\",\n default: 15000,\n note: \"sentinel.c:94\",\n },\n election_timeout: { key: \"SENTINEL DEBUG election-timeout\", scope: \"process\", unit: \"ms\", default: 10000, note: \"sentinel.c:95\" },\n max_desync: { key: \"SENTINEL_MAX_DESYNC\", scope: \"build\", unit: \"ms\", default: 1000, note: \"sentinel.c:105\" },\n },\n timers: {\n tick: {\n // serverCron returns 1000 / server.hz (server.c:1724), and Sentinel draws hz from 10 to 19 (sentinel.c:5478)\n duration: { expr: \"1000 / config_hz\", unit: \"ms\" },\n early: { expr: \"1000 / config_hz - floor(1000 / (2 * config_hz - 1))\", unit: \"ms\" },\n arms: [\"timer.tick\"],\n fires: \"timer.tick\",\n note: \"the period of sentinelTimer: each check below occurs at a tick, so its lateness is one tick\",\n },\n ping: {\n // ping_period = min(down_after, ping period), sent when the last PONG is older (sentinel.c:3047-3060)\n duration: { expr: \"min(down_after, ping_period)\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"rx.pong\"],\n fires: \"tx.ping\",\n },\n down_after: {\n // elapsed = now - act_ping_time > down_after_period, in whole ms (sentinel.c:4446-4447, :4482)\n duration: { knob: \"down_after\", unit: \"ms\" },\n lateness: { expr: \"1 + 1000 / config_hz\", unit: \"ms\" },\n arms: [\"tx.ping\"],\n cancels: [\"rx.pong\"],\n fires: \"timer.down-after\",\n note: \"it counts from the first PING without a PONG (act_ping_time). A link that closes keeps that time, and its next connect sends a PING at once (sentinel.c:2386-2387)\",\n },\n ask: {\n // asked again when the last reply is ask_period old, and a reply 5 × ask_period old is stale (sentinel.c:4598, :4610)\n duration: { knob: \"ask_period\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"rx.down-reply\"],\n fires: \"tx.ask\",\n },\n info: {\n duration: { knob: \"info_period\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"rx.info\"],\n fires: \"tx.info\",\n note: \"INFO to each primary and replica when the last reply is older (sentinel.c:3049-3053)\",\n },\n info_failover: {\n duration: { knob: \"info_period_failover\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"rx.info\"],\n fires: \"tx.info\",\n note: \"the INFO period of a replica while its primary is ODOWN or in a failover: the promotion is seen at the next INFO\",\n },\n hello: {\n duration: { knob: \"publish_period\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"tx.hello\"],\n fires: \"tx.hello\",\n note: \"a promotion forces the next hello at the next tick (sentinel.c:2630, :2980-2987)\",\n },\n election: {\n // the election timeout is min(SENTINEL_ELECTION_TIMEOUT, failover-timeout) (sentinel.c:5102-5110)\n duration: { expr: \"min(election_timeout, failover_timeout)\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"local.start\"],\n cancels: [\"rx.votes\", \"app.failover\"],\n fires: \"timer.election\",\n note: \"-failover-abort-not-elected. A forced failover (SENTINEL FAILOVER) does not wait for votes\",\n },\n desync: {\n // failover_start_time = now + rand() % SENTINEL_MAX_DESYNC (sentinel.c:4946, :4654)\n duration: { const: 0, unit: \"ms\" },\n lateness: { expr: \"max_desync - 1\", unit: \"ms\" },\n arms: [\"local.start\"],\n fires: \"timer.election\",\n note: \"a random delay of the start time: it moves the abort of an election and the next attempt, not the election itself\",\n },\n retry: {\n duration: { expr: \"failover_timeout * 2\", unit: \"ms\" },\n arms: [\"local.start\"],\n fires: \"timer.retry\",\n note: \"no new failover of the same primary sooner (sentinel.c:4969). A switch resets it (sentinel.c:1545)\",\n },\n promotion: {\n duration: { knob: \"failover_timeout\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"tx.replicaof-noone\"],\n cancels: [\"rx.info-master\"],\n fires: \"timer.promotion\",\n note: \"-failover-abort-slave-timeout (sentinel.c:5198-5205)\",\n },\n reconf: {\n duration: { knob: \"replica_reconf_timeout\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"rx.info-master\"],\n cancels: [\"rx.info-reconfigured\"],\n fires: \"timer.reconf\",\n note: \"a replica that does not follow in time counts as done (sentinel.c:5294-5300)\",\n },\n convert: {\n // a replica that reports master waits publish_period × 4 after the change of its role (sentinel.c:2635-2640)\n duration: { expr: \"publish_period * 4\", unit: \"ms\" },\n arms: [\"rx.info-master\"],\n fires: \"timer.convert\",\n note: \"the check runs at each INFO reply, so the conversion comes at the first INFO after this wait\",\n },\n low_activity: {\n // a command link with a PING pending for down_after / 2, open for min_link_reconnect_period, closes (sentinel.c:4456-4464)\n duration: { expr: \"max(min_link_reconnect_period, down_after / 2)\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"tx.ping\"],\n cancels: [\"rx.pong\"],\n fires: \"timer.low-activity\",\n },\n },\n transitions: [\n { id: \"sdown\", from: \"up\", to: \"sdown\", on: \"timer.down-after\", timer: \"down_after\", emits: [\"+sdown\"], source: \"sentinel.c:4482-4491\" },\n { id: \"sdown-clear\", from: \"sdown\", to: \"up\", on: \"rx.pong\", emits: [\"-sdown\"], source: \"sentinel.c:4493-4498\" },\n {\n id: \"odown\",\n from: \"sdown\",\n to: \"odown\",\n on: \"local.quorum\",\n emits: [\"+odown\"],\n guard: \"the reply of another Sentinel that is down too, then this Sentinel's next tick\",\n source: \"sentinel.c:4508-4535\",\n },\n { id: \"odown-clear\", from: \"odown\", to: \"up\", on: \"rx.pong\", emits: [\"-odown\", \"-sdown\"] },\n { id: \"start\", from: \"odown\", to: \"wait-start\", on: \"local.start\", emits: [\"+new-epoch\", \"+try-failover\"], source: \"sentinel.c:4938-4948\" },\n {\n id: \"planned\",\n from: \"up\",\n to: \"wait-start\",\n on: \"app.failover\",\n emits: [\"+new-epoch\", \"+try-failover\"],\n guard: \"SRI_FORCE_FAILOVER: no election. COORDINATED holds an election as an ODOWN does\",\n source: \"sentinel.c:3949-3962\",\n },\n {\n id: \"elected\",\n from: \"wait-start\",\n to: \"select-replica\",\n on: [\"rx.votes\", \"app.failover\"],\n emits: [\"+elected-leader\", \"+failover-state-select-slave\"],\n guard: \"at the next tick after the votes\",\n source: \"sentinel.c:5090-5119\",\n },\n { id: \"not-elected\", from: \"wait-start\", to: \"odown\", on: \"timer.election\", timer: \"election\", emits: [\"-failover-abort-not-elected\"] },\n {\n id: \"selected\",\n from: \"select-replica\",\n to: \"send-replicaof-noone\",\n on: \"local.selected\",\n emits: [\"+selected-slave\", \"+failover-state-send-slaveof-noone\"],\n guard: \"at the next tick\",\n source: \"sentinel.c:5121-5137\",\n },\n { id: \"no-replica\", from: \"select-replica\", to: \"odown\", on: \"local.no-replica\", emits: [\"-failover-abort-no-good-slave\"] },\n {\n id: \"replicaof-noone\",\n from: \"send-replicaof-noone\",\n to: \"wait-promotion\",\n on: \"tx.replicaof-noone\",\n emits: [\"+failover-state-wait-promotion\"],\n guard: \"at the next tick\",\n source: \"sentinel.c:5171-5196\",\n },\n {\n id: \"promoted\",\n from: \"wait-promotion\",\n to: \"reconf-replicas\",\n on: \"rx.info-master\",\n emits: [\"+promoted-slave\", \"+failover-state-reconf-slaves\"],\n note: \"get-master-addr-by-name gives the new primary from here (sentinel.c:1658-1670)\",\n source: \"sentinel.c:2610-2630\",\n },\n { id: \"promotion-timeout\", from: \"wait-promotion\", to: \"odown\", on: \"timer.promotion\", timer: \"promotion\", emits: [\"-failover-abort-slave-timeout\"] },\n {\n id: \"reconfigured\",\n from: \"reconf-replicas\",\n to: \"update-config\",\n on: [\"rx.info-reconfigured\", \"timer.reconf\"],\n emits: [\"+failover-end\"],\n source: \"sentinel.c:5207-5246\",\n },\n { id: \"switch\", from: \"update-config\", to: \"up\", on: \"local.switch\", emits: [\"+switch-master\"], source: \"sentinel.c:5324-5332\" },\n {\n id: \"switch-from-hello\",\n from: [\"up\", \"sdown\", \"odown\"],\n to: \"up\",\n on: \"rx.hello-newer\",\n emits: [\"+config-update-from\", \"+switch-master\"],\n note: \"the other Sentinels switch on the hello of the leader, before the leader's own +failover-end\",\n source: \"sentinel.c:2848-2862\",\n },\n ],\n});\n","// @mark1russell7/machines: the machine documents of the systems program, in one place. Each\n// document is a `mark1russell7.machine/1` document of @mark1russell7/algebra. It describes one\n// system at one version from its source, and each fact names its file and line. The schema of the\n// algebra examines each document at load. A document changes only for a reason from its source\n// (a citation) or from a measurement (a run).\n\nimport type { Machine } from \"@mark1russell7/algebra\";\nimport { GO_TRANSPORT } from \"./http/go-transport.ts\";\nimport { NODE_HTTP_AGENT } from \"./http/node-agent.ts\";\nimport { NODE_HTTP_SERVER } from \"./http/node-server.ts\";\nimport { UNDICI_CLIENT } from \"./http/undici.ts\";\nimport { IOREDIS_SENTINEL } from \"./ioredis-sentinel.ts\";\nimport { IOREDIS_STATUS, LINUX_TCP, NF_CONNTRACK_TCP, REDIS_CLIENT } from \"./json.ts\";\nimport { MONGOD_REPL } from \"./mongo/mongod-replication.ts\";\nimport { MONGOD_SESSION } from \"./mongo/mongod-session.ts\";\nimport { MONGODB_NODE } from \"./mongo/mongodb-node.ts\";\nimport { HIKARICP_PGJDBC } from \"./pg/hikaricp-pgjdbc.ts\";\nimport { NODE_POSTGRES } from \"./pg/node-postgres.ts\";\nimport { PGBOUNCER_CLIENT } from \"./pg/pgbouncer.ts\";\nimport { PGBOUNCER_SERVER } from \"./pg/pgbouncer-server.ts\";\nimport { PGPOOL_SESSION } from \"./pg/pgpool.ts\";\nimport { POSTGRES_SESSION } from \"./pg/postgres-session.ts\";\nimport { SUPAVISOR_CLIENT } from \"./pg/supavisor-client.ts\";\nimport { SUPAVISOR_SERVER } from \"./pg/supavisor-server.ts\";\nimport { PROCEDURES_WS_CLIENT, PROCEDURES_WS_SERVER } from \"./procedures-ws.ts\";\nimport { SENTINEL } from \"./sentinel.ts\";\n\nexport {\n GO_TRANSPORT,\n HIKARICP_PGJDBC,\n IOREDIS_SENTINEL,\n IOREDIS_STATUS,\n LINUX_TCP,\n MONGOD_REPL,\n MONGOD_SESSION,\n MONGODB_NODE,\n NF_CONNTRACK_TCP,\n NODE_HTTP_AGENT,\n NODE_HTTP_SERVER,\n NODE_POSTGRES,\n PGBOUNCER_CLIENT,\n PGBOUNCER_SERVER,\n PGPOOL_SESSION,\n POSTGRES_SESSION,\n PROCEDURES_WS_CLIENT,\n PROCEDURES_WS_SERVER,\n REDIS_CLIENT,\n SENTINEL,\n SUPAVISOR_CLIENT,\n SUPAVISOR_SERVER,\n UNDICI_CLIENT,\n};\nexport { MANIFESTATIONS } from \"./json.ts\";\nexport {\n NODE_TIMER_EARLY,\n UNDICI_TICK_MS,\n goLateSeconds,\n goTimerLateness,\n nodeEarlySeconds,\n nodeLateSeconds,\n nodeTimerLateness,\n undiciFastEarly,\n undiciFastLateness,\n} from \"./http/timers.ts\";\n\n/** This function gives each document by its identifier. Two documents with one identifier stop the import. */\nconst byId = (documents: readonly Machine[]): Readonly<Record<string, Machine>> => {\n const out: Record<string, Machine> = {};\n for (const document of documents) {\n if (out[document.id] !== undefined) throw new Error(`two machine documents have the identifier ${document.id}`);\n out[document.id] = document;\n }\n return Object.freeze(out);\n};\n\n/**\n * This map holds each document of the package by its identifier, for example `linux-tcp`. A\n * document on another machine names that machine in `over.machine` as `systems.machine.<id>`.\n */\nexport const MACHINES: Readonly<Record<string, Machine>> = byId([\n LINUX_TCP,\n NF_CONNTRACK_TCP,\n REDIS_CLIENT,\n IOREDIS_STATUS,\n IOREDIS_SENTINEL,\n SENTINEL,\n NODE_HTTP_SERVER,\n NODE_HTTP_AGENT,\n UNDICI_CLIENT,\n GO_TRANSPORT,\n PROCEDURES_WS_CLIENT,\n PROCEDURES_WS_SERVER,\n MONGODB_NODE,\n MONGOD_REPL,\n MONGOD_SESSION,\n NODE_POSTGRES,\n POSTGRES_SESSION,\n HIKARICP_PGJDBC,\n PGBOUNCER_CLIENT,\n PGBOUNCER_SERVER,\n PGPOOL_SESSION,\n SUPAVISOR_CLIENT,\n SUPAVISOR_SERVER,\n]);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["AT","linuxTcp","nfConntrackTcp","redisClient","ioredisStatus","manifestations","AT","AT","AT","AT","AT"],"sources":["../src/http/timers.ts","../src/http/go-transport.ts","../src/http/node-agent.ts","../src/http/node-server.ts","../src/http/undici.ts","../src/ioredis-sentinel.ts","../src/ioredis-status.json","../src/linux-tcp.json","../src/manifestations.json","../src/nf-conntrack-tcp.json","../src/redis-client.json","../src/json.ts","../src/mongo/mongod-replication.ts","../src/mongo/mongod-session.ts","../src/mongo/mongodb-node.ts","../src/pg/hikaricp-pgjdbc.ts","../src/pg/node-postgres.ts","../src/pg/pgbouncer.ts","../src/pg/pgbouncer-server.ts","../src/pg/pgpool.ts","../src/pg/postgres-session.ts","../src/pg/supavisor-client.ts","../src/pg/supavisor-server.ts","../src/procedures-ws.ts","../src/sentinel.ts","../src/index.ts"],"sourcesContent":["import type { Expr } from \"@mark1russell7/algebra\";\n\n/**\n * This module gives the lateness of a timer in user space on Linux 6.6. A Node timer and a Go timer\n * both sleep in `epoll_wait` with a timeout in whole milliseconds. The kernel lets that sleep end\n * late by a slack, and the loop reads its clock in whole milliseconds.\n *\n * The facts, each from the source at its version:\n * - `fs/eventpoll.c:1836` (Linux v6.6) takes the slack from `select_estimate_accuracy`, and\n * `fs/eventpoll.c:1921` sleeps with `schedule_hrtimeout_range(to, slack)`. Thus the wake comes\n * in [due, due + slack].\n * - `fs/select.c:51-74` makes the slack the remaining time divided by 1000, at most 100 ms\n * (`MAX_SLACK`). A task with a nice value above 0 divides by 200.\n * - `fs/select.c:91-92` and `init/init_task.c:133` make the slack 50 µs at the minimum\n * (`timer_slack_ns`).\n * - libuv 1.52.1 (`deps/uv/src/unix/linux.c:1451` in Node v24.21.0) calls `epoll_pwait` with the\n * timeout in milliseconds. `deps/uv/src/timer.c:143-160` gives that timeout as the due time\n * less the loop clock, in milliseconds.\n * - `deps/uv/src/unix/internal.h:467-470` truncates the loop clock to milliseconds.\n * - `deps/uv/src/unix/linux.c:1603-1629` reads `CLOCK_MONOTONIC_COARSE` for that clock when its\n * resolution is 1 ms or less, and `CLOCK_MONOTONIC` when it is coarser.\n * - The resolution of the coarse clock is one jiffy (`kernel/time/posix-timers.c:187-190`,\n * `include/vdso/ktime.h:13-14`, `include/vdso/jiffies.h`). It gives the time of the last tick.\n * Thus at HZ 1000 the loop clock can be one jiffy behind, and at HZ 250 it is exact.\n * - Node stamps the start of a timer with the loop clock (`lib/internal/timers.js:426-429`,\n * `src/env.cc:1649-1651`). It starts the callback of a timer when the loop clock less that start\n * is the duration or more (`lib/internal/timers.js:631-641`). Thus the start can be up to 1 ms\n * before the arming, and one more step of the coarse clock.\n * - Go 1.27.2 sleeps in `epoll_wait` with the delay truncated to milliseconds, and with 1 ms when\n * less than 1 ms remains (`src/runtime/netpoll_epoll.go:117-133`). A Go timer does not fire\n * early: a wake before the due time sleeps again.\n *\n * The time that the loop itself spends in callbacks is the time of the application. These\n * documents do not bound it, and the noise of the harness (δ_abs) holds a small part of it. The\n * handling of the first reply by a Node client can take more time than δ_abs, before the client\n * arms its pool timer. The race of the cells adds that time from a calibration (`HANDLING` in\n * `packages/cells/src/http/race.ts`).\n */\n\n/** This text is the slack of `epoll_wait` for a sleep of `ms` milliseconds, in milliseconds. */\nconst slackMs = (ms: string): string => `min(max((${ms}) / 1000, 0.05), 100)`;\n\n/**\n * This text is the step of the loop clock of libuv, in milliseconds, from the knob `hz`. It is one\n * jiffy when the coarse clock is 1 ms or finer (HZ 1000). It is 0 when libuv reads `CLOCK_MONOTONIC`.\n */\nconst COARSE_MS = \"min(floor(hz / 1000), 1) * 1000 / hz\";\n\n/**\n * This function gives the lateness of a Node timer of `ms` milliseconds. The lateness is the slack\n * of its sleep, 1 ms for the truncation of the loop clock, and the step of the coarse clock. The\n * arithmetic reads `ms` in milliseconds, and the knob `hz` in Hz.\n */\nexport const nodeTimerLateness = (ms: string): Expr => ({ expr: `${slackMs(ms)} + 1 + ${COARSE_MS}`, unit: \"ms\" });\n\n/**\n * This expression is how early a Node timer can fire. It is 1 ms for the truncation of the loop\n * clock that stamps its start, and the step of the coarse clock.\n */\nexport const NODE_TIMER_EARLY: Expr = { expr: `1 + ${COARSE_MS}`, unit: \"ms\" };\n\n/** 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. */\nexport const goTimerLateness = (s: string): Expr => ({\n expr: `min(max((${s}) / 1000, 0.00005), 0.1) + 0.001`,\n unit: \"s\",\n});\n\n/** This function gives the step of the coarse loop clock at a HZ, in seconds: the number form of `COARSE_MS`. */\nconst coarseSeconds = (hz: number): number => (Math.min(Math.floor(hz / 1000), 1) * 1000) / hz / 1000;\n\n/** This function gives the lateness of a Node timer of `seconds` at a HZ, in seconds: the number form of `nodeTimerLateness`. */\nexport const nodeLateSeconds = (seconds: number, hz: number): number =>\n (Math.min(Math.max(seconds, 0.05), 100) + 1) / 1000 + coarseSeconds(hz);\n\n/** This function gives how early a Node timer can fire at a HZ, in seconds: the number form of `NODE_TIMER_EARLY`. */\nexport const nodeEarlySeconds = (hz: number): number => 0.001 + coarseSeconds(hz);\n\n/** This function gives the lateness of a Go timer of `seconds`, in seconds: the number form of `goTimerLateness`. */\nexport const goLateSeconds = (seconds: number): number => Math.min(Math.max(seconds / 1000, 0.00005), 0.1) + 0.001;\n\n/**\n * This count is the tick of the fast timers of undici 8.12.2, in milliseconds:\n * `(RESOLUTION_MS >> 1) - 1` with `RESOLUTION_MS` 1000 (`lib/util/timers.js:30-40`).\n */\nexport const UNDICI_TICK_MS = 499;\n\n/**\n * This function gives how early a fast timer of undici can fire, for a duration of `ms`\n * milliseconds. Each tick adds the tick to the clock of the fast timers, whatever time passed\n * (`lib/util/timers.js:115-123`).\n *\n * A new timer takes the clock of the next tick less one tick as its\n * start (`lib/util/timers.js:151-155`). It fires at the first tick where the clock is its start\n * plus its duration or more (`lib/util/timers.js:156-162`). Thus it fires after\n * `ceil(ms / 499) - 1` ticks and part of one more tick. Each tick is a Node timer. The loop clock\n * of each tick has the same lag, thus the early bound of a Node timer comes in one time.\n */\nexport const undiciFastEarly = (ms: string): Expr => ({\n expr: `(${ms}) - (ceil((${ms}) / ${UNDICI_TICK_MS}) - 1) * ${UNDICI_TICK_MS} + 1 + ${COARSE_MS}`,\n unit: \"ms\",\n});\n\n/**\n * This function gives how late a fast timer of undici can fire, for a duration of `ms`\n * milliseconds. It fires after at most `ceil(ms / 499)` whole ticks. Each tick is a Node timer\n * of 499 ms (`lib/util/timers.js:190-207`), with the lateness of a Node timer.\n */\nexport const undiciFastLateness = (ms: string): Expr => ({\n expr:\n `ceil((${ms}) / ${UNDICI_TICK_MS}) * ${UNDICI_TICK_MS} - (${ms})` +\n ` + ceil((${ms}) / ${UNDICI_TICK_MS}) * (${slackMs(String(UNDICI_TICK_MS))} + 1 + ${COARSE_MS})`,\n unit: \"ms\",\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { goTimerLateness } from \"./timers.ts\";\n\n/**\n * This document is one connection of the `http.Transport` of Go 1.27.2 at its defaults, over its\n * Linux TCP socket. Each fact comes from the source at the tag `go1.27.2`. The comments give the\n * file and the line.\n *\n * The idle timeout is the C of the keep-alive race. The transport ignores the `Keep-Alive` hint of\n * the server. It finds a connection that the server closed when its read loop reads the end of\n * file. A reused connection can fail before any byte of the reply. Then the transport sends a\n * request that it can replay again, on a new connection, by itself.\n */\nexport const GO_TRANSPORT: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"go-nethttp-transport\",\n title: \"One connection of the http.Transport of Go 1.27.2\",\n layer: \"driver\",\n version: \"go1.27.2\",\n conditions: { go: \"1.27.2\", os: \"linux\", protocol: \"HTTP/1.1 without TLS\" },\n sources: [\n {\n ref: \"go1.27.2 src/net/http/transport.go:47-62 DefaultTransport: Dialer Timeout 30 s and KeepAlive 30 s, MaxIdleConns 100, IdleConnTimeout 90 s, DefaultMaxIdleConnsPerHost 2\",\n rung: \"implemented\",\n },\n {\n ref: \"go1.27.2 src/net/http/transport.go:1129-1236 tryPutIdleConn: the connection goes back to the pool after its reply, with an idle timer of IdleConnTimeout and idleAt = now\",\n rung: \"implemented\",\n },\n {\n ref: \"go1.27.2 src/net/http/transport.go:1241-1303 queueForIdleConn: the most recent idle connection, unless it is broken or idle for IdleConnTimeout or more by the wall clock\",\n rung: \"implemented\",\n },\n {\n ref: \"go1.27.2 src/net/http/transport.go:2454-2512 readLoop and :2653-2672 readLoopPeekFailLocked: an end of file on an idle connection closes it (errServerClosedIdle); a read error while a reply is due is transportReadFromServerError\",\n rung: \"implemented\",\n },\n {\n ref: \"go1.27.2 src/net/http/transport.go:694-769 roundTrip and :844-889 shouldRetryRequest: a new connection for a reused connection that failed before the reply, when the request can be replayed\",\n rung: \"implemented\",\n },\n {\n ref: \"go1.27.2 src/net/http/request.go:1561-1573 isReplayable: GET, HEAD, OPTIONS, TRACE without a body, or a request with an Idempotency-Key\",\n rung: \"implemented\",\n },\n {\n ref: \"go1.27.2 src/net/tcpsock.go:289-307 newTCPConn: TCP_NODELAY on, and keepalive from Dialer.KeepAlive; src/net/tcpsock_unix.go:12-27; src/net/tcpsockopt_unix.go:15-53 (idle and interval 15 s and count 9 when 0, rounded up to whole seconds); src/net/dial.go:18-27\",\n rung: \"implemented\",\n },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n DIALING: {},\n ACTIVE: { note: \"a request owns the connection\" },\n IDLE: { note: \"in the pool of idle connections\" },\n CLOSED: { final: true },\n },\n events: {\n \"req.dispatch\": { kind: \"app\", note: \"a request asks the transport for a connection (getConn)\" },\n \"conn.established\": { kind: \"local\" },\n \"resp.done\": { kind: \"local\", note: \"the reply was read to its end: the read loop puts the connection back\" },\n \"rx.fin\": { kind: \"peer\", note: \"the read loop reads io.EOF\" },\n \"read.error\": { kind: \"local\", note: \"a read fails: ECONNRESET, ETIMEDOUT, EHOSTUNREACH\" },\n \"rx.rst\": { kind: \"peer\" },\n \"rx.icmp-hard\": { kind: \"rx\", note: \"an ICMP error while the dial waits\" },\n \"timer.idle-conn\": { kind: \"timer\" },\n \"timer.dial\": { kind: \"timer\" },\n \"timer.client\": { kind: \"timer\" },\n \"timer.response-header\": { kind: \"timer\" },\n \"tx.request\": { kind: \"tx\", note: \"the write loop wrote the request\" },\n \"rx.headers\": { kind: \"rx\" },\n },\n knobs: {\n IdleConnTimeout: { key: \"go http.Transport IdleConnTimeout\", scope: \"client\", unit: \"s\", default: 90 },\n MaxIdleConnsPerHost: {\n key: \"go http.Transport MaxIdleConnsPerHost\",\n scope: \"client\",\n unit: \"count\",\n default: 2,\n note: \"0 gives DefaultMaxIdleConnsPerHost, 2 (transport.go:1121)\",\n },\n MaxIdleConns: { key: \"go http.Transport MaxIdleConns\", scope: \"client\", unit: \"count\", default: 100 },\n DialTimeout: { key: \"go net.Dialer Timeout\", scope: \"client\", unit: \"s\", default: 30 },\n KeepAlive: {\n key: \"go net.Dialer KeepAlive\",\n scope: \"client\",\n unit: \"s\",\n default: 30,\n note: \"the TCP_KEEPIDLE of the socket; 0 gives 15 s, and a negative value turns keepalive off\",\n },\n KeepAliveInterval: {\n key: \"go net.KeepAliveConfig Interval\",\n scope: \"client\",\n unit: \"s\",\n default: 15,\n note: \"0 gives 15 s (dial.go:24)\",\n },\n KeepAliveCount: {\n key: \"go net.KeepAliveConfig Count\",\n scope: \"client\",\n unit: \"count\",\n default: 9,\n note: \"0 gives 9 (dial.go:27)\",\n },\n Timeout: {\n key: \"go http.Client Timeout\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n note: \"0 is no deadline: a reader gives it no bound\",\n },\n ResponseHeaderTimeout: {\n key: \"go http.Transport ResponseHeaderTimeout\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n note: \"0 is no deadline\",\n },\n },\n timers: {\n idle_conn: {\n duration: { knob: \"IdleConnTimeout\", unit: \"s\" },\n lateness: goTimerLateness(\"IdleConnTimeout\"),\n arms: [\"resp.done\", \"enter:IDLE\"],\n cancels: [\"req.dispatch\"],\n fires: \"timer.idle-conn\",\n note: \"time.AfterFunc(IdleConnTimeout, closeConnIfStillIdle) closes the connection late by a Go timer. The reuse is exact: queueForIdleConn compares idleAt with the wall clock\",\n },\n dial: {\n duration: { knob: \"DialTimeout\", unit: \"s\" },\n lateness: goTimerLateness(\"DialTimeout\"),\n arms: [\"enter:DIALING\"],\n cancels: [\"conn.established\"],\n fires: \"timer.dial\",\n },\n client: {\n duration: { knob: \"Timeout\", unit: \"s\" },\n lateness: goTimerLateness(\"Timeout\"),\n arms: [\"req.dispatch\", \"enter:ACTIVE\"],\n cancels: [\"resp.done\"],\n fires: \"timer.client\",\n },\n response_header: {\n duration: { knob: \"ResponseHeaderTimeout\", unit: \"s\" },\n lateness: goTimerLateness(\"ResponseHeaderTimeout\"),\n arms: [\"tx.request\", \"enter:ACTIVE\"],\n cancels: [\"rx.headers\"],\n fires: \"timer.response-header\",\n },\n },\n realizes: {\n \"systems.mechanism.pool-idle-expiry\": { timer: \"idle_conn\" },\n \"systems.mechanism.connect-bound\": { timer: \"dial\" },\n \"systems.mechanism.request-timeout\": { timer: \"client\" },\n },\n transitions: [\n {\n id: \"gt.dial\",\n from: \"ABSENT\",\n to: \"DIALING\",\n on: \"req.dispatch\",\n guard: \"no idle connection that is younger than IdleConnTimeout and not broken\",\n source: \"transport.go:1613-1616\",\n },\n { id: \"gt.connected\", from: \"DIALING\", to: \"ACTIVE\", on: \"conn.established\" },\n { id: \"gt.dial-timeout\", from: \"DIALING\", to: \"CLOSED\", on: \"timer.dial\", timer: \"dial\", errno: \"TIMEOUT\" },\n { id: \"gt.dial-refused\", from: \"DIALING\", to: \"CLOSED\", on: \"rx.rst\", errno: \"ECONNREFUSED\" },\n { id: \"gt.dial-unreachable\", from: \"DIALING\", to: \"CLOSED\", on: \"rx.icmp-hard\", errno: \"EHOSTUNREACH\" },\n {\n id: \"gt.idle\",\n from: \"ACTIVE\",\n to: \"IDLE\",\n on: \"resp.done\",\n guard: \"neither side asked for a close, and fewer than MaxIdleConnsPerHost connections are idle\",\n timer: \"idle_conn\",\n source: \"transport.go:1129-1236, :2547-2556, :2616-2627\",\n },\n {\n id: \"gt.reuse\",\n from: \"IDLE\",\n to: \"ACTIVE\",\n on: \"req.dispatch\",\n guard: \"idle for less than IdleConnTimeout by the wall clock, and not broken\",\n source: \"transport.go:1258-1303\",\n },\n {\n id: \"gt.expire\",\n from: \"IDLE\",\n to: \"CLOSED\",\n on: \"timer.idle-conn\",\n timer: \"idle_conn\",\n emits: [\"tx.fin\"],\n source: \"transport.go:2342-2352\",\n },\n {\n id: \"gt.server-closed-idle\",\n from: \"IDLE\",\n to: \"CLOSED\",\n on: [\"rx.fin\", \"read.error\"],\n emits: [\"tx.fin\"],\n source: \"transport.go:2493-2500, :2653-2672\",\n },\n {\n id: \"gt.retry\",\n from: \"ACTIVE\",\n to: \"CLOSED\",\n on: [\"rx.fin\", \"read.error\"],\n guard: \"the connection was reused, no byte of the reply came, and the request can be replayed\",\n emits: [\"req.retry\"],\n note: \"the request goes again on a new connection, and the caller sees only the second outcome\",\n source: \"transport.go:740-768, :844-889\",\n },\n {\n id: \"gt.fail\",\n from: \"ACTIVE\",\n to: \"CLOSED\",\n on: [\"rx.fin\", \"read.error\"],\n guard: \"otherwise: a new connection, or a request that it cannot replay\",\n errno: \"EOF\",\n note: \"the caller gets the read error: io.EOF, or the errno of the socket\",\n source: \"transport.go:745-760\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { DIALING: \"SYN_SENT\", ACTIVE: \"ESTABLISHED\", IDLE: \"ESTABLISHED\" },\n sets: {\n keepidle: { expr: \"ceil(KeepAlive)\", unit: \"s\" },\n keepintvl: { expr: \"ceil(KeepAliveInterval)\", unit: \"s\" },\n keepcnt: { knob: \"KeepAliveCount\", unit: \"count\" },\n },\n ends: \"read.error\",\n note: \"Go sets SO_KEEPALIVE with its own idle, interval and count on each dialed socket, rounded up to whole seconds. Thus the keepalive sysctls of the namespace do not reach it. A negative KeepAlive turns it off: a reader gives keepidle no bound.\",\n },\n} satisfies Machine);\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { NODE_TIMER_EARLY, nodeTimerLateness } from \"./timers.ts\";\n\n/**\n * This document is one socket of the `http.Agent` of Node v24.21.0, as its global agent sets it.\n * 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\n * comes from the source at the tag `v24.21.0`, with the file and the line.\n *\n * A free socket keeps its connection until the smaller of the timeout of the agent and the hint of\n * the server less a buffer. An agent without a timeout keeps it with no limit, and then the hint\n * changes nothing.\n *\n * The free socket timer arms on the event loop of the program, when the program has read the\n * whole response. The time from the last segment that the kernel received to that arm is the time\n * of the program. No source bounds it, and this document does not hold it. The race of the cells\n * adds it from a calibration (`HANDLING` in `packages/cells/src/http/race.ts`).\n */\nexport const NODE_HTTP_AGENT: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"node-http-agent\",\n title: \"One socket of the http.Agent of Node 24.21.0\",\n layer: \"driver\",\n version: \"24.21.0\",\n conditions: { node: \"24.21.0\", libuv: \"1.52.1\", agent: \"http.globalAgent, or an Agent with its options\" },\n sources: [\n {\n ref: \"node v24.21.0 lib/internal/http.js:263-265 getGlobalAgent: keepAlive true, scheduling lifo, timeout 5000\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_agent.js:172-185 (keepAliveMsecs 1000, maxFreeSockets 256, scheduling lifo, agentKeepAliveTimeoutBuffer 1000)\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_agent.js:201-265 the free event, and :633-667 keepSocketAlive: setKeepAlive(true, keepAliveMsecs), and the free socket timeout is min(timeout, hint * 1000 - agentKeepAliveTimeoutBuffer), or no reuse when that is 0 or less\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_client.js:964 and :1017-1051 responseOnEnd at the end of the response, :986-1015 responseKeepAlive and :1074-1080 emitFreeNT: the socket emits free on the next tick, on the event loop\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_agent.js:662-664: keepSocketAlive sets the timeout only when it changes. Else the timeout of the socket from its connect (:452-456, lib/net.js:257-258) counts from its last read or write (lib/net.js:738-745, lib/internal/stream_base_commons.js:164-170)\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_agent.js:101-139 freeSocketOnReadGuard: a read on a free socket, an end of file too, destroys it\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_agent.js:385-416 addRequest: a free socket by LIFO, after the destroyed ones at the head; :541-550 onTimeout destroys a free socket; :669-675 reuseSocket sets req.reusedSocket\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_client.js:712-797: an end or a close before the response is socket hang up (ECONNRESET), and a socket error goes to the request. The agent sends no request again\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/net.js:846-888 setKeepAlive (the delay in whole seconds) and src/tcp_wrap.cc:204-219 (interval 1 s and count 10 when none is given)\",\n rung: \"implemented\",\n },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n CONNECTING: {},\n BUSY: { note: \"a request owns the socket\" },\n FREE: { note: \"in the freeSockets list of the agent\" },\n CLOSED: { final: true },\n },\n events: {\n \"req.dispatch\": { kind: \"app\", note: \"agent.addRequest\" },\n \"socket.connect\": { kind: \"local\" },\n \"resp.end\": {\n kind: \"local\",\n note: \"the program read the whole response: the socket emits free on the next tick. It comes after the last segment by the handling time of the program\",\n },\n \"rx.fin\": { kind: \"peer\" },\n \"rx.rst\": { kind: \"peer\" },\n \"rx.data\": { kind: \"peer\", note: \"bytes that nothing asked for\" },\n \"timer.free-socket\": { kind: \"timer\" },\n \"socket.error\": { kind: \"local\", note: \"the kernel beneath gave up, or an ICMP error ended the socket\" },\n },\n knobs: {\n keepAlive: {\n key: \"node http.Agent keepAlive\",\n scope: \"client\",\n unit: null,\n default: 1,\n note: \"1 for the global agent; new Agent() without options has 0\",\n },\n timeout: {\n key: \"node http.Agent timeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 5000,\n note: \"5000 for the global agent; 0 is no free socket timer, and then the hint does not apply: a reader gives timeout and hint no bound\",\n },\n keepAliveMsecs: { key: \"node http.Agent keepAliveMsecs\", scope: \"client\", unit: \"ms\", default: 1000 },\n agentKeepAliveTimeoutBuffer: {\n key: \"node http.Agent agentKeepAliveTimeoutBuffer\",\n scope: \"client\",\n unit: \"ms\",\n default: 1000,\n },\n maxFreeSockets: { key: \"node http.Agent maxFreeSockets\", scope: \"client\", unit: \"count\", default: 256 },\n hint: {\n key: \"Keep-Alive timeout= of the server\",\n scope: \"connection\",\n unit: \"s\",\n default: null,\n note: \"the hint that the response gives; a response without one: a reader gives it no bound\",\n },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"the HZ of the kernel, for the step of the coarse loop clock of libuv (timers.ts)\",\n },\n },\n timers: {\n free_socket: {\n duration: { expr: \"min(timeout, hint * 1000 - agentKeepAliveTimeoutBuffer)\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"min(timeout, hint * 1000 - agentKeepAliveTimeoutBuffer)\"),\n early: NODE_TIMER_EARLY,\n arms: [\"resp.end\", \"enter:FREE\"],\n cancels: [\"req.dispatch\"],\n fires: \"timer.free-socket\",\n note: \"socket.setTimeout(agentTimeout) in keepSocketAlive: the Node timer of the socket. It arms in the free handler, or at the last read of the reply when its duration stays the same. Both come in the handling time of the program after the last segment (race.ts)\",\n },\n },\n realizes: {\n \"systems.mechanism.pool-idle-expiry\": { timer: \"free_socket\" },\n },\n transitions: [\n { id: \"na.connect\", from: \"ABSENT\", to: \"CONNECTING\", on: \"req.dispatch\", guard: \"no free socket\" },\n { id: \"na.connected\", from: \"CONNECTING\", to: \"BUSY\", on: \"socket.connect\" },\n {\n id: \"na.free\",\n from: \"BUSY\",\n to: \"FREE\",\n on: \"resp.end\",\n guard: \"keepAlive, the response keeps the connection, and hint * 1000 - agentKeepAliveTimeoutBuffer > 0\",\n timer: \"free_socket\",\n source: \"lib/_http_agent.js:237-264, :633-667\",\n },\n {\n id: \"na.no-reuse\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: \"resp.end\",\n guard: \"hint * 1000 - agentKeepAliveTimeoutBuffer is 0 or less, or the response closes the connection\",\n emits: [\"tx.fin\"],\n source: \"lib/_http_agent.js:238-254, :649-654\",\n },\n {\n id: \"na.reuse\",\n from: \"FREE\",\n to: \"BUSY\",\n on: \"req.dispatch\",\n guard: \"the socket is not destroyed\",\n source: \"lib/_http_agent.js:385-416\",\n },\n {\n id: \"na.expire\",\n from: \"FREE\",\n to: \"CLOSED\",\n on: \"timer.free-socket\",\n timer: \"free_socket\",\n emits: [\"tx.fin\"],\n source: \"lib/_http_agent.js:541-550\",\n },\n {\n id: \"na.peer-closed\",\n from: \"FREE\",\n to: \"CLOSED\",\n on: [\"rx.fin\", \"rx.rst\", \"rx.data\", \"socket.error\"],\n source: \"lib/_http_agent.js:94-112\",\n },\n {\n id: \"na.hang-up\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: \"rx.fin\",\n errno: \"ECONNRESET\",\n note: \"socket hang up, an error with the code ECONNRESET\",\n source: \"lib/_http_client.js:781-797\",\n },\n {\n id: \"na.reset\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: [\"rx.rst\", \"socket.error\"],\n errno: \"ECONNRESET\",\n note: \"the errno of the socket: ECONNRESET for a reset, ETIMEDOUT or the soft ICMP errno for a give-up\",\n source: \"lib/_http_client.js:757-779\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { CONNECTING: \"SYN_SENT\", BUSY: \"ESTABLISHED\", FREE: \"ESTABLISHED\" },\n sets: {\n keepidle: { expr: \"floor(keepAliveMsecs / 1000)\", unit: \"s\" },\n keepintvl: { const: 1, unit: \"s\" },\n keepcnt: { const: 10, unit: \"count\" },\n },\n ends: \"socket.error\",\n note: \"The agent turns keepalive on at the connect (lib/_http_agent.js:474-478, lib/net.js:1991-1994) and again on each free socket. Node passes the delay in whole seconds and libuv sets 1 s and 10 probes. Thus the keepalive sysctls of the namespace do not reach it.\",\n },\n} satisfies Machine);\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { NODE_TIMER_EARLY, nodeTimerLateness } from \"./timers.ts\";\n\n/**\n * This document is one connection as the `http.Server` of Node v24.21.0 holds it, over the Linux\n * TCP socket of the connection. Each fact comes from the source at the tag `v24.21.0`. The comments\n * give the file and the line.\n *\n * The keep-alive timer is the S of the keep-alive race. It arms when the response ends, not when\n * the request starts. It is a socket timeout on the timers of libuv, thus it has the lateness of a\n * Node timer (`timers.ts`). When it fires, the server closes the socket. The kernel sends a FIN, or\n * a reset when the receive queue has data that nothing read.\n */\nexport const NODE_HTTP_SERVER: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"node-http-server\",\n title: \"One connection as the http.Server of Node 24.21.0 holds it\",\n layer: \"server\",\n version: \"24.21.0\",\n conditions: { node: \"24.21.0\", libuv: \"1.52.1\", kernel: \"Linux 6.6\" },\n sources: [\n {\n ref: \"node v24.21.0 lib/_http_server.js:537-579 (requestTimeout 300000, headersTimeout min(60000, requestTimeout), keepAliveTimeout 5000, keepAliveTimeoutBuffer 1000, connectionsCheckingInterval 30000), :665-667 (timeout 0, maxRequestsPerSocket 0)\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_server.js:1096-1150 resOnFinish: the keep-alive timer arms when the response finishes, at keepAliveTimeout + keepAliveTimeoutBuffer\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_server.js:1167-1168 and :1299-1305 parserOnIncoming and resetSocketTimeout: the headers of the next request disarm it\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_server.js:963-968 onParserExecute and lib/net.js:738-745 _unrefTimer: each read refreshes the socket timeout\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_server.js:900-909 socketOnTimeout: without a timeout listener, the socket is destroyed; lib/net.js:1097-1131 _destroy closes the handle\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_outgoing.js:514-527: Keep-Alive: timeout=floor(keepAliveTimeout / 1000), with max= when maxRequestsPerSocket is set, and Connection: close on the last allowed response\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_server.js:616-624 and :743-764 checkConnections: the headers and request timeouts are a sweep each connectionsCheckingInterval; src/node_http_parser.cc:310-330, :1223-1284 (a connection counts from the start of its message, and leaves the list when the message is complete)\",\n rung: \"implemented\",\n },\n {\n ref: \"linux v6.6 net/ipv4/tcp.c:2771-2797 __tcp_close: unread data in the receive queue makes the close a reset (RFC 2525 2.17), else :2802-2832 a FIN\",\n rung: \"implemented\",\n },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n WAITING: { note: \"accepted, and no byte of a request yet: the headers timeout counts from the accept\" },\n READING: { note: \"a request has started and its headers or its body are not complete\" },\n HANDLING: { note: \"the request is complete and its response is not finished, for example a held reply\" },\n IDLE: { note: \"a response finished and the keep-alive timer is armed\" },\n CLOSED: { final: true },\n },\n events: {\n accept: { kind: \"local\" },\n \"rx.message-begin\": { kind: \"rx\", note: \"the first byte of a request (llhttp on_message_begin)\" },\n \"rx.request\": { kind: \"rx\", note: \"the headers of a request are complete: parserOnIncoming\" },\n \"rx.message-complete\": { kind: \"rx\", note: \"the whole request arrived, its body too\" },\n \"rx.data\": { kind: \"rx\", note: \"bytes arrive on the socket: each read refreshes the socket timeout\" },\n \"res.finish\": { kind: \"local\", note: \"the last byte of a response went to the kernel\" },\n \"rx.fin\": { kind: \"peer\", note: \"the client closed: socketOnEnd ends the socket, because httpAllowHalfOpen is false\" },\n \"rx.rst\": { kind: \"peer\" },\n \"timer.keep-alive\": { kind: \"timer\" },\n \"timer.headers\": { kind: \"timer\" },\n \"timer.request\": { kind: \"timer\" },\n \"timer.socket\": { kind: \"timer\" },\n \"socket.error\": { kind: \"local\", note: \"the kernel beneath gave up on the socket, or a reset arrived\" },\n },\n knobs: {\n keepAliveTimeout: {\n key: \"node http.Server keepAliveTimeout\",\n scope: \"server\",\n unit: \"ms\",\n default: 5000, off: 0,\n note: \"0 disables the keep-alive timer and the hint: a reader gives the timer no bound\",\n },\n keepAliveTimeoutBuffer: {\n key: \"node http.Server keepAliveTimeoutBuffer\",\n scope: \"server\",\n unit: \"ms\",\n default: 1000,\n note: \"added to the timer, not to the hint (lib/_http_server.js:1136-1141)\",\n },\n headersTimeout: { key: \"node http.Server headersTimeout\", scope: \"server\", unit: \"ms\", default: 60000 },\n requestTimeout: { key: \"node http.Server requestTimeout\", scope: \"server\", unit: \"ms\", default: 300000 },\n connectionsCheckingInterval: {\n key: \"node http.Server connectionsCheckingInterval\",\n scope: \"server\",\n unit: \"ms\",\n default: 30000,\n },\n timeout: {\n key: \"node http.Server timeout\",\n scope: \"server\",\n unit: \"ms\",\n default: 0, off: 0,\n note: \"the socket timeout while a request is open (lib/_http_server.js:1303); 0 is off\",\n },\n maxRequestsPerSocket: {\n key: \"node http.Server maxRequestsPerSocket\",\n scope: \"server\",\n unit: \"count\",\n default: 0,\n note: \"0 is no limit; at the limit the response says Connection: close, and a request above it gets 503 (lib/_http_server.js:1255-1271)\",\n },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"the HZ of the kernel: at 1000, libuv reads the coarse clock, a jiffy a step, and each Node timer gets that step on each bound (timers.ts)\",\n },\n },\n timers: {\n keep_alive: {\n duration: { expr: \"keepAliveTimeout + keepAliveTimeoutBuffer\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"keepAliveTimeout + keepAliveTimeoutBuffer\"),\n early: NODE_TIMER_EARLY,\n arms: [\"res.finish\", \"rx.data\", \"enter:IDLE\"],\n cancels: [\"rx.request\"],\n fires: \"timer.keep-alive\",\n note: \"socket.setTimeout(keepAliveTimeout + keepAliveTimeoutBuffer) in resOnFinish; a read refreshes it, and the headers of the next request reset it to the server timeout\",\n },\n headers: {\n duration: { knob: \"headersTimeout\", unit: \"ms\" },\n lateness: {\n expr: \"connectionsCheckingInterval + min(max(connectionsCheckingInterval / 1000, 0.05), 100) + 1\",\n unit: \"ms\",\n },\n arms: [\"accept\", \"rx.message-begin\", \"enter:WAITING\", \"enter:READING\"],\n cancels: [\"rx.request\"],\n fires: \"timer.headers\",\n note: \"a sweep each connectionsCheckingInterval finds the expired connections by uv_hrtime, thus the 408 comes in [T, T + interval], late by the interval timer\",\n },\n request: {\n duration: { knob: \"requestTimeout\", unit: \"ms\" },\n lateness: {\n expr: \"connectionsCheckingInterval + min(max(connectionsCheckingInterval / 1000, 0.05), 100) + 1\",\n unit: \"ms\",\n },\n arms: [\"accept\", \"rx.message-begin\", \"enter:READING\"],\n cancels: [\"rx.message-complete\"],\n fires: \"timer.request\",\n },\n socket: {\n duration: { knob: \"timeout\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"timeout\"),\n early: NODE_TIMER_EARLY,\n arms: [\"rx.request\", \"enter:HANDLING\"],\n cancels: [\"res.finish\"],\n fires: \"timer.socket\",\n note: \"off at its default: a reader gives 0 as no bound\",\n },\n },\n realizes: {\n \"systems.mechanism.server-idle-close\": { timer: \"keep_alive\" },\n },\n transitions: [\n { id: \"ns.accept\", from: \"ABSENT\", to: \"WAITING\", on: \"accept\" },\n {\n id: \"ns.begin\",\n from: [\"WAITING\", \"IDLE\"],\n to: \"READING\",\n on: \"rx.message-begin\",\n source: \"src/node_http_parser.cc:310-330\",\n },\n {\n id: \"ns.request\",\n from: \"READING\",\n to: \"HANDLING\",\n on: [\"rx.request\", \"rx.message-complete\"],\n source: \"lib/_http_server.js:1167-1168, :1299-1305\",\n },\n {\n id: \"ns.respond\",\n from: \"HANDLING\",\n to: \"IDLE\",\n on: \"res.finish\",\n guard: \"keepAliveTimeout > 0, and the response is not the last one (Connection: close or maxRequestsPerSocket)\",\n timer: \"keep_alive\",\n source: \"lib/_http_server.js:1130-1142\",\n },\n {\n id: \"ns.last\",\n from: \"HANDLING\",\n to: \"CLOSED\",\n on: \"res.finish\",\n guard: \"the response is the last one: destroySoon ends the socket after it\",\n emits: [\"tx.fin\"],\n source: \"lib/_http_server.js:1124-1129\",\n },\n {\n id: \"ns.keep-alive\",\n from: \"IDLE\",\n to: \"CLOSED\",\n on: \"timer.keep-alive\",\n timer: \"keep_alive\",\n emits: [\"tx.fin\"],\n note: \"a reset in place of the FIN when the receive queue holds data that nothing read (net/ipv4/tcp.c:2793-2797)\",\n source: \"lib/_http_server.js:900-909\",\n },\n {\n id: \"ns.headers-timeout\",\n from: [\"WAITING\", \"READING\"],\n to: \"CLOSED\",\n on: \"timer.headers\",\n timer: \"headers\",\n emits: [\"tx.408\", \"tx.fin\"],\n source: \"lib/_http_server.js:743-764, :958-961\",\n },\n {\n id: \"ns.request-timeout\",\n from: \"READING\",\n to: \"CLOSED\",\n on: \"timer.request\",\n timer: \"request\",\n emits: [\"tx.408\", \"tx.fin\"],\n source: \"lib/_http_server.js:743-764\",\n },\n {\n id: \"ns.peer-end\",\n from: [\"WAITING\", \"READING\", \"HANDLING\", \"IDLE\"],\n to: \"CLOSED\",\n on: \"rx.fin\",\n emits: [\"tx.fin\"],\n source: \"lib/_http_server.js:932-948\",\n },\n { id: \"ns.error\", from: [\"WAITING\", \"READING\", \"HANDLING\", \"IDLE\"], to: \"CLOSED\", on: [\"rx.rst\", \"socket.error\"] },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { WAITING: \"ESTABLISHED\", READING: \"ESTABLISHED\", HANDLING: \"ESTABLISHED\", IDLE: \"ESTABLISHED\" },\n sets: {},\n ends: \"socket.error\",\n note: \"http.Server passes keepAlive to net.Server, and its default is off (lib/_http_server.js:646-651, lib/net.js:2753-2756). Thus an accepted socket has no SO_KEEPALIVE, and a reader gives the keepalive of the kernel no bound.\",\n },\n} satisfies Machine);\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { NODE_TIMER_EARLY, nodeTimerLateness, undiciFastEarly, undiciFastLateness } from \"./timers.ts\";\n\n/**\n * This document is the socket of an HTTP/1.1 `Client` of undici 8.12.2, over its Linux TCP socket.\n * Each fact comes from the published package at 8.12.2, with the file and the line.\n *\n * The keep-alive timeout comes from the hint of the server less a threshold, capped by a maximum.\n * The headers and body timeouts use the fast timers of undici, which count in ticks of 499 ms. The\n * client sends no request again by itself. A request that it did not write yet goes on the next\n * connection.\n *\n * The keep-alive timer arms on the event loop of the program, in the check phase after the parse\n * of the reply. The time from the last segment that the kernel received to that arm is the time of\n * the program. No source bounds it, and this document does not hold it. The race of the cells adds\n * it from a calibration (`HANDLING` in `packages/cells/src/http/race.ts`).\n */\nexport const UNDICI_CLIENT: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"undici-client-h1\",\n title: \"The socket of an HTTP/1.1 Client of undici 8.12.2\",\n layer: \"driver\",\n version: \"8.12.2\",\n conditions: { undici: \"8.12.2\", node: \"24.21.0\", pipelining: \"1\" },\n sources: [\n {\n ref: \"undici 8.12.2 lib/dispatcher/client.js:309-319 (keepAliveTimeout 4000, keepAliveMaxTimeout 600000, keepAliveTimeoutThreshold 2000, bodyTimeout and headersTimeout 300000)\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/dispatcher/client-h1.js:705-721 onHeadersComplete: the timeout is min(hint - threshold, maximum), no reuse when it is 0 or less, and keepAliveTimeout without a hint; lib/core/util.js:390-398 (the hint in ms)\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/dispatcher/client-h1.js:213-223 and :262-288: a native Node timer for keep-alive, the fast timers for the headers and the body\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/dispatcher/client-h1.js:785-852 onMessageComplete: a reply that ends the connection destroys the socket in the parse (:827-841), else one setImmediate (:842-846). Then lib/dispatcher/client.js:646-676 and client-h1.js:1111-1163 resumeH1 arm the keep-alive timer (:1151-1154). After the write of a request, the headers timer\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/dispatcher/client-h1.js:1087-1106 and :1125-1141: before a request on a used idle socket, the client yields to the check phase, thus a FIN or a reset already received closes the socket first\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/dispatcher/client-h1.js:855-876 onParserTimeout, :990-1007 onHttpSocketError, :1013-1025 onHttpSocketEnd (other side closed) and :1027-1072 onHttpSocketClose (the request at the head fails, the others wait for the next connection)\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/util/timers.js:30-207 the fast timers: a tick each 499 ms, a clock that adds 499 at each tick\",\n rung: \"implemented\",\n },\n {\n ref: \"undici 8.12.2 lib/core/connect.js:68-75 and :141-149 (connect timeout 10000, setKeepAlive(true, 60000), setNoDelay)\",\n rung: \"implemented\",\n },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n CONNECTING: {},\n BUSY: { note: \"a request is written and its reply is not complete\" },\n IDLE: { note: \"a reply is complete and the keep-alive timer is armed\" },\n CLOSED: { final: true },\n },\n events: {\n \"req.dispatch\": { kind: \"app\" },\n \"socket.connect\": { kind: \"local\" },\n \"tx.request\": { kind: \"tx\", note: \"the client wrote the request and resumes\" },\n \"rx.headers\": { kind: \"rx\" },\n \"rx.body\": { kind: \"rx\", note: \"a chunk of the body: it refreshes the body timer\" },\n \"resp.complete\": {\n kind: \"local\",\n note: \"onMessageComplete, in the parse of the reply on the event loop. It comes after the last segment by the handling time of the program\",\n },\n \"rx.fin\": { kind: \"peer\" },\n \"rx.rst\": { kind: \"peer\" },\n \"timer.keep-alive\": { kind: \"timer\" },\n \"timer.headers\": { kind: \"timer\" },\n \"timer.body\": { kind: \"timer\" },\n \"timer.connect\": { kind: \"timer\" },\n \"socket.error\": { kind: \"local\" },\n },\n knobs: {\n keepAliveTimeout: { key: \"undici Client keepAliveTimeout\", scope: \"client\", unit: \"ms\", default: 4000 },\n keepAliveMaxTimeout: { key: \"undici Client keepAliveMaxTimeout\", scope: \"client\", unit: \"ms\", default: 600000 },\n keepAliveTimeoutThreshold: {\n key: \"undici Client keepAliveTimeoutThreshold\",\n scope: \"client\",\n unit: \"ms\",\n default: 2000,\n },\n headersTimeout: { key: \"undici Client headersTimeout\", scope: \"client\", unit: \"ms\", default: 300000 },\n bodyTimeout: { key: \"undici Client bodyTimeout\", scope: \"client\", unit: \"ms\", default: 300000 },\n connectTimeout: { key: \"undici Client connect.timeout\", scope: \"client\", unit: \"ms\", default: 10000 },\n keepAliveInitialDelay: {\n key: \"undici Client connect.keepAliveInitialDelay\",\n scope: \"client\",\n unit: \"ms\",\n default: 60000,\n },\n hint: {\n key: \"Keep-Alive timeout= of the server\",\n scope: \"connection\",\n unit: \"s\",\n default: null,\n note: \"without a hint, the timeout is keepAliveTimeout\",\n },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"the HZ of the kernel, for the step of the coarse loop clock of libuv (timers.ts)\",\n },\n },\n timers: {\n keep_alive: {\n duration: { expr: \"min(hint * 1000 - keepAliveTimeoutThreshold, keepAliveMaxTimeout)\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"min(hint * 1000 - keepAliveTimeoutThreshold, keepAliveMaxTimeout)\"),\n early: NODE_TIMER_EARLY,\n arms: [\"resp.complete\", \"enter:IDLE\"],\n cancels: [\"req.dispatch\"],\n fires: \"timer.keep-alive\",\n note: \"setTimeout(onParserTimeout, delay) with unref: a native Node timer. It arms in resumeH1, in the check phase after the parse of the reply. That comes in the handling time of the program after the last segment (race.ts)\",\n },\n headers: {\n duration: { knob: \"headersTimeout\", unit: \"ms\" },\n lateness: undiciFastLateness(\"headersTimeout\"),\n early: undiciFastEarly(\"headersTimeout\"),\n arms: [\"tx.request\", \"enter:BUSY\"],\n cancels: [\"rx.headers\"],\n fires: \"timer.headers\",\n },\n body: {\n duration: { knob: \"bodyTimeout\", unit: \"ms\" },\n lateness: undiciFastLateness(\"bodyTimeout\"),\n early: undiciFastEarly(\"bodyTimeout\"),\n arms: [\"rx.headers\", \"rx.body\"],\n cancels: [\"resp.complete\"],\n fires: \"timer.body\",\n },\n connect: {\n duration: { knob: \"connectTimeout\", unit: \"ms\" },\n arms: [\"enter:CONNECTING\"],\n cancels: [\"socket.connect\"],\n fires: \"timer.connect\",\n },\n },\n realizes: {\n \"systems.mechanism.pool-idle-expiry\": { timer: \"keep_alive\" },\n \"systems.mechanism.request-timeout\": { timer: \"headers\" },\n \"systems.mechanism.connect-bound\": { timer: \"connect\" },\n },\n transitions: [\n { id: \"un.connect\", from: \"ABSENT\", to: \"CONNECTING\", on: \"req.dispatch\" },\n { id: \"un.connected\", from: \"CONNECTING\", to: \"BUSY\", on: \"socket.connect\" },\n {\n id: \"un.idle\",\n from: \"BUSY\",\n to: \"IDLE\",\n on: \"resp.complete\",\n guard: \"the reply keeps the connection, and min(hint - threshold, maximum) > 0\",\n timer: \"keep_alive\",\n source: \"client-h1.js:705-717, :842-846\",\n },\n {\n id: \"un.no-reuse\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: \"resp.complete\",\n guard: \"hint * 1000 - keepAliveTimeoutThreshold is 0 or less, or the reply closes the connection\",\n emits: [\"tx.fin\"],\n source: \"client-h1.js:709-711, :832-841\",\n },\n {\n id: \"un.reuse\",\n from: \"IDLE\",\n to: \"BUSY\",\n on: \"req.dispatch\",\n guard: \"the socket is still open after the yield to the check phase\",\n source: \"client-h1.js:1087-1106, :1125-1141\",\n },\n {\n id: \"un.expire\",\n from: \"IDLE\",\n to: \"CLOSED\",\n on: \"timer.keep-alive\",\n timer: \"keep_alive\",\n emits: [\"tx.fin\"],\n source: \"client-h1.js:872-875\",\n },\n {\n id: \"un.peer-closed\",\n from: \"IDLE\",\n to: \"CLOSED\",\n on: [\"rx.fin\", \"rx.rst\", \"socket.error\"],\n note: \"no request fails: the next request opens a new connection\",\n source: \"client-h1.js:1013-1025, :1065\",\n },\n {\n id: \"un.other-side-closed\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: \"rx.fin\",\n errno: \"UND_ERR_SOCKET\",\n note: \"SocketError: other side closed. The request at the head fails\",\n source: \"client-h1.js:1013-1025, :1057-1063\",\n },\n {\n id: \"un.reset\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: [\"rx.rst\", \"socket.error\"],\n errno: \"ECONNRESET\",\n note: \"the error of the socket, with its own code\",\n source: \"client-h1.js:990-1007, :1057-1063\",\n },\n {\n id: \"un.headers-timeout\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: \"timer.headers\",\n timer: \"headers\",\n errno: \"UND_ERR_HEADERS_TIMEOUT\",\n source: \"client-h1.js:863-867\",\n },\n {\n id: \"un.body-timeout\",\n from: \"BUSY\",\n to: \"CLOSED\",\n on: \"timer.body\",\n timer: \"body\",\n errno: \"UND_ERR_BODY_TIMEOUT\",\n source: \"client-h1.js:868-871\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { CONNECTING: \"SYN_SENT\", BUSY: \"ESTABLISHED\", IDLE: \"ESTABLISHED\" },\n sets: {\n keepidle: { expr: \"floor(keepAliveInitialDelay / 1000)\", unit: \"s\" },\n keepintvl: { const: 1, unit: \"s\" },\n keepcnt: { const: 10, unit: \"count\" },\n },\n ends: \"socket.error\",\n note: \"The connector turns keepalive on with a delay of 60 s, and Node and libuv add 1 s and 10 probes (src/tcp_wrap.cc:215-216). Thus the keepalive sysctls of the namespace do not reach it.\",\n },\n} satisfies Machine);\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the built code of ioredis 6.0.0 as npm has it, under built/.\n// Each line number is a line of that file in the package.\nconst AT = \"ioredis 6.0.0 built\";\n\n/**\n * This document is the Sentinel path of ioredis 6.0.0. It tells how ioredis finds the primary of a\n * group through the Sentinels, loses it, and connects to the new one. The standalone states of\n * `ioredis-status` stay, and a connect asks a Sentinel first. The driver has no timer that watches\n * the group: it moves only when its own connection closes. The failover detector, which\n * subscribes to `+switch-master`, is off by default.\n */\nexport const IOREDIS_SENTINEL: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"ioredis-sentinel\",\n title: \"ioredis 6.0.0 in Sentinel mode: the primary of a group, found through its Sentinels\",\n layer: \"driver\",\n version: \"6.0.0\",\n conditions: { ioredis: \"6.0.0\", mode: \"sentinel\", node: \"24.21.0\" },\n sources: [\n { ref: `${AT}/connectors/SentinelConnector/index.js:46-121 connect (each Sentinel in turn, then sentinelRetryStrategy)`, rung: \"implemented\" },\n { ref: `${AT}/connectors/SentinelConnector/index.js:145-151 resolveMaster (get-master-addr-by-name, then SENTINEL sentinels)`, rung: \"implemented\" },\n { ref: `${AT}/connectors/SentinelConnector/index.js:175-212 connectToSentinel and resolve (one connection for each question, no retry)`, rung: \"implemented\" },\n { ref: `${AT}/connectors/SentinelConnector/index.js:27-39 check (the role of the ready check)`, rung: \"implemented\" },\n { ref: `${AT}/connectors/SentinelConnector/FailoverDetector.js:6-43 (+switch-master, only with failoverDetector)`, rung: \"implemented\" },\n { ref: `${AT}/redis/RedisOptions.js:9-57 (the defaults)`, rung: \"implemented\" },\n { ref: `${AT}/redis/event_handler.js:294-355 closeHandler (retryStrategy, then maxRetriesPerRequest flushes the queue)`, rung: \"implemented\" },\n { ref: `${AT}/redis/event_handler.js:364-449 readyHandler (retryAttempts back to 0, the resend, the offline queue)`, rung: \"implemented\" },\n { ref: `${AT}/Redis.js:123-240 _connect (connectTimeout, keepAlive) and :379-405 sendCommand (the offline queue)`, rung: \"implemented\" },\n { ref: `${AT}/Redis.js:599-605 handleReconnection (reconnectOnError: null, thus a READONLY error goes to the caller)`, rung: \"implemented\" },\n ],\n states: {\n \"[empty]\": { initial: true, pseudo: true },\n resolving: { note: \"a connect: one Sentinel after another, get-master-addr-by-name (SentinelConnector/index.js:50-119)\" },\n connecting: { note: \"the TCP connect to the primary that the Sentinel named\" },\n connect: { note: \"the handshake: HELLO 3, CLIENT SETINFO, then the INFO of the ready check, whose role must be master\" },\n ready: { note: \"writes go to the primary\" },\n close: { note: \"the connection closed: closeHandler (event_handler.js:294-350)\" },\n reconnecting: { note: \"the wait of retryStrategy before the next connect\" },\n end: { final: true },\n },\n events: {\n \"app.connect\": { kind: \"app\" },\n \"sentinel.answer\": { kind: \"local\", note: \"a Sentinel named a primary\" },\n \"sentinel.none\": { kind: \"local\", note: \"no Sentinel answered: sentinelRetryStrategy (SentinelConnector/index.js:51-73)\" },\n \"stream.connect\": { kind: \"local\" },\n \"stream.close\": { kind: \"local\", note: \"a FIN, a reset, a refused connect, a CLIENT KILL, or the connect timeout\" },\n \"handshake.ready\": { kind: \"local\", note: \"the ready check says role:master (event_handler.js:194-210)\" },\n \"handshake.role\": { kind: \"local\", note: \"the ready check says another role: disconnect and connect again (SentinelConnector/index.js:27-39)\" },\n \"timer.retry\": { kind: \"timer\" },\n \"timer.sentinel-retry\": { kind: \"timer\" },\n \"timer.connect-timeout\": { kind: \"timer\" },\n \"local.flush\": { kind: \"local\", note: \"MaxRetriesPerRequestError for each queued command (event_handler.js:337-349)\" },\n \"rx.switch-master\": { kind: \"rx\", note: \"a message on +switch-master: only with failoverDetector (FailoverDetector.js:28-32)\" },\n },\n knobs: {\n connectTimeout: { key: \"ioredis connectTimeout\", scope: \"client\", unit: \"ms\", default: 10000, note: \"RedisOptions.js:9\" },\n disconnectTimeout: { key: \"ioredis disconnectTimeout\", scope: \"client\", unit: \"ms\", default: 2000, note: \"RedisOptions.js:10\" },\n keepAlive: { key: \"ioredis keepAlive\", scope: \"client\", unit: \"ms\", default: 30000, note: \"RedisOptions.js:17: setKeepAlive on the socket of the primary\" },\n maxRetriesPerRequest: {\n key: \"ioredis maxRetriesPerRequest\",\n scope: \"client\",\n unit: \"count\",\n default: 20,\n note: \"RedisOptions.js:57: the queue goes at each close whose count since ready is a multiple of maxRetriesPerRequest + 1\",\n },\n sentinel_retry_step: { key: \"ioredis sentinelRetryStrategy\", scope: \"client\", unit: \"ms\", default: 10, note: \"RedisOptions.js:26-28: min(times × 10, 1000) ms\" },\n sentinel_retry_cap: { key: \"ioredis sentinelRetryStrategy\", scope: \"client\", unit: \"ms\", default: 1000 },\n sentinelReconnect: { key: \"ioredis sentinelReconnectStrategy\", scope: \"client\", unit: \"ms\", default: 60000, note: \"RedisOptions.js:29-35: the detector's own links only\" },\n failoverDetector: { key: \"ioredis failoverDetector\", scope: \"client\", unit: null, default: 0, note: \"RedisOptions.js:40: off\" },\n commandTimeout: { key: \"ioredis commandTimeout\", scope: \"client\", unit: \"ms\", default: null, note: \"unset: a command waits without a limit (Redis.js:368)\" },\n attempt_round_trips: {\n key: \"the round trips of one connect that fails\",\n scope: \"path\",\n unit: \"count\",\n default: 5,\n note: \"a connect to the Sentinel, HELLO with CLIENT SETINFO, get-master-addr-by-name, SENTINEL sentinels, then the connect to the primary\",\n },\n success_round_trips: {\n key: \"the round trips of a connect that succeeds, to its first accepted write\",\n scope: \"path\",\n unit: \"count\",\n default: 9,\n note: \"the five of a failed connect, then HELLO, the INFO of the ready check, and the write itself\",\n },\n rtt: { key: \"the round trip of the network of the group\", scope: \"path\", unit: \"ms\", default: null },\n slack: {\n key: \"the lateness of the event loop of Node for one step\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"an assumption of this document, not a value of ioredis: a timer or a callback of Node that comes late\",\n },\n },\n timers: {\n retry_delay: {\n // min(2 ** (times - 1) × 50, 5000) + floor(random × 200), times = ++retryAttempts (RedisOptions.js:11-16, event_handler.js:326)\n duration: { model: \"ioredis.retry-base\", knobs: [\"fired\"], unit: \"s\" },\n lateness: { expr: \"199 + slack\", unit: \"ms\" },\n arms: [\"stream.close\"],\n fires: \"timer.retry\",\n backoff: { resets: [\"handshake.ready\"] },\n note: \"fired counts the closes since the last ready, from 0: the readyHandler sets retryAttempts to 0 (event_handler.js:367)\",\n },\n attempt: {\n // one connect that fails: each question to a Sentinel is a new connection (SentinelConnector/index.js:197-212)\n duration: { expr: \"attempt_round_trips * rtt\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"timer.retry\"],\n fires: \"stream.close\",\n },\n success: {\n duration: { expr: \"success_round_trips * rtt\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"timer.retry\"],\n fires: \"handshake.ready\",\n },\n connect_timeout: {\n duration: { knob: \"connectTimeout\", unit: \"ms\" },\n arms: [\"enter:connecting\"],\n cancels: [\"stream.connect\"],\n fires: \"timer.connect-timeout\",\n note: \"a connect into a black hole: the socket goes, then stream.close (Redis.js:179-201)\",\n },\n sentinel_retry: {\n duration: { expr: \"min(sentinel_retry_step * (fired + 1), sentinel_retry_cap)\", unit: \"ms\" },\n arms: [\"sentinel.none\"],\n fires: \"timer.sentinel-retry\",\n backoff: { resets: [\"sentinel.answer\"] },\n note: \"only when no Sentinel answers\",\n },\n },\n transitions: [\n { id: \"connect\", from: [\"[empty]\", \"end\"], to: \"resolving\", on: \"app.connect\" },\n { id: \"resolved\", from: \"resolving\", to: \"connecting\", on: \"sentinel.answer\", note: \"the first Sentinel of the list that answers; it moves to the head (SentinelIterator.js)\" },\n { id: \"no-sentinel\", from: \"resolving\", to: \"resolving\", on: \"timer.sentinel-retry\", timer: \"sentinel_retry\" },\n { id: \"socket-up\", from: \"connecting\", to: \"connect\", on: \"stream.connect\" },\n { id: \"attempt-failed\", from: [\"connecting\", \"connect\"], to: \"close\", on: [\"stream.close\", \"timer.connect-timeout\"] },\n { id: \"ready\", from: \"connect\", to: \"ready\", on: \"handshake.ready\" },\n { id: \"wrong-role\", from: \"connect\", to: \"close\", on: \"handshake.role\" },\n { id: \"lost\", from: \"ready\", to: \"close\", on: \"stream.close\", note: \"the commands in flight wait for the resend (event_handler.js:309-316)\" },\n { id: \"detected\", from: \"ready\", to: \"close\", on: \"rx.switch-master\", note: \"only with failoverDetector\" },\n { id: \"retry\", from: \"close\", to: \"reconnecting\", on: \"local.flush\", note: \"a close whose count is a multiple of maxRetriesPerRequest + 1 fails the queue first\" },\n { id: \"wait\", from: \"close\", to: \"reconnecting\", on: \"stream.close\" },\n { id: \"reconnect\", from: \"reconnecting\", to: \"resolving\", on: \"timer.retry\", timer: \"retry_delay\" },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { connecting: \"SYN_SENT\", connect: \"ESTABLISHED\", ready: \"ESTABLISHED\" },\n sets: { keepidle: { expr: \"floor(keepAlive / 1000)\", unit: \"s\" } },\n ends: \"stream.close\",\n note: \"the socket of the primary is a Linux TCP socket with keepalive at keepAlive. A write in flight to a black hole waits for the retransmissions of the kernel\",\n },\n});\n","","","","","","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { z } from \"zod\";\nimport ioredisStatus from \"./ioredis-status.json\" with { type: \"json\" };\nimport linuxTcp from \"./linux-tcp.json\" with { type: \"json\" };\nimport manifestations from \"./manifestations.json\" with { type: \"json\" };\nimport nfConntrackTcp from \"./nf-conntrack-tcp.json\" with { type: \"json\" };\nimport redisClient from \"./redis-client.json\" with { type: \"json\" };\n\n// The documents of the kernel, of Redis and of ioredis are JSON files. The schema of the algebra\n// examines each one at load, and a document that it refuses stops the import.\n\n/** This document is TCP as Linux 6.6 implements it: one full socket, from the source of the kernel and the RFCs. */\nexport const LINUX_TCP: Machine = machineSchema.parse(linuxTcp);\n\n/** 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. */\nexport const NF_CONNTRACK_TCP: Machine = machineSchema.parse(nfConntrackTcp);\n\n/** This document is one client connection as the Redis 8.10.2 server holds it, over its Linux TCP socket. */\nexport const REDIS_CLIENT: Machine = machineSchema.parse(redisClient);\n\n/** This document is the status of one standalone connection of ioredis 6.0.0, over its Linux TCP socket. */\nexport const IOREDIS_STATUS: Machine = machineSchema.parse(ioredisStatus);\n\n/**\n * This map gives, for each manifestation of a failure, the incoming events that continue to arrive\n * at Linux TCP while the failure lasts. A black hole lets nothing through. The kernel of a frozen\n * process continues to send ACKs, thus `rx.ack` arrives.\n */\nexport const MANIFESTATIONS: Readonly<Record<string, readonly string[]>> = z\n .record(z.string(), z.array(z.string()))\n .parse(manifestations);\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is src/mongo/db/repl of MongoDB at the tag r9.0.4, unless a line\n// names another folder. Each line number is a line of that file at that tag.\nconst AT = \"mongodb r9.0.4 src/mongo/db/repl\";\n\n/**\n * This document is the replication of mongod 9.0.4. It gives one member of a replica set, its view\n * of the primary, and the election that it can hold. The states are the states of the member. The\n * timers are the heartbeats, the election timeout, the liveness check of a primary, the vote, the\n * catch-up of a new primary and a step-down.\n *\n * Each member sends a heartbeat to each other member. A heartbeat window is 10 s: in it, a failed\n * request goes again at once, two times at most. A window without a response marks the target\n * DOWN. A secondary starts an election when it hears nothing from the primary for the election\n * timeout and a random offset. A primary steps down when it cannot see a majority for the election\n * timeout.\n *\n * A secondary keeps a silent primary as its sync source until its oplog fetcher gives up. That is\n * two timeouts and a restart: 17 s to 18 s at the defaults. Its reporter keeps a\n * replSetUpdatePosition in flight to that primary for 30 s. Until then, a new primary learns the\n * position of that secondary only from the response to each heartbeat.\n */\nexport const MONGOD_REPL: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"mongod-replication\",\n title: \"mongod 9.0.4 replication: one member of a replica set, its heartbeats, its elections and its step-downs\",\n layer: \"server\",\n version: \"9.0.4\",\n conditions: { mongodb: \"9.0.4\", protocol: \"replication protocol version 1\", members: \"three members, each with one vote and priority 1\" },\n sources: [\n { ref: `${AT}/repl_set_config.idl:74-109 the settings: heartbeatIntervalMillis 2000, heartbeatTimeoutSecs 10, electionTimeoutMillis 10000, catchUpTimeoutMillis -1, catchUpTakeoverDelayMillis 30000`, rung: \"implemented\" },\n { ref: `${AT}/repl_server_parameters.idl:320-328 replElectionTimeoutOffsetLimitFraction 0.15`, rung: \"implemented\" },\n { ref: `${AT}/topology_coordinator.cpp:1058-1101 the heartbeat window and the timeout of each request, :1124-1147 the next heartbeat, :1239-1248 a member DOWN`, rung: \"implemented\" },\n { ref: `${AT}/topology_coordinator.h:62 kMaxHeartbeatRetries 2`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl_heartbeat.cpp:97-111 the random offset, :346-352 a heartbeat from the primary postpones the election, :1215-1271 the election timeout and its offset`, rung: \"implemented\" },\n { ref: `${AT}/data_replicator_external_state_impl.cpp:70-81 an oplog batch that names a primary postpones the election`, rung: \"implemented\" },\n { ref: `${AT}/delayable_timeout_callback.cpp:149-172 the offset changes at most once in its own length`, rung: \"implemented\" },\n { ref: `${AT}/topology_coordinator.cpp:1440-1457 and :1476-1489 the liveness check: a primary that cannot see a majority steps down`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl_heartbeat.cpp:1158-1188 the liveness check runs at the stalest member's last update plus the election timeout`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl_elect_v1.cpp:189-226 the dry run, :268-382 the term, the durable vote and the real vote, :408-468 the win`, rung: \"implemented\" },\n { ref: `${AT}/vote_requester.cpp:96 a vote request times out at min(electionTimeoutMillis, 30 s), :160-177 a majority of yes votes ends the round`, rung: \"implemented\" },\n { ref: `${AT}/topology_coordinator.cpp:3741-3790 a member votes for each candidate whose data is not staler than its own, and only an arbiter refuses one because it sees a primary`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl_catchup.cpp:35-85 the catch-up and its timeout, :110-133 it ends when each other member answered a heartbeat since the win, or failed one, :349-379 the win restarts each heartbeat`, rung: \"implemented\" },\n { ref: `${AT}/topology_coordinator.cpp:3841-3849 and :3910-3932 a restarted heartbeat, and the latest optime that the catch-up waits for`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl.cpp:1490-1570 the end of the drain: a reconfig of the term, then writes, :2580-2588 the hello of a primary that cannot write yet`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl_step_up_step_down.cpp:64-329 replSetStepDown: the wait for a caught-up secondary, the step-down and the hand-off`, rung: \"implemented\" },\n { ref: `${AT}/repl_set_commands.cpp:545-561 stepDownSecs 60 and secondaryCatchUpPeriodSecs 10`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl.idl:18-26 enableElectionHandoff true, and replication_coordinator_impl.cpp:2830-2873 the hand-off: replSetStepUp with skipDryRun`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl.cpp:1516 the reconfig of the term, :4598 and :4750 a new config starts each heartbeat again`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl_heartbeat.cpp:367-376 a heartbeat response that moves a member's optime forward moves the commit point and wakes the writes that wait`, rung: \"implemented\" },\n { ref: `${AT}/oplog_fetcher.cpp:119-133 the awaitData timeout min(electionTimeoutMillis / 2, 30 s), :317-324 the socket timeout adds oplogNetworkTimeoutBufferSeconds, :640-647 the exhaust read`, rung: \"implemented\" },\n { ref: `${AT}/oplog_fetcher.cpp:395-441 an error makes a new cursor while restarts remain, :596-611 the new cursor sets the retried find timeout, :1073-1113 one restart after 5 ms`, rung: \"implemented\" },\n { ref: `${AT}/repl_server_parameters.idl:121-126 oplogRetriedFindMaxSeconds 2, :234-244 oplogFetcherSteadyStateMaxFetcherRestarts 1, :344-351 oplogNetworkTimeoutBufferSeconds 5`, rung: \"implemented\" },\n { ref: \"mongodb r9.0.4 src/mongo/transport/asio/asio_session_impl.cpp:500-527 the timeout of a synchronous session is SO_RCVTIMEO, and src/mongo/client/dbclient_session.cpp:345-349 its connect uses the same timeout\", rung: \"implemented\" },\n { ref: `${AT}/bgsync.cpp:395-447 a member without a sync source waits for new heartbeat data or 1 s (:971-976), and topology_coordinator.cpp:1124-1136 it sends its heartbeats each 500 ms`, rung: \"implemented\" },\n { ref: `${AT}/replication_coordinator_impl.cpp:4947-4972 a member that loses its sync source starts each heartbeat again at once`, rung: \"implemented\" },\n { ref: `${AT}/sync_source_feedback.cpp:37-47 the keepalive of the reporter min(electionTimeoutMillis / 2, 30 s), :39-40 the network timeout 30 s, :99-117 and :134-236 a new reporter only after the old one ends`, rung: \"implemented\" },\n { ref: `${AT}/reporter.cpp:113-117 a reporter ends when its command in flight ends, :119-169 a trigger, :195-228 each replSetUpdatePosition has the network timeout`, rung: \"implemented\" },\n { ref: \"linux v6.6 net/core/sock.c:427-460 SO_RCVTIMEO in jiffies, and kernel/time/timer.c:516-528 the wheel rounds a timer up to the granularity of its level\", rung: \"implemented\" },\n ],\n states: {\n startup: { initial: true, pseudo: true },\n secondary: { note: \"SECONDARY: it replicates from its sync source, and its election timeout runs\" },\n \"dry-run\": { note: \"a dry run: votes are asked in the current term (replication_coordinator_impl_elect_v1.cpp:200-226)\" },\n candidate: { note: \"the real election: a new term, a durable vote for itself, and a vote request to each member\" },\n catchup: { note: \"PRIMARY in catch-up: it waits for a heartbeat answer from each other member, or a failure (log 21359)\" },\n drain: { note: \"PRIMARY in drain mode: the applier ends its buffer, and the hello says secondary (replication_coordinator_impl.cpp:2580-2584)\" },\n primary: { note: \"PRIMARY that accepts writes (log 21331)\" },\n \"stepping-down\": { note: \"replSetStepDown waits for a caught-up secondary, and the hello says not writable (step_up_step_down.cpp:46-52)\" },\n },\n events: {\n \"tx.heartbeat\": { kind: \"tx\", note: \"a heartbeat request, the first of a window or a retry in it\" },\n \"rx.heartbeat\": { kind: \"rx\", note: \"a heartbeat response\" },\n \"rx.primary-heartbeat\": { kind: \"rx\", note: \"a heartbeat response from the primary in the current term\" },\n \"rx.primary-oplog\": { kind: \"rx\", note: \"an oplog batch whose metadata names a primary\" },\n \"rx.member\": { kind: \"rx\", note: \"any message from a member: a heartbeat request or response, or an update of its position\" },\n \"timer.heartbeat\": { kind: \"timer\" },\n \"timer.heartbeat-window\": { kind: \"timer\", note: \"the window ends without a response: the target is DOWN (log 21216)\" },\n \"timer.election\": { kind: \"timer\", note: \"log 4615652: Starting an election\" },\n \"timer.liveness\": { kind: \"timer\", note: \"log 21809: Can't see a majority of the set, relinquishing primary\" },\n \"rx.votes\": { kind: \"rx\", note: \"a majority of yes votes\" },\n \"rx.no-votes\": { kind: \"rx\", note: \"the round ends without a majority\" },\n \"local.caught-up\": { kind: \"local\", note: \"log 21364 or 21368\" },\n \"timer.catchup\": { kind: \"timer\" },\n \"local.drained\": { kind: \"local\", note: \"log 21331: Transition to primary complete\" },\n \"rx.higher-term\": { kind: \"rx\" },\n \"app.step-down\": { kind: \"app\", note: \"replSetStepDown\" },\n \"timer.step-down-wait\": { kind: \"timer\" },\n \"local.secondary-caught-up\": { kind: \"local\" },\n \"app.step-up\": { kind: \"app\", note: \"replSetStepUp, as a hand-off sends it with skipDryRun\" },\n \"timer.catchup-takeover\": { kind: \"timer\" },\n \"timer.step-down-hold\": { kind: \"timer\" },\n \"rx.oplog-batch\": { kind: \"rx\", note: \"a batch of the exhaust stream of the sync source\" },\n \"timer.oplog-read\": { kind: \"timer\", note: \"log 21275: Recreating cursor for oplog fetcher due to error (NetworkTimeout)\" },\n \"local.oplog-restart\": { kind: \"local\", note: \"the fetcher makes a new cursor on the same sync source\" },\n \"timer.oplog-refind\": { kind: \"timer\", note: \"log 21080: Clearing sync source to choose a new one\" },\n \"tx.update-position\": { kind: \"tx\", note: \"a replSetUpdatePosition to the sync source\" },\n \"rx.update-position\": { kind: \"rx\", note: \"the reply to a replSetUpdatePosition\" },\n \"timer.update-position\": { kind: \"timer\", note: \"log 21760: SyncSourceFeedback error sending update\" },\n },\n knobs: {\n heartbeatIntervalMillis: { key: \"settings.heartbeatIntervalMillis\", scope: \"replica set\", unit: \"ms\", default: 2000, note: \"repl_set_config.idl:74-78\" },\n heartbeatTimeoutSecs: { key: \"settings.heartbeatTimeoutSecs\", scope: \"replica set\", unit: \"s\", default: 10, note: \"repl_set_config.idl:79-85\" },\n electionTimeoutMillis: { key: \"settings.electionTimeoutMillis\", scope: \"replica set\", unit: \"ms\", default: 10000, note: \"repl_set_config.idl:86-92\" },\n offset_fraction: {\n key: \"replElectionTimeoutOffsetLimitFraction\",\n scope: \"process\",\n unit: \"count\",\n default: 0.15,\n note: \"repl_server_parameters.idl:320-328: a fraction, thus the offset is less than 0.15 × electionTimeoutMillis\",\n },\n catchUpTimeoutMillis: {\n key: \"settings.catchUpTimeoutMillis\",\n scope: \"replica set\",\n unit: \"ms\",\n default: null,\n note: \"repl_set_config.idl:93-101: -1 at the defaults, which is no bound. 0 skips the catch-up\",\n },\n catchUpTakeoverDelayMillis: { key: \"settings.catchUpTakeoverDelayMillis\", scope: \"replica set\", unit: \"ms\", default: 30000, note: \"repl_set_config.idl:102-109\" },\n secondaryCatchUpPeriodSecs: { key: \"replSetStepDown secondaryCatchUpPeriodSecs\", scope: \"command\", unit: \"s\", default: 10, note: \"repl_set_commands.cpp:553-561\" },\n stepDownSecs: { key: \"replSetStepDown stepDownSecs\", scope: \"command\", unit: \"s\", default: 60, note: \"repl_set_commands.cpp:545-548\" },\n heartbeat_retries: { key: \"kMaxHeartbeatRetries\", scope: \"build\", unit: \"count\", default: 2, note: \"topology_coordinator.h:62\" },\n vote_timeout_max: { key: \"maximumVoteRequestTimeoutMS\", scope: \"build\", unit: \"ms\", default: 30000, note: \"vote_requester.cpp:96\" },\n executor_slack: {\n key: \"the lateness of the replication executor for one step\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"an assumption of this document, not a value of mongod: a callback of the executor that comes late\",\n },\n election_work: {\n key: \"the local work of an election or a step-up\",\n scope: \"process\",\n unit: \"ms\",\n default: 100,\n note: \"an assumption of this document, not a value of mongod: the durable vote, the reconfig of the term and the first oplog entry of a new primary are local writes\",\n },\n rtt: { key: \"the round trip between members\", scope: \"path\", unit: \"ms\", default: null },\n maximumAwaitDataTimeoutMS: { key: \"maximumAwaitDataTimeoutMS\", scope: \"build\", unit: \"ms\", default: 30000, note: \"oplog_fetcher.cpp:119\" },\n oplogNetworkTimeoutBufferSeconds: { key: \"oplogNetworkTimeoutBufferSeconds\", scope: \"process\", unit: \"s\", default: 5, note: \"repl_server_parameters.idl:344-351\" },\n oplogRetriedFindMaxSeconds: { key: \"oplogRetriedFindMaxSeconds\", scope: \"process\", unit: \"s\", default: 2, note: \"repl_server_parameters.idl:121-126\" },\n oplogFetcherSteadyStateMaxFetcherRestarts: {\n key: \"oplogFetcherSteadyStateMaxFetcherRestarts\",\n scope: \"process\",\n unit: \"count\",\n default: 1,\n note: \"repl_server_parameters.idl:234-244: one new cursor after an error, then the fetcher stops\",\n },\n oplog_read_timeout: {\n key: \"the receive timeout of the exhaust read of an oplog fetcher\",\n scope: \"process\",\n unit: \"ms\",\n default: 10000,\n note: \"the value of min(electionTimeoutMillis / 2, maximumAwaitDataTimeoutMS) + oplogNetworkTimeoutBufferSeconds × 1000 (oplog_fetcher.cpp:124-133, :317-324). The model gives it from the settings. The wheel reads it as a knob\",\n },\n syncSourceFeedbackNetworkTimeoutSecs: { key: \"syncSourceFeedbackNetworkTimeoutSecs\", scope: \"build\", unit: \"s\", default: 30, note: \"sync_source_feedback.cpp:39-40\" },\n maximumKeepAliveIntervalMS: { key: \"maximumKeepAliveIntervalMS\", scope: \"build\", unit: \"ms\", default: 30000, note: \"sync_source_feedback.cpp:37\" },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"the build option of the kernel: SO_RCVTIMEO of the fetcher's socket is a timer on its wheel\",\n },\n },\n timers: {\n heartbeat: {\n // the next heartbeat starts heartbeatIntervalMillis after a response or a failed window (topology_coordinator.cpp:1129, :1146)\n duration: { knob: \"heartbeatIntervalMillis\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"rx.heartbeat\", \"timer.heartbeat-window\"],\n fires: \"timer.heartbeat\",\n },\n heartbeat_fast: {\n // a member that is not primary and has no sync source sends its heartbeats more often (topology_coordinator.cpp:1133-1136)\n duration: { expr: \"min(electionTimeoutMillis / 2, heartbeatIntervalMillis / 4)\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"rx.heartbeat\", \"timer.heartbeat-window\"],\n fires: \"timer.heartbeat\",\n note: \"500 ms at the defaults\",\n },\n heartbeat_window: {\n // a window is heartbeatTimeoutSecs from its first request, and each retry gets what is left (topology_coordinator.cpp:1058-1068, :1096-1100)\n duration: { expr: \"heartbeatTimeoutSecs * 1000\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"tx.heartbeat\"],\n cancels: [\"rx.heartbeat\"],\n fires: \"timer.heartbeat-window\",\n note: \"the target is DOWN at the end of a window without a response (topology_coordinator.cpp:1245-1247, member_data.cpp:86-99)\",\n },\n election: {\n // now + electionTimeoutMillis + an offset in [0, fraction × electionTimeoutMillis) (heartbeat.cpp:1249-1253, :97-111)\n duration: { knob: \"electionTimeoutMillis\", unit: \"ms\" },\n lateness: { expr: \"electionTimeoutMillis * offset_fraction + executor_slack\", unit: \"ms\" },\n arms: [\"enter:secondary\", \"rx.primary-heartbeat\", \"rx.primary-oplog\"],\n fires: \"timer.election\",\n note: \"the offset is random, and it changes at most once in its own length (delayable_timeout_callback.cpp:149-158)\",\n },\n liveness: {\n // a member whose last update is older than the election timeout is stale (topology_coordinator.cpp:1444-1449)\n duration: { knob: \"electionTimeoutMillis\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"enter:primary\", \"rx.member\"],\n fires: \"timer.liveness\",\n note: \"a primary steps down when the stale members leave it without a majority (topology_coordinator.cpp:1452-1455)\",\n },\n vote_request: {\n duration: { expr: \"min(electionTimeoutMillis, vote_timeout_max)\", unit: \"ms\" },\n arms: [\"enter:dry-run\", \"enter:candidate\"],\n cancels: [\"rx.votes\"],\n fires: \"rx.no-votes\",\n note: \"a majority of yes votes ends the round before it (vote_requester.cpp:160-177)\",\n },\n catchup: {\n duration: { knob: \"catchUpTimeoutMillis\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"enter:catchup\"],\n cancels: [\"local.caught-up\"],\n fires: \"timer.catchup\",\n note: \"no bound at -1, and no catch-up at 0 (catchup.cpp:48-75)\",\n },\n catchup_takeover: {\n duration: { knob: \"catchUpTakeoverDelayMillis\", unit: \"ms\" },\n arms: [\"rx.heartbeat\"],\n cancels: [\"local.caught-up\"],\n fires: \"timer.catchup-takeover\",\n note: \"a secondary that is ahead of a primary in catch-up takes over after this delay (heartbeat.cpp:501-515)\",\n },\n step_down_wait: {\n duration: { knob: \"secondaryCatchUpPeriodSecs\", unit: \"s\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"app.step-down\"],\n cancels: [\"local.secondary-caught-up\"],\n fires: \"timer.step-down-wait\",\n note: \"the wait of replSetStepDown for an electable secondary at the primary's optime (step_up_step_down.cpp:197-292)\",\n },\n step_down_hold: {\n duration: { knob: \"stepDownSecs\", unit: \"s\" },\n arms: [\"app.step-down\"],\n fires: \"timer.step-down-hold\",\n note: \"the old primary cannot be elected in this time (step_up_step_down.cpp:313-315)\",\n },\n oplog_read: {\n // the exhaust stream reads with SO_RCVTIMEO: awaitData and the buffer (oplog_fetcher.cpp:640-647, asio_session_impl.cpp:500-527)\n duration: { expr: \"min(electionTimeoutMillis / 2, maximumAwaitDataTimeoutMS) + oplogNetworkTimeoutBufferSeconds * 1000\", unit: \"ms\" },\n early: { model: \"linux.jiffy\", knobs: [\"hz\"], unit: \"s\" },\n lateness: { model: \"linux.wheel\", knobs: [\"oplog_read_timeout\", \"hz\"], unit: \"s\" },\n arms: [\"rx.oplog-batch\"],\n fires: \"timer.oplog-read\",\n note: \"a kernel timer in jiffies (sock.c:427-460), which the wheel rounds up at the level of its length: up to 512 ms late for 10 s at HZ 1000\",\n },\n oplog_restart: {\n duration: { const: 5, unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"timer.oplog-read\"],\n fires: \"local.oplog-restart\",\n note: \"oplog_fetcher.cpp:1097-1112: the first restart sleeps 5 ms, and the fetcher has one restart\",\n },\n oplog_refind: {\n // the new cursor reads with the retried find timeout and the buffer, and the connect uses it too (oplog_fetcher.cpp:596-611, dbclient_session.cpp:345-349)\n duration: { expr: \"(oplogRetriedFindMaxSeconds + oplogNetworkTimeoutBufferSeconds) * 1000\", unit: \"ms\" },\n lateness: { model: \"linux.wheel\", knobs: [\"oplog_read_timeout\", \"hz\"], unit: \"s\" },\n arms: [\"local.oplog-restart\"],\n cancels: [\"rx.oplog-batch\"],\n fires: \"timer.oplog-refind\",\n note: \"a cut source times out the connect, and a frozen source the read of the find, on the wheel. The wheel at the longer read timeout bounds both. Then the member clears its sync source\",\n },\n feedback_keepalive: {\n duration: { expr: \"min(electionTimeoutMillis / 2, maximumKeepAliveIntervalMS)\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"rx.update-position\"],\n cancels: [\"rx.oplog-batch\"],\n fires: \"tx.update-position\",\n note: \"sync_source_feedback.cpp:45-47: a reporter with no news sends its position again after this time\",\n },\n feedback_update: {\n duration: { knob: \"syncSourceFeedbackNetworkTimeoutSecs\", unit: \"s\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n arms: [\"tx.update-position\"],\n cancels: [\"rx.update-position\"],\n fires: \"timer.update-position\",\n note: \"the network timeout of a replSetUpdatePosition (reporter.cpp:195-228). The reporter ends only when this command ends (reporter.cpp:113-117), and the feedback makes the reporter for a new sync source only then (sync_source_feedback.cpp:99-117)\",\n },\n },\n realizes: {\n // from the start of a silence: the next request goes out up to heartbeatIntervalMillis after the last response, and its window starts then\n \"systems.mechanism.heartbeat-detection-time\": {\n duration: { expr: \"heartbeatIntervalMillis + heartbeatTimeoutSecs * 1000\", unit: \"ms\" },\n lateness: { knob: \"executor_slack\", unit: \"ms\" },\n early: { knob: \"heartbeatIntervalMillis\", unit: \"ms\" },\n note: \"a member is DOWN at the end of a heartbeat window without a response. A silence that starts just before a request is found one window later. One that starts just after a response is found an interval and a window later\",\n },\n \"systems.mechanism.election-timeout\": { timer: \"election\" },\n // how long a leader keeps its role without a majority: the primary steps down at the end of it\n \"systems.mechanism.step-down-window\": { timer: \"liveness\" },\n },\n transitions: [\n { id: \"rs.secondary\", from: \"startup\", to: \"secondary\", on: \"rx.heartbeat\" },\n { id: \"rs.election\", from: \"secondary\", to: \"dry-run\", on: \"timer.election\", timer: \"election\", emits: [\"4615652\"], source: \"replication_coordinator_impl_heartbeat.cpp:1345-1352\" },\n { id: \"rs.step-up\", from: \"secondary\", to: \"candidate\", on: \"app.step-up\", note: \"a hand-off skips the dry run\", source: \"replication_coordinator_impl_elect_v1.cpp:192-198\" },\n { id: \"rs.dry-run-won\", from: \"dry-run\", to: \"candidate\", on: \"rx.votes\", source: \"replication_coordinator_impl_elect_v1.cpp:257-265\" },\n { id: \"rs.dry-run-lost\", from: \"dry-run\", to: \"secondary\", on: \"rx.no-votes\", timer: \"vote_request\", emits: [\"21440\"], source: \"replication_coordinator_impl_elect_v1.cpp:244-246\" },\n {\n id: \"rs.won\",\n from: \"candidate\",\n to: \"catchup\",\n on: \"rx.votes\",\n emits: [\"21450\", \"21359\"],\n note: \"the win restarts each heartbeat, and the catch-up waits for each other member's answer or failure\",\n source: \"replication_coordinator_impl_elect_v1.cpp:435-463, replication_coordinator_impl_catchup.cpp:349-379\",\n },\n { id: \"rs.lost\", from: \"candidate\", to: \"secondary\", on: \"rx.no-votes\", timer: \"vote_request\", emits: [\"21448\"] },\n { id: \"rs.caught-up\", from: \"catchup\", to: \"drain\", on: [\"local.caught-up\", \"timer.catchup\"], emits: [\"21363\"], source: \"replication_coordinator_impl_catchup.cpp:87-133\" },\n { id: \"rs.writable\", from: \"drain\", to: \"primary\", on: \"local.drained\", emits: [\"21331\"], source: \"replication_coordinator_impl.cpp:1490-1570\" },\n { id: \"rs.no-majority\", from: [\"primary\", \"catchup\", \"drain\"], to: \"secondary\", on: \"timer.liveness\", timer: \"liveness\", emits: [\"21809\"], source: \"topology_coordinator.cpp:1440-1457\" },\n { id: \"rs.higher-term\", from: [\"primary\", \"catchup\", \"drain\"], to: \"secondary\", on: \"rx.higher-term\", emits: [\"21475\"], source: \"replication_coordinator_impl_heartbeat.cpp:469-480\" },\n { id: \"rs.step-down\", from: \"primary\", to: \"stepping-down\", on: \"app.step-down\", note: \"writes stop, and the hello says not writable\", source: \"replication_coordinator_impl_step_up_step_down.cpp:46-52, :118-125\" },\n {\n id: \"rs.stepped-down\",\n from: \"stepping-down\",\n to: \"secondary\",\n on: \"local.secondary-caught-up\",\n emits: [\"962660\", \"21347\"],\n note: \"then the hand-off: replSetStepUp with skipDryRun to the best secondary\",\n source: \"replication_coordinator_impl_step_up_step_down.cpp:207-321\",\n },\n { id: \"rs.step-down-failed\", from: \"stepping-down\", to: \"primary\", on: \"timer.step-down-wait\", timer: \"step_down_wait\", errno: \"ExceededTimeLimit\" },\n ],\n observe: {\n \"mongod-log\": {\n fidelity: \"complete\",\n note: \"the JSON log of mongod: id 21358 gives each state change, and the ids of the transitions give the steps between them\",\n states: { SECONDARY: \"secondary\", PRIMARY: \"catchup\" },\n },\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the source of MongoDB at the tag r9.0.4. Each line number is a\n// line of that file at that tag.\nconst AT = \"mongodb r9.0.4 src/mongo\";\n\n/**\n * This document is the hold of mongod 9.0.4 on one client connection, over its socket. `mongod`\n * turns keepalive on for each TCP session. It lowers two keepalive options of the socket to a\n * maximum: the idle time to 300 s and the interval to 1 s. It does not change the probe count.\n * Thus the namespace sysctls give the idle time and the interval only when they are lower, and\n * they always give the count.\n *\n * `mongod` writes no warning about keepalive. A failure to read or to set an option goes to the\n * log at debug level 3 in a release build.\n *\n * An awaitable hello of an exhaust stream waits for a change of the topology or `maxAwaitTimeMS`.\n * Then `mongod` sends the reply, and it starts the next hello of the stream at once.\n */\nexport const MONGOD_SESSION: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"mongod-session\",\n title: \"A client connection as mongod 9.0.4 holds it, over its Linux socket\",\n layer: \"server\",\n version: \"9.0.4\",\n conditions: { mongodb: \"9.0.4\", os: \"linux\", image: \"mongo:9.0.4 (Ubuntu 26.04)\" },\n sources: [\n { ref: `${AT}/transport/asio/asio_session_impl.cpp:156-165 each TCP session: TCP_NODELAY, SO_KEEPALIVE, setSocketKeepAliveParams, failures at debug 3 in a release build`, rung: \"implemented\" },\n { ref: `${AT}/util/net/socket_utils.h:15-16 kMaxKeepIdleSecs 300 and kMaxKeepIntvlSecs 1, :19-22 the defaults of setSocketKeepAliveParams`, rung: \"implemented\" },\n { ref: `${AT}/util/net/socket_utils.cpp:165-196 applyMax: read the option, and set the maximum only when the value is higher, :199-220 TCP_KEEPIDLE and TCP_KEEPINTVL, never TCP_KEEPCNT`, rung: \"implemented\" },\n { ref: `${AT}/util/net/socket_utils.cpp:176-181 and :190-194 the log of a failed read or set, at the severity of the caller`, rung: \"implemented\" },\n { ref: `${AT}/util/net/sock.cpp:135-142 the older socket path: SO_KEEPALIVE, then the same maximums, failures as errors`, rung: \"implemented\" },\n { ref: `${AT}/db/repl/replication_info.cpp:131-143 an awaitable hello waits until now + maxAwaitTimeMS on the precise clock, or a change of the topology`, rung: \"implemented\" },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n CONNECTED: { note: \"a session of the transport layer, with its socket\" },\n GONE: { final: true },\n },\n events: {\n accept: { kind: \"local\" },\n \"peer.fin\": { kind: \"peer\", note: \"a read gives 0 bytes: the client closed\" },\n \"peer.rst\": { kind: \"peer\" },\n \"socket.error\": { kind: \"local\", note: \"a read fails with the error of the socket: the kernel gave up, by keepalive or by its retransmissions\" },\n \"rx.hello\": { kind: \"rx\", note: \"an awaitable hello with exhaustAllowed: the start of a stream\" },\n \"tx.hello-reply\": { kind: \"tx\", note: \"a reply of the stream, after which mongod runs the next hello\" },\n },\n knobs: {\n tcp_keepalive_time: { key: \"net.ipv4.tcp_keepalive_time\", scope: \"netns\", unit: \"s\", default: 7200, note: \"the value of a new socket, which mongod lowers to max_keep_idle\" },\n tcp_keepalive_intvl: { key: \"net.ipv4.tcp_keepalive_intvl\", scope: \"netns\", unit: \"s\", default: 75, note: \"the value of a new socket, which mongod lowers to max_keep_intvl\" },\n tcp_keepalive_probes: { key: \"net.ipv4.tcp_keepalive_probes\", scope: \"netns\", unit: \"count\", default: 9, note: \"mongod does not change it\" },\n max_keep_idle: { key: \"kMaxKeepIdleSecs\", scope: \"build\", unit: \"s\", default: 300, note: \"socket_utils.h:15\" },\n max_keep_intvl: { key: \"kMaxKeepIntvlSecs\", scope: \"build\", unit: \"s\", default: 1, note: \"socket_utils.h:16\" },\n hz: { key: \"CONFIG_HZ\", scope: \"global\", unit: \"Hz\", default: null, note: \"the kernel's build option: the timer wheel rounds the keepalive of mongod\" },\n maxAwaitTimeMS: { key: \"hello maxAwaitTimeMS\", scope: \"command\", unit: \"ms\", default: null, note: \"the field of an awaitable hello: the driver sends its heartbeatFrequencyMS (mongodb monitor.ts:338-371)\" },\n wait_slack: {\n key: \"the lateness of a wait of a command of mongod\",\n scope: \"process\",\n unit: \"ms\",\n default: 20,\n note: \"an assumption of this document, not a value of mongod. In CI, the first reply of a stream after a fault came 1 ms to 10.6 ms after maxAwaitTimeMS (T01.defaults.42, T03.defaults.3)\",\n },\n },\n timers: {\n hello_await: {\n duration: { knob: \"maxAwaitTimeMS\", unit: \"ms\" },\n lateness: { knob: \"wait_slack\", unit: \"ms\" },\n arms: [\"rx.hello\", \"tx.hello-reply\"],\n fires: \"tx.hello-reply\",\n note: \"replication_info.cpp:131-143: with no change of the topology, each reply of the stream comes maxAwaitTimeMS after the last reply, or after the request\",\n },\n },\n realizes: {\n \"systems.mechanism.idle-refresh-interval\": {\n duration: { expr: \"min(tcp_keepalive_time, max_keep_idle)\", unit: \"s\" },\n lateness: { model: \"linux.wheel\", knobs: [\"max_keep_idle\", \"hz\"], unit: \"s\" },\n early: { model: \"linux.jiffy\", knobs: [\"hz\"], unit: \"s\" },\n note: \"the first probe of an idle connection. The lateness is the wheel's at 300 s: at a lower idle time it is the same or longer than the true one\",\n },\n \"systems.mechanism.keepalive-detection-window\": { timer: \"keepalive\" },\n },\n transitions: [\n { id: \"ms.accept\", from: \"ABSENT\", to: \"CONNECTED\", on: \"accept\", source: \"asio_session_impl.cpp:149-165\" },\n { id: \"ms.gone\", from: \"CONNECTED\", to: \"GONE\", on: [\"peer.fin\", \"peer.rst\", \"socket.error\"] },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { CONNECTED: \"ESTABLISHED\" },\n sets: {\n keepidle: { expr: \"min(tcp_keepalive_time, max_keep_idle)\", unit: \"s\" },\n keepintvl: { expr: \"min(tcp_keepalive_intvl, max_keep_intvl)\", unit: \"s\" },\n keepcnt: { knob: \"tcp_keepalive_probes\", unit: \"count\" },\n },\n ends: \"socket.error\",\n note: \"at the Linux defaults the window is 300 s + 9 × 1 s = 309 s, not 300 s + 9 × 75 s: the interval has a maximum too\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the TypeScript source of the npm package mongodb at 7.7.0,\n// under src/. Each line number is a line of that file in the package. Node's own facts are from\n// node v24.21.0, as the ioredis document of this repository cites them.\nconst AT = \"mongodb 7.7.0 src\";\n\n/**\n * This document is the MongoDB Node driver 7.7.0, for one server of a replica set. It gives one\n * connection of the driver by its role, and the timers that act on it. The roles are the monitor\n * of the server, the pool connection that an operation uses, and the wait of an operation for a\n * suitable server. The monitor streams `hello`: the server answers when its topology changes, or\n * after `heartbeatFrequencyMS`. The monitor writes the server off when its socket is silent for\n * `connectTimeoutMS + heartbeatFrequencyMS`.\n *\n * A knob of the driver at 0 has no timer: give it as no bound (`infinite`). This is true of\n * `connectTimeoutMS`, `socketTimeoutMS`, `waitQueueTimeoutMS`, `maxIdleTimeMS` and\n * `serverSelectionTimeoutMS`.\n */\nexport const MONGODB_NODE: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"mongodb-node\",\n title: \"MongoDB Node driver 7.7.0: one server of a replica set, its monitor, its pool and the retry of an operation\",\n layer: \"driver\",\n version: \"7.7.0\",\n conditions: {\n mongodb: \"7.7.0\",\n node: \"24.21.0\",\n topology: \"a replica set, with the streaming monitor (serverMonitoringMode auto, not in a FaaS environment)\",\n timeouts: \"no timeoutMS: the legacy timeout context\",\n },\n sources: [\n { ref: `${AT}/connection_string.ts:804-807 connectTimeoutMS 30000, :850-853 heartbeatFrequencyMS 10000, :934-937 minHeartbeatFrequencyMS 500`, rung: \"implemented\" },\n { ref: `${AT}/connection_string.ts:1100-1103 serverSelectionTimeoutMS 30000, :1107-1111 socketTimeoutMS 0, :1178-1182 waitQueueTimeoutMS 0`, rung: \"implemented\" },\n { ref: `${AT}/connection_string.ts:896-898 maxConnecting 2, :906-908 maxIdleTimeMS 0, :910-912 maxPoolSize 100, :930-933 minPoolSize 0, :1075-1082 retryReads and retryWrites true, :1089-1091 serverMonitoringMode auto`, rung: \"implemented\" },\n { ref: `${AT}/cmap/connect.ts:291 DEFAULT_KEEP_ALIVE_INITIAL_DELAY_MS 120000, :336-338 keepAlive and noDelay, :378-417 makeSocket: setKeepAlive, setNoDelay, setTimeout(connectTimeoutMS), :432-438 the connect timeout`, rung: \"implemented\" },\n { ref: `${AT}/cmap/connect.ts:117-120 the handshake reads with socketTimeoutMS = connectTimeoutMS`, rung: \"implemented\" },\n { ref: `${AT}/sdam/monitor.ts:245-259 the streaming protocol, :338-371 the awaitable hello: maxAwaitTimeMS = heartbeatFrequencyMS, socketTimeoutMS = connectTimeoutMS + maxAwaitTimeMS`, rung: \"implemented\" },\n { ref: `${AT}/sdam/monitor.ts:273-293 a failed heartbeat: ResetPool, and InterruptInUseConnections for a timeout`, rung: \"implemented\" },\n { ref: `${AT}/sdam/monitor.ts:175-194 reset: the next check after heartbeatFrequencyMS, :609-636 wake: no check sooner than minHeartbeatFrequencyMS, :668-691 the next check after heartbeatFrequencyMS`, rung: \"implemented\" },\n { ref: `${AT}/sdam/monitor.ts:490-565 the RTT pinger: its own connection, a hello each heartbeatFrequencyMS, no socket timeout`, rung: \"implemented\" },\n { ref: `${AT}/cmap/connection.ts:328-334 a socket timeout, 1 ms later, is a MongoNetworkTimeoutError, :461-505 the socket timeout of a command, set again at each reply`, rung: \"implemented\" },\n { ref: `${AT}/sdam/server.ts:186 resetServer, :390-444 handleError, :450-515 decorateCommandError, :532-546 markServerUnknown: a network error that is not a timeout resets the monitor`, rung: \"implemented\" },\n { ref: `${AT}/sdam/topology.ts:559 the selection timeout, :568-572 and :635-664 MongoServerSelectionError, :862-888 updateServers clears the pool, :1082-1089 a waiting selection wakes each monitor`, rung: \"implemented\" },\n { ref: `${AT}/sdam/topology_description.ts:458-467 a primary that another primary replaces is Unknown, and nothing clears its pool`, rung: \"implemented\" },\n { ref: `${AT}/cmap/connection_pool.ts:417-468 clear, :475-481 interruptInUseConnections: PoolClearedOnNetworkError, :584 a connection idle for maxIdleTimeMS is perished at the next check-out`, rung: \"implemented\" },\n { ref: `${AT}/cmap/errors.ts:37-84 PoolClearedError and PoolClearedOnNetworkError, with the label PoolRequestedRetry`, rung: \"implemented\" },\n { ref: `${AT}/operations/execute_operation.ts:252-279 two attempts for a retryable read or write, :375-380 the retry selects a server again, :442-445 canRetry`, rung: \"implemented\" },\n { ref: `${AT}/error.ts:1377-1394 the retryable codes, :1431-1436 isRetryableWriteError: RetryableWriteError or PoolRequestedRetry`, rung: \"implemented\" },\n { ref: `${AT}/timeout.ts:362-372 the legacy timeout context: the selection timeout, and no check-out timeout at waitQueueTimeoutMS 0`, rung: \"implemented\" },\n { ref: \"node v24.21.0 lib/net.js:846-888 (setKeepAlive truncates the delay to whole seconds) and src/tcp_wrap.cc:204-221 (interval 1 s and count 10 when none is given)\", rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"before the driver opens a connection to the server\" },\n connecting: { note: \"the TCP connect of a connection of any role, with the socket timeout connectTimeoutMS (connect.ts:417)\" },\n handshake: { note: \"the first hello of a new connection: a read with socketTimeoutMS = connectTimeoutMS (connect.ts:117-120)\" },\n streaming: { note: \"the monitor waits for the next hello reply of an exhaust stream (monitor.ts:338-371)\" },\n waiting: { note: \"the monitor waits for its next check: heartbeatFrequencyMS, or minHeartbeatFrequencyMS on a request (monitor.ts:609-691)\" },\n pooled: { note: \"a pool connection that no operation uses\" },\n \"in-use\": { note: \"a pool connection with an operation in flight: its read has socketTimeoutMS, 0 at the defaults (connection.ts:461-465)\" },\n selecting: { note: \"an operation waits for a suitable server, for serverSelectionTimeoutMS (topology.ts:559-572)\" },\n retrying: { note: \"the second attempt of a retryable operation, after a new selection (execute_operation.ts:375-380)\" },\n closed: { final: true, note: \"the connection ends, or the operation fails to the application\" },\n },\n events: {\n \"app.operation\": { kind: \"app\", note: \"an operation selects a server and checks out a connection\" },\n \"socket.connect\": { kind: \"local\" },\n \"socket.error\": { kind: \"local\", note: \"the socket ends: a FIN, a reset, or an error from the kernel (ETIMEDOUT, EHOSTUNREACH)\" },\n \"rx.hello\": { kind: \"rx\", note: \"a hello reply to the monitor\" },\n \"rx.reply\": { kind: \"rx\", note: \"the reply to the operation\" },\n \"timer.connect-timeout\": { kind: \"timer\" },\n \"timer.handshake-timeout\": { kind: \"timer\" },\n \"timer.stream-timeout\": { kind: \"timer\", note: \"the monitor socket was silent for connectTimeoutMS + heartbeatFrequencyMS: MongoNetworkTimeoutError\" },\n \"timer.socket-timeout\": { kind: \"timer\" },\n \"timer.check\": { kind: \"timer\", note: \"the next check of the monitor\" },\n \"timer.selection-timeout\": { kind: \"timer\", note: \"MongoServerSelectionError\" },\n \"timer.checkout-timeout\": { kind: \"timer\", note: \"WaitQueueTimeoutError\" },\n \"local.interrupt\": { kind: \"local\", note: \"the pool interrupts each connection in use: PoolClearedOnNetworkError\" },\n \"local.suitable\": { kind: \"local\", note: \"a server description suits the selection: a primary for a write\" },\n \"local.newer-primary\": { kind: \"local\", note: \"a hello from another member with a newer electionId\" },\n },\n knobs: {\n connectTimeoutMS: { key: \"mongodb connectTimeoutMS\", scope: \"client\", unit: \"ms\", default: 30000, off: 0, note: \"connection_string.ts:804-807. 0 is no timeout, thus also no stream timeout (monitor.ts:353)\" },\n heartbeatFrequencyMS: { key: \"mongodb heartbeatFrequencyMS\", scope: \"client\", unit: \"ms\", default: 10000, note: \"connection_string.ts:850-853: the period of the monitor, and the maxAwaitTimeMS of its hello\" },\n minHeartbeatFrequencyMS: { key: \"mongodb minHeartbeatFrequencyMS\", scope: \"client\", unit: \"ms\", default: 500, note: \"connection_string.ts:934-937\" },\n serverSelectionTimeoutMS: { key: \"mongodb serverSelectionTimeoutMS\", scope: \"client\", unit: \"ms\", default: 30000, note: \"connection_string.ts:1100-1103\" },\n socketTimeoutMS: { key: \"mongodb socketTimeoutMS\", scope: \"client\", unit: \"ms\", default: 0, off: 0, note: \"connection_string.ts:1107-1111. 0 is no timeout\" },\n waitQueueTimeoutMS: { key: \"mongodb waitQueueTimeoutMS\", scope: \"client\", unit: \"ms\", default: 0, off: 0, note: \"connection_string.ts:1178-1182 and timeout.ts:368-372. 0 is no timeout\" },\n maxIdleTimeMS: { key: \"mongodb maxIdleTimeMS\", scope: \"client\", unit: \"ms\", default: 0, note: \"connection_string.ts:906-908 and connection_pool.ts:584. 0 is no limit\" },\n maxPoolSize: { key: \"mongodb maxPoolSize\", scope: \"client\", unit: \"count\", default: 100, note: \"connection_string.ts:910-912\" },\n minPoolSize: { key: \"mongodb minPoolSize\", scope: \"client\", unit: \"count\", default: 0, note: \"connection_string.ts:930-933\" },\n maxConnecting: { key: \"mongodb maxConnecting\", scope: \"client\", unit: \"count\", default: 2, note: \"connection_string.ts:896-898\" },\n keepAliveInitialDelay: { key: \"mongodb keepAliveInitialDelay\", scope: \"client\", unit: \"ms\", default: 120000, note: \"connect.ts:291 and :415: setKeepAlive(true, delay) on each socket\" },\n node_keepalive_interval: { key: \"node net.Socket setKeepAlive interval\", scope: \"client\", unit: \"s\", default: 1, note: \"Node passes 1 s to libuv when setKeepAlive gets no interval, as the driver gives none\" },\n node_keepalive_count: { key: \"node net.Socket setKeepAlive count\", scope: \"client\", unit: \"count\", default: 10, note: \"Node passes 10 to libuv when setKeepAlive gets no count, as the driver gives none\" },\n retryWrites: { key: \"mongodb retryWrites\", scope: \"client\", unit: null, default: 1, note: \"connection_string.ts:1079-1082: on\" },\n retryReads: { key: \"mongodb retryReads\", scope: \"client\", unit: null, default: 1, note: \"connection_string.ts:1075-1078: on\" },\n attempts: { key: \"the attempts of a retryable operation\", scope: \"client\", unit: \"count\", default: 2, note: \"execute_operation.ts:272-279: one try and one retry, without timeoutMS\" },\n slack: {\n key: \"the lateness of the event loop of Node for one step\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"an assumption of this document, not a value of the driver: a timer or a callback of Node that comes late\",\n },\n rtt: { key: \"the round trip to the server\", scope: \"path\", unit: \"ms\", default: null },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"the build option of the kernel: the keepalive of the driver is the kernel's, thus the timer wheel rounds its firings\",\n },\n },\n timers: {\n stream_timeout: {\n // the exhaust hello reads with socketTimeoutMS = connectTimeoutMS + maxAwaitTimeMS (monitor.ts:351-356),\n // and each reply sets the timeout again (connection.ts:492-501). The timeout is 1 ms later (connection.ts:328-334)\n duration: { expr: \"connectTimeoutMS + heartbeatFrequencyMS\", unit: \"ms\" },\n early: { const: 1, unit: \"ms\" },\n lateness: { expr: \"1 + slack\", unit: \"ms\" },\n arms: [\"enter:streaming\", \"rx.hello\"],\n cancels: [\"socket.error\"],\n fires: \"timer.stream-timeout\",\n note: \"the write-off of a silent server: the monitor fails its heartbeat with MongoNetworkTimeoutError, clears the pool and interrupts each connection in use\",\n },\n connect_timeout: {\n duration: { knob: \"connectTimeoutMS\", unit: \"ms\" },\n lateness: { expr: \"1 + slack\", unit: \"ms\" },\n arms: [\"enter:connecting\"],\n cancels: [\"socket.connect\", \"socket.error\"],\n fires: \"timer.connect-timeout\",\n note: \"connect.ts:417 and :432-438: the socket timeout of the TCP connect. The kernel's SYN retransmissions go on under it\",\n },\n handshake_timeout: {\n duration: { knob: \"connectTimeoutMS\", unit: \"ms\" },\n lateness: { expr: \"1 + slack\", unit: \"ms\" },\n arms: [\"enter:handshake\"],\n cancels: [\"rx.hello\", \"socket.error\"],\n fires: \"timer.handshake-timeout\",\n note: \"connect.ts:117-120: the first hello of a connection reads with socketTimeoutMS = connectTimeoutMS\",\n },\n socket_timeout: {\n duration: { knob: \"socketTimeoutMS\", unit: \"ms\" },\n lateness: { expr: \"1 + slack\", unit: \"ms\" },\n arms: [\"enter:in-use\"],\n cancels: [\"rx.reply\", \"socket.error\", \"local.interrupt\"],\n fires: \"timer.socket-timeout\",\n note: \"connection.ts:461-465: no bound at the defaults, thus an operation in flight waits for the kernel or for an interruption\",\n },\n check_period: {\n duration: { knob: \"heartbeatFrequencyMS\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:waiting\"],\n fires: \"timer.check\",\n note: \"monitor.ts:190-193 and :668-691: after a check that failed, or after a reset, the next check waits heartbeatFrequencyMS. A waiting selection wakes it after minHeartbeatFrequencyMS (monitor.ts:629-633)\",\n },\n selection_timeout: {\n duration: { knob: \"serverSelectionTimeoutMS\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:selecting\", \"enter:retrying\"],\n cancels: [\"local.suitable\"],\n fires: \"timer.selection-timeout\",\n note: \"topology.ts:559, :568-572: each selection, the retry's too, waits serverSelectionTimeoutMS\",\n },\n checkout_timeout: {\n duration: { knob: \"waitQueueTimeoutMS\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"app.operation\"],\n cancels: [\"socket.connect\"],\n fires: \"timer.checkout-timeout\",\n note: \"timeout.ts:368-372: no bound at the defaults\",\n },\n interrupt: {\n duration: { const: 0, unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"timer.stream-timeout\", \"timer.connect-timeout\", \"timer.handshake-timeout\"],\n fires: \"local.interrupt\",\n note: \"connection_pool.ts:463-481: a heartbeat that fails with a timeout clears the pool and interrupts each connection in use, one microtask later\",\n },\n },\n realizes: {\n \"systems.mechanism.connect-bound\": { timer: \"connect_timeout\" },\n \"systems.mechanism.driver-writeoff-time\": { timer: \"stream_timeout\" },\n \"systems.mechanism.heartbeat-interval\": { timer: \"check_period\" },\n // an operation that fails on a server is retried once, and the retry selects again with a new serverSelectionTimeoutMS\n \"systems.mechanism.client-retry-window\": { timer: \"selection_timeout\" },\n \"systems.mechanism.idle-refresh-interval\": {\n duration: { expr: \"floor(keepAliveInitialDelay / 1000)\", unit: \"s\" },\n lateness: { model: \"linux.wheel\", knobs: [\"keepAliveInitialDelay\", \"hz\"], unit: \"s\" },\n early: { model: \"linux.jiffy\", knobs: [\"hz\"], unit: \"s\" },\n note: \"the first keepalive probe of an idle pool connection: the delay in whole seconds, rounded up on the timer wheel of the kernel\",\n },\n },\n transitions: [\n { id: \"open\", from: \"[none]\", to: \"connecting\", on: \"app.operation\", source: \"connect.ts:378-417\" },\n { id: \"connected\", from: \"connecting\", to: \"handshake\", on: \"socket.connect\", source: \"connect.ts:427-428\" },\n {\n id: \"connect-timed-out\",\n from: \"connecting\",\n to: \"waiting\",\n on: \"timer.connect-timeout\",\n timer: \"connect_timeout\",\n errno: \"MongoNetworkTimeoutError\",\n emits: [\"local.interrupt\"],\n note: \"a timeout of the monitor's connect interrupts each connection in use, as a stream timeout does\",\n source: \"connect.ts:432-438, monitor.ts:418-422\",\n },\n { id: \"connect-failed\", from: [\"connecting\", \"handshake\"], to: \"waiting\", on: \"socket.error\", errno: \"MongoNetworkError\", source: \"connect.ts:429-431\" },\n {\n id: \"handshake-timed-out\",\n from: \"handshake\",\n to: \"waiting\",\n on: \"timer.handshake-timeout\",\n timer: \"handshake_timeout\",\n errno: \"MongoNetworkTimeoutError\",\n emits: [\"local.interrupt\"],\n source: \"connect.ts:117-120, monitor.ts:418-422\",\n },\n { id: \"monitor-up\", from: \"handshake\", to: \"streaming\", on: \"rx.hello\", note: \"the monitor sends the awaitable hello at once (monitor.ts:449-456)\", source: \"monitor.ts:394-417\" },\n { id: \"pool-up\", from: \"handshake\", to: \"pooled\", on: \"rx.hello\" },\n { id: \"hello\", from: \"streaming\", to: \"streaming\", on: \"rx.hello\", note: \"each reply arms the stream timeout again\", source: \"monitor.ts:295-336\" },\n {\n id: \"written-off\",\n from: \"streaming\",\n to: \"waiting\",\n on: \"timer.stream-timeout\",\n timer: \"stream_timeout\",\n errno: \"MongoNetworkTimeoutError\",\n emits: [\"local.interrupt\"],\n note: \"ResetPool and InterruptInUseConnections: the pool interrupts each operation in flight on the server\",\n source: \"monitor.ts:273-293, topology.ts:862-876\",\n },\n {\n id: \"stream-ended\",\n from: \"streaming\",\n to: \"waiting\",\n on: \"socket.error\",\n errno: \"MongoNetworkError\",\n note: \"ResetPool only: the pool does not interrupt an operation in flight. The monitor resets, and checks again after heartbeatFrequencyMS\",\n source: \"monitor.ts:273-293, server.ts:538-540, monitor.ts:175-194\",\n },\n {\n id: \"replaced\",\n from: \"streaming\",\n to: \"streaming\",\n on: \"local.newer-primary\",\n note: \"the description of the old primary is Unknown, its stream goes on, and nothing clears its pool\",\n source: \"topology_description.ts:458-467, topology.ts:862-888\",\n },\n { id: \"check\", from: \"waiting\", to: \"connecting\", on: \"timer.check\", timer: \"check_period\" },\n { id: \"checkout\", from: \"pooled\", to: \"in-use\", on: \"app.operation\" },\n { id: \"replied\", from: \"in-use\", to: \"pooled\", on: \"rx.reply\" },\n { id: \"socket-timed-out\", from: \"in-use\", to: \"closed\", on: \"timer.socket-timeout\", timer: \"socket_timeout\", errno: \"MongoNetworkTimeoutError\" },\n { id: \"interrupted\", from: \"in-use\", to: \"retrying\", on: \"local.interrupt\", errno: \"PoolClearedOnNetworkError\", note: \"a retryable error: the label PoolRequestedRetry\", source: \"connection_pool.ts:475-481, cmap/errors.ts:71-84\" },\n { id: \"op-socket-ended\", from: \"in-use\", to: \"retrying\", on: \"socket.error\", errno: \"MongoNetworkError\", note: \"the driver adds RetryableWriteError, and the server is Unknown\", source: \"server.ts:474-493\" },\n { id: \"selected\", from: [\"selecting\", \"retrying\"], to: \"in-use\", on: \"local.suitable\" },\n { id: \"no-server\", from: [\"selecting\", \"retrying\"], to: \"closed\", on: \"timer.selection-timeout\", timer: \"selection_timeout\", errno: \"MongoServerSelectionError\", source: \"topology.ts:635-664\" },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { connecting: \"SYN_SENT\", handshake: \"ESTABLISHED\", streaming: \"ESTABLISHED\", pooled: \"ESTABLISHED\", \"in-use\": \"ESTABLISHED\" },\n sets: {\n keepidle: { expr: \"floor(keepAliveInitialDelay / 1000)\", unit: \"s\" },\n keepintvl: { knob: \"node_keepalive_interval\", unit: \"s\" },\n keepcnt: { knob: \"node_keepalive_count\", unit: \"count\" },\n },\n ends: \"socket.error\",\n note: \"each socket of the driver is a Linux TCP socket. makeSocket calls setKeepAlive(true, keepAliveInitialDelay), and Node gives libuv the delay in whole seconds with its own interval and count. Thus the keepalive sysctls of the namespace never reach these sockets\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the Java source of HikariCP at the tag HikariCP-7.1.0 (commit\n// e4c04e8b6d33) and of pgjdbc at the tag REL42.7.13 (commit 3297557c6a80). Each line number is a\n// line of that file at its tag. A fact of the JDK (java.net.Socket, the executors) is an\n// assumption of this document, and its note says so.\nconst HK = \"HikariCP-7.1.0 src/main/java/com/zaxxer/hikari\";\nconst PG = \"pgjdbc REL42.7.13 pgjdbc/src/main/java/org/postgresql\";\n\n/**\n * This document is HikariCP 7.1.0 over pgjdbc 42.7.13, for one connection of a pool. It gives the\n * states of the connection, from its creation to its close, and the timers that act on it. The\n * pool makes its connections one at a time, on one thread. At the defaults the pool has a fixed\n * size of 10, thus its idle timer has no effect.\n *\n * HikariCP reads no idle socket. It finds a dead connection only by a check. A borrow checks a\n * connection that was idle for more than 500 ms. The keepalive checks an idle connection each 96 to\n * 120 s from its creation. Each check is `isValid`: pgjdbc sends one Query message with an empty\n * string, with a read timeout of `validationTimeout`. A read timeout or an I/O error closes the\n * socket.\n *\n * pgjdbc sends nothing on an idle connection. Its only read timeout is `socketTimeout`, which is\n * off at the defaults, thus no timer of pgjdbc bounds a statement or the startup. Its connect\n * timeout of 10 s bounds only the TCP connect and the SSLRequest. At sslmode `prefer` (the\n * default), a read timeout in the connect starts one more connect with SSL off, in what remains of\n * the 10 s.\n *\n * The JDK waits for a read or a connect with a timeout in poll(). Linux ends that wait up to 0.1 % of\n * its time late, at most 100 ms: 11 ms for a read timeout of 11 s (run 39109649303).\n *\n * HikariCP closes a connection at once when a statement fails with an SQLState of the class 08. It\n * also closes it for 57P01, 57P02, 57P03 and 0A000. pgjdbc gives 08006 for each I/O error of a\n * statement. Thus a reset, an end of the stream or a give-up of the kernel each close the\n * connection. HikariCP does not send a statement again.\n */\nexport const HIKARICP_PGJDBC: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"hikaricp-pgjdbc\",\n title: \"HikariCP 7.1.0 over pgjdbc 42.7.13: one connection of a pool, its creation, its checks, its statements and its lifetime\",\n layer: \"driver\",\n version: \"7.1.0\",\n conditions: {\n hikaricp: \"7.1.0\",\n pgjdbc: \"42.7.13\",\n client: \"a HikariDataSource with jdbcUrl, at the defaults of HikariCP and pgjdbc unless a knob says otherwise, with no connectionTestQuery\",\n transport: \"TCP to a host and port, at sslmode prefer against a server with no TLS: the server answers the SSLRequest with N, and the connection stays plain\",\n },\n sources: [\n { ref: `${HK}/HikariConfig.java:50-56, :115-134 the defaults: connectionTimeout 30 s, validationTimeout 5 s, idleTimeout 10 min, maxLifetime 30 min, keepaliveTime 2 min, maximumPoolSize 10`, rung: \"implemented\" },\n { ref: `${HK}/HikariConfig.java:120, :1137-1139 minimumIdle is maximumPoolSize when it is not set: a pool of a fixed size`, rung: \"implemented\" },\n { ref: `${HK}/HikariConfig.java:189-200, :351-358 a connectionTimeout of 0 is Integer.MAX_VALUE, and a timeout below 250 ms throws`, rung: \"implemented\" },\n { ref: `${HK}/HikariConfig.java:1101-1152 validateNumerics: a maxLifetime below 30 s is 30 min, a keepaliveTime below 30 s or at maxLifetime or above is off, an idleTimeout below 10 s is 10 min, and an idleTimeout has no effect in a pool of a fixed size`, rung: \"implemented\" },\n { ref: `${HK}/HikariConfig.java:745, :755 the javadoc of keepaliveTime gives 0 as its default, against the code (:55, :128)`, rung: \"documented\" },\n { ref: `${HK}/pool/HikariPool.java:62-64 aliveBypassWindowMs 500, housekeeping.periodMs 30000, lifeTimeVarianceFactor 4 (from 2 to 40)`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:118, :644-656 the housekeeper: one thread, 100 ms after the start and then a fixed delay of 30 s. It also runs each lifetime and keepalive task`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:793-851 each run of the housekeeper: idle eviction only when minimumIdle is below maximumPoolSize, then fillPool`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:490-496 the lifetime of each connection is maxLifetime less a variance of 0 to maxLifetime / lifeTimeVarianceFactor, drawn one time`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:498-504 the keepalive of each connection: a fixed delay of keepaliveTime less a variance of 0 to keepaliveTime / 5, drawn one time, from the creation`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:870-892 the keepalive checks only a connection that it can reserve (not in use): a dead one closes at once`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:853-868, :626-635 the end of a lifetime evicts an idle connection at once, and marks a connection in use, which closes at its return`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:152-193 getConnection: a borrow waits up to connectionTimeout, and a connection idle for more than aliveBypassWindowMs is checked first. A dead one closes, and the borrow goes on in the time that remains`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:183-184, :700-721 the timeout of a borrow: SQLTransientConnectionException 'Connection is not available, request timed out after', with the SQLState of the last failed creation`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:745-787 the creator: one connection at a time, with a backoff from 10 ms to 5000 ms after a failure`, rung: \"implemented\" },\n { ref: `${HK}/pool/HikariPool.java:567-599 checkFailFast: at the start of the pool, one attempt, then a sleep of 1 s after a failure, until initializationFailTimeout passes. Then PoolInitializationException, with the error of the last attempt`, rung: \"implemented\" },\n { ref: `${HK}/HikariConfig.java:126 initializationFailTimeout 1 ms`, rung: \"implemented\" },\n { ref: `${HK}/util/UtilityElf.java:168-191 the adder and the closer each have one thread`, rung: \"implemented\" },\n { ref: `${HK}/pool/PoolBase.java:157-192 isConnectionDead: setNetworkTimeout(validationTimeout), then isValid(validationTimeout in whole seconds, at least 1). An exception or false is a dead connection`, rung: \"implemented\" },\n { ref: `${HK}/pool/PoolBase.java:416-456, :463-493 the setup of a new connection runs under setNetworkTimeout(validationTimeout), then gives back the network timeout of the driver`, rung: \"implemented\" },\n { ref: `${HK}/pool/PoolBase.java:360-408 HikariCP puts no timer around the connect of the driver`, rung: \"implemented\" },\n { ref: `${HK}/pool/PoolBase.java:639-649 and util/DriverDataSource.java:159-163 the login timeout that HikariCP gives goes to DriverManager, for the whole JVM`, rung: \"implemented\" },\n { ref: `${HK}/pool/PoolEntry.java:70, :77-83 lastAccessed changes only at the creation and at each return: a keepalive does not change it`, rung: \"implemented\" },\n { ref: `${HK}/pool/ProxyConnection.java:67-84, :151-186 checkException: the class 08, 0A000, 57P01, 57P02, 57P03, 01002, JZ0C0 and JZ0C1 close the connection at once, and the exception goes to the application`, rung: \"implemented\" },\n { ref: `${HK}/pool/ProxyConnection.java:538-564 a closed proxy throws 'Connection is closed' for each call`, rung: \"implemented\" },\n { ref: `${HK}/util/ClockSource.java:190-213 the clock is System.nanoTime() on Linux`, rung: \"implemented\" },\n { ref: `${PG}/PGProperty.java:205-214 connectTimeout 10 s, :746-755 socketTimeout 0, :441-448 loginTimeout 0, :908-920 tcpKeepAlive false and tcpNoDelay true, :139-148 cancelSignalTimeout 10 s, :586-592 queryTimeout 0, :862-869 sslResponseTimeout 5000 ms`, rung: \"implemented\" },\n { ref: `${PG}/Driver.java:730-740 and PGProperty.java:1046-1048 an unset loginTimeout is 0, thus the login timeout of DriverManager does not apply`, rung: \"derived\" },\n { ref: `${PG}/core/v3/ConnectionFactoryImpl.java:195-208, :221, :323-324 the connect budget: one deadline for each connect of the attempt, and 1 ms when it is spent`, rung: \"implemented\" },\n { ref: `${PG}/core/v3/ConnectionFactoryImpl.java:221-265 SO_TIMEOUT from socketTimeout, then SO_KEEPALIVE and TCP_NODELAY on each new socket`, rung: \"implemented\" },\n { ref: `${PG}/core/PGStream.java:255-283, :299-302 Socket.connect with the connect budget, and TCP_NODELAY on each socket`, rung: \"implemented\" },\n { ref: `${PG}/jdbc/SslMode.java:63-71 sslmode prefer when it is not set, and ConnectionFactoryImpl.java:646-720 the SSLRequest, with a read timeout of sslResponseTimeout`, rung: \"implemented\" },\n { ref: `${PG}/core/v3/ConnectionFactoryImpl.java:141-159, :365-455 a SocketTimeoutException at prefer connects again with SSL off. A refusal is 'Connection to … refused' and each other I/O error is 'The connection attempt failed.', both 08001`, rung: \"implemented\" },\n { ref: `${PG}/core/v3/ConnectionFactoryImpl.java:473-476, :1076-1121 after the startup, SET application_name as one more simple query`, rung: \"implemented\" },\n { ref: `${PG}/core/v3/QueryExecutorImpl.java:471-475, :2880-2884 and core/QueryExecutorCloseAction.java:42-54 each I/O error of a statement closes the socket with no Terminate: 08006 'An I/O error occurred while sending to the backend.'`, rung: \"implemented\" },\n { ref: `${PG}/core/v3/QueryExecutorImpl.java:2654-2669, :2977-3000 an ErrorResponse is a PSQLException with the SQLState of the server`, rung: \"implemented\" },\n { ref: `${PG}/jdbc/PgConnection.java:1578-1621 and core/v3/QueryExecutorImpl.java:2253-2274 isValid sends a simple Query with the empty string, and true needs its ReadyForQuery`, rung: \"implemented\" },\n { ref: `${PG}/jdbc/PgConnection.java:1788-1806 and core/PGStream.java:738-745 setNetworkTimeout is SO_TIMEOUT`, rung: \"implemented\" },\n { ref: `${PG}/jdbc/PgStatement.java:532-537, :1032-1048 and core/QueryExecutorBase.java:189-230 a query timeout is a task of java.util.Timer that sends a CancelRequest on a new connection`, rung: \"implemented\" },\n { ref: `${PG}/jdbc/PgConnection.java:1048-1053 after a close, each call fails with 'This connection has been closed.', 08003, and :1251-1253 isClosed tells only of a close at this end`, rung: \"implemented\" },\n { ref: `${PG}/core/QueryExecutorCloseAction.java:42-93 a close sends Terminate with a read timeout of at most 1000 ms`, rung: \"implemented\" },\n { ref: \"the JDK: SO_TIMEOUT bounds each blocking read and not a write, and a read that gets data starts its time again\", rung: \"derived\" },\n { ref: \"jdk-21.0.12+8 src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java:172-191, :270-304, :548: a read or a connect with a timeout waits in poll() (Net.poll), with the time that remains\", rung: \"implemented\" },\n { ref: \"linux v6.6 fs/select.c:39-50, :51-95, :902: the timeout of poll() gets a slack of 0.1 % of itself, at most 100 ms (0.5 % for a nice task), and at least the timer slack of the task\", rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"Before the pool creates the connection, or before a borrow gets one\" },\n waiting: { note: \"A borrow of the application waits in the bag for a connection, up to connectionTimeout (HikariPool.java:152-193)\" },\n connecting: { note: \"The TCP connect of a new connection, with TCP_NODELAY and no keepalive at the defaults (PGStream.java:255-283)\" },\n \"start-check\": {\n note: \"The start of the pool after a failed attempt of its check: a sleep of 1 s, then one more attempt while initializationFailTimeout has not passed (HikariPool.java:567-599)\",\n },\n negotiating: { note: \"The SSLRequest of sslmode prefer and its answer, with a read timeout of sslResponseTimeout (ConnectionFactoryImpl.java:646-720)\" },\n startup: {\n note: \"The startup message, the authentication, the first ReadyForQuery and SET application_name. Only socketTimeout bounds a read here, and it is off at the defaults\",\n },\n setup: { note: \"The setup of HikariCP on the new connection, under a read timeout of validationTimeout (PoolBase.java:416-456)\" },\n pooled: { note: \"An idle connection in the bag, which nothing reads (HikariPool.java:870-892)\" },\n checking: { note: \"The check of a borrow: isValid, with a read timeout of validationTimeout. The borrow waits for it (HikariPool.java:166-169)\" },\n probing: { note: \"The keepalive: isValid on a reserved idle connection, with a read timeout of validationTimeout (HikariPool.java:870-892)\" },\n held: { note: \"A connection that the application holds, with no statement in flight. Nothing reads its socket\" },\n querying: { note: \"A statement in flight: pgjdbc waits for its ReadyForQuery, with a read timeout of socketTimeout\" },\n cancelling: { note: \"The query timeout fired, and pgjdbc sent a CancelRequest on a new connection. The statement waits for the answer of the server (PgStatement.java:1032-1048)\" },\n ended: {\n final: true,\n note: \"The pool closed the connection, or its creation failed. A call on its proxy fails with 'Connection is closed' (ProxyConnection.java:538-564)\",\n },\n },\n events: {\n \"app.borrow\": { kind: \"app\", note: \"The application calls getConnection\" },\n \"app.statement\": { kind: \"app\", note: \"The application runs a statement on the connection\" },\n \"app.close\": { kind: \"app\", note: \"The application closes the connection: it goes back to the pool\" },\n \"local.create\": { kind: \"local\", note: \"The adder of the pool starts a new connection: to fill the pool, or for a waiting borrow (HikariPool.java:525-538, :745-787)\" },\n \"local.handout\": { kind: \"local\", note: \"The bag gives an idle connection to a waiting borrow (ConcurrentBag.java:161-205)\" },\n \"socket.connect\": { kind: \"local\" },\n \"rx.ssl-refused\": { kind: \"rx\", note: \"The server answers the SSLRequest with N: the connection stays plain\" },\n \"local.connected\": { kind: \"local\", note: \"The connect of pgjdbc returns: the first ReadyForQuery and the initial queries\" },\n \"local.created\": { kind: \"local\", note: \"The setup of HikariCP ends, and the connection goes into the bag\" },\n \"rx.valid\": { kind: \"rx\", note: \"The EmptyQueryResponse and the ReadyForQuery of isValid\" },\n \"rx.ready-for-query\": { kind: \"rx\", note: \"The ReadyForQuery that ends a statement\" },\n \"rx.error-response\": { kind: \"rx\", note: \"An ErrorResponse of the server: a PSQLException with the SQLState of the server\" },\n \"peer.fin\": { kind: \"peer\", note: \"The server or a middlebox closes the connection: a read gets the end of the stream\" },\n \"peer.rst\": { kind: \"peer\", note: \"A reset of the connection: a read or a write fails\" },\n \"socket.error\": { kind: \"local\", note: \"The socket fails with its own error: a reset, an ICMP error or a give-up of the kernel\" },\n \"tx.ssl-request\": { kind: \"tx\", note: \"The SSLRequest of sslmode prefer\" },\n \"tx.empty-query\": { kind: \"tx\", note: \"The empty simple Query of isValid\" },\n \"tx.cancel\": { kind: \"tx\", note: \"A CancelRequest on a new TCP connection to the server (QueryExecutorBase.java:189-230)\" },\n \"tx.terminate\": { kind: \"tx\", note: \"The Terminate message, then the close of the socket (QueryExecutorCloseAction.java:42-93)\" },\n \"timer.connect-timeout\": { kind: \"timer\", note: \"Socket.connect throws SocketTimeoutException\" },\n \"timer.ssl-response-timeout\": { kind: \"timer\", note: \"The read of the answer to the SSLRequest throws SocketTimeoutException\" },\n \"timer.socket-timeout\": { kind: \"timer\", note: \"A read of a statement throws SocketTimeoutException: pgjdbc closes the socket\" },\n \"timer.validation-timeout\": { kind: \"timer\", note: \"A read of isValid or of the setup throws SocketTimeoutException: pgjdbc closes the socket\" },\n \"timer.query-timeout\": { kind: \"timer\", note: \"The query timeout of the statement: pgjdbc sends a CancelRequest\" },\n \"timer.connection-timeout\": { kind: \"timer\", note: \"The borrow fails: 'Connection is not available, request timed out after'\" },\n \"timer.keepalive\": { kind: \"timer\", note: \"The keepalive task of the connection\" },\n \"timer.max-lifetime\": { kind: \"timer\", note: \"The lifetime of the connection ends\" },\n \"timer.idle\": { kind: \"timer\", note: \"A run of the housekeeper finds the connection idle for more than idleTimeout\" },\n \"timer.start-check\": { kind: \"timer\", note: \"The sleep of 1 s of the start check ends\" },\n },\n knobs: {\n connectionTimeout: {\n key: \"HikariCP connectionTimeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 30000,\n off: 0,\n note: \"HikariConfig.java:50, :189-200: the most that a borrow waits. 0 is Integer.MAX_VALUE, and a value below 250 ms throws\",\n },\n validationTimeout: {\n key: \"HikariCP validationTimeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 5000,\n note: \"HikariConfig.java:51, :351-358: the read timeout of each check and of the setup. isValid gets it in whole seconds, at least 1 (PoolBase.java:157-192)\",\n },\n idleTimeout: {\n key: \"HikariCP idleTimeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 600000,\n off: 0,\n note: \"HikariConfig.java:53, :1141-1151: it has an effect only when minimumIdle is below maximumPoolSize. Then a value below 10 s is 10 min\",\n },\n maxLifetime: {\n key: \"HikariCP maxLifetime\",\n scope: \"client\",\n unit: \"ms\",\n default: 1800000,\n off: 0,\n note: \"HikariConfig.java:54, :1103-1106: a value below 30 s is 30 min\",\n },\n keepaliveTime: {\n key: \"HikariCP keepaliveTime\",\n scope: \"client\",\n unit: \"ms\",\n default: 120000,\n off: 0,\n note: \"HikariConfig.java:55, :1108-1118: a value below 30 s, or at maxLifetime or above, turns the keepalive off\",\n },\n idle_eviction: {\n key: \"the idle eviction time of the pool\",\n scope: \"client\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"A value of this document. The idle timer has an effect only when minimumIdle is below maximumPoolSize: then give idleTimeout. At the defaults the pool has a fixed size, thus 0 (off)\",\n },\n maximumPoolSize: { key: \"HikariCP maximumPoolSize\", scope: \"client\", unit: \"count\", default: 10, note: \"HikariConfig.java:56\" },\n initializationFailTimeout: {\n key: \"HikariCP initializationFailTimeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 1,\n note: \"HikariConfig.java:126. Below 0, the pool does no check at its start. At 0, the pool starts after a failed check. Above 0, the check tries again each 1 s while it has not passed, and then the start fails (HikariPool.java:567-599). At 1 ms, the start fails after one attempt and one sleep\",\n },\n minimumIdle: {\n key: \"HikariCP minimumIdle\",\n scope: \"client\",\n unit: \"count\",\n default: 10,\n note: \"HikariConfig.java:120, :1137-1139: maximumPoolSize when it is not set, thus a pool of a fixed size\",\n },\n lifeTimeVarianceFactor: {\n key: \"the system property com.zaxxer.hikari.lifeTimeVarianceFactor\",\n scope: \"process\",\n unit: \"count\",\n default: 4,\n note: \"HikariPool.java:64: from 2 to 40. The variance of a lifetime is up to 100 / factor percent\",\n },\n housekeepingPeriodMs: {\n key: \"the system property com.zaxxer.hikari.housekeeping.periodMs\",\n scope: \"process\",\n unit: \"ms\",\n default: 30000,\n note: \"HikariPool.java:63. The README names it housekeeping.period, but the code reads housekeeping.periodMs\",\n },\n aliveBypassWindowMs: {\n key: \"the system property com.zaxxer.hikari.aliveBypassWindowMs\",\n scope: \"process\",\n unit: \"ms\",\n default: 500,\n note: \"HikariPool.java:62: a borrow checks a connection only when it was idle for longer\",\n },\n connectTimeout: {\n key: \"pgjdbc connectTimeout\",\n scope: \"client\",\n unit: \"s\",\n default: 10,\n off: 0,\n note: \"PGProperty.java:205-214: the TCP connect and the SSLRequest of each attempt, with its connects again (ConnectionFactoryImpl.java:195-208)\",\n },\n socketTimeout: {\n key: \"pgjdbc socketTimeout\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"PGProperty.java:746-755: SO_TIMEOUT for each read of the startup and of a statement\",\n },\n sslResponseTimeout: {\n key: \"pgjdbc sslResponseTimeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 5000,\n note: \"PGProperty.java:862-869: the read timeout of the answer to the SSLRequest\",\n },\n queryTimeout: {\n key: \"pgjdbc queryTimeout\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"PGProperty.java:586-592: the query timeout of each statement. At its end, pgjdbc sends a CancelRequest\",\n },\n cancelSignalTimeout: {\n key: \"pgjdbc cancelSignalTimeout\",\n scope: \"client\",\n unit: \"s\",\n default: 10,\n note: \"PGProperty.java:139-148: the connect timeout and the read timeout of the connection of a CancelRequest\",\n },\n tcpKeepAlive: {\n key: \"pgjdbc tcpKeepAlive\",\n scope: \"client\",\n unit: null,\n default: 0,\n note: \"PGProperty.java:908-914: off. When it is on, pgjdbc sets SO_KEEPALIVE and no other option, thus the keepalive sysctls of the namespace apply\",\n },\n keepalive_idle: {\n key: \"the keepalive idle time of the socket of pgjdbc\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"A value of this document. 0 is no keepalive, as at the defaults. With tcpKeepAlive on, give tcp_keepalive_time of the namespace\",\n },\n slack: {\n key: \"the lateness of a timer or a thread of the JVM for one step\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of HikariCP or pgjdbc\",\n },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"The build option of the kernel: the keepalive of the socket is the kernel's, thus the timer wheel rounds its firings\",\n },\n },\n timers: {\n connect_timeout: {\n duration: { knob: \"connectTimeout\", unit: \"s\" },\n lateness: { expr: \"min(connectTimeout, 100) + slack\", unit: \"ms\" },\n arms: [\"enter:connecting\"],\n cancels: [\"socket.connect\", \"socket.error\", \"peer.rst\"],\n fires: \"timer.connect-timeout\",\n note: \"Socket.connect with what remains of the budget of the attempt. The negotiating state reads the same budget for its SSLRequest\",\n },\n ssl_response_timeout: {\n duration: { expr: \"min(sslResponseTimeout, connectTimeout * 1000)\", unit: \"ms\" },\n lateness: { expr: \"min(min(sslResponseTimeout, connectTimeout * 1000), 100000) / 1000 + slack\", unit: \"ms\" },\n arms: [\"enter:negotiating\"],\n cancels: [\"rx.ssl-refused\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.ssl-response-timeout\",\n note: \"ConnectionFactoryImpl.java:660-670, :683: the smaller of sslResponseTimeout and the read timeout that the socket has. The connect budget of the attempt also bounds it\",\n },\n socket_timeout: {\n duration: { knob: \"socketTimeout\", unit: \"s\" },\n lateness: { expr: \"min(socketTimeout, 100) + slack\", unit: \"ms\" },\n arms: [\"enter:startup\", \"enter:querying\"],\n cancels: [\"local.connected\", \"rx.ready-for-query\", \"rx.error-response\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.socket-timeout\",\n note: \"SO_TIMEOUT: each read that gets data starts it again. No bound at the defaults. The JDK waits for the read in poll(), thus Linux can end the wait 0.1 % of its time late, at most 100 ms\",\n },\n validation_timeout: {\n duration: { knob: \"validationTimeout\", unit: \"ms\" },\n lateness: { expr: \"min(validationTimeout, 100000) / 1000 + slack\", unit: \"ms\" },\n arms: [\"enter:setup\", \"enter:checking\", \"enter:probing\"],\n cancels: [\"local.created\", \"rx.valid\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.validation-timeout\",\n note: \"PoolBase.java:157-192, :416-456: setNetworkTimeout(validationTimeout) is SO_TIMEOUT for each read of the check or of the setup\",\n },\n query_timeout: {\n duration: { knob: \"queryTimeout\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:querying\"],\n cancels: [\"rx.ready-for-query\", \"rx.error-response\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.query-timeout\",\n note: \"PgStatement.java:1032-1048: a task of java.util.Timer for each statement. No bound at the defaults\",\n },\n connection_timeout: {\n duration: { knob: \"connectionTimeout\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:waiting\"],\n cancels: [\"local.handout\"],\n fires: \"timer.connection-timeout\",\n note: \"HikariPool.java:152-193: one bound for the whole borrow, with each check and each wait in it. A check that fails takes its time from it\",\n },\n keepalive: {\n duration: { knob: \"keepaliveTime\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n early: { expr: \"keepaliveTime / 5\", unit: \"ms\" },\n arms: [\"local.created\", \"rx.valid\", \"timer.keepalive\"],\n fires: \"timer.keepalive\",\n note: \"HikariPool.java:498-504: a fixed delay from the creation, of keepaliveTime less a variance drawn one time for the connection. The next delay counts from the end of the last task, also when the task skipped a connection in use. A use of the connection does not move it. Thus the entry to a state does not arm it, and its first firing after a failure can come at any time in one delay: a cell times it from its empty query on the wire. The task of each connection runs on the one thread of the housekeeper (HikariPool.java:644-656, :879-891). A check that waits for its read timeout delays each task that comes due after it: behind a silent fault, the check of one connection can wait for the checks of the others\",\n },\n max_lifetime: {\n duration: { knob: \"maxLifetime\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n early: { expr: \"maxLifetime / lifeTimeVarianceFactor\", unit: \"ms\" },\n arms: [\"local.created\"],\n fires: \"timer.max-lifetime\",\n note: \"HikariPool.java:490-496: one time, at maxLifetime less a variance drawn one time for the connection: 22.5 to 30 min at the defaults\",\n },\n start_check: {\n duration: { const: 1000, unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:start-check\"],\n fires: \"timer.start-check\",\n note: \"HikariPool.java:592: quietlySleep of 1 s after each failed attempt of the check, on the thread that starts the pool\",\n },\n idle_timeout: {\n duration: { knob: \"idle_eviction\", unit: \"ms\" },\n lateness: { knob: \"housekeepingPeriodMs\", unit: \"ms\" },\n arms: [\"enter:pooled\"],\n cancels: [\"app.borrow\", \"timer.keepalive\", \"timer.max-lifetime\"],\n fires: \"timer.idle\",\n note: \"HikariPool.java:830-841: a run of the housekeeper closes a connection idle for longer than idleTimeout, thus up to one period late. Only when minimumIdle is below maximumPoolSize: at the defaults, no effect\",\n },\n },\n realizes: {\n \"systems.mechanism.connect-bound\": { timer: \"connect_timeout\" },\n \"systems.mechanism.pool-idle-expiry\": { timer: \"idle_timeout\" },\n \"systems.mechanism.request-timeout\": { timer: \"socket_timeout\" },\n \"systems.mechanism.max-connection-age\": { timer: \"max_lifetime\" },\n \"systems.mechanism.idle-refresh-interval\": {\n duration: { knob: \"keepaliveTime\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n early: { expr: \"keepaliveTime / 5\", unit: \"ms\" },\n note: \"The keepalive of the pool: an empty query on an idle connection, each 96 to 120 s at the defaults. A connection in use gets no keepalive\",\n },\n },\n transitions: [\n { id: \"hk.create\", from: \"[none]\", to: \"connecting\", on: \"local.create\", timer: \"connect_timeout\", source: \"HikariPool.java:745-787, PGStream.java:255-283\" },\n {\n id: \"hk.wait\",\n from: \"[none]\",\n to: \"waiting\",\n on: \"app.borrow\",\n timer: \"connection_timeout\",\n note: \"A borrow with an idle connection in the bag gets it at once, and the bag starts a creation when the borrow must wait\",\n source: \"HikariPool.java:152-193, ConcurrentBag.java:161-205\",\n },\n { id: \"hk.handout\", from: \"waiting\", to: \"held\", on: \"local.handout\", guard: \"the connection was idle for no more than aliveBypassWindowMs\", source: \"HikariPool.java:166-178\" },\n {\n id: \"hk.borrow-timed-out\",\n from: \"waiting\",\n to: \"ended\",\n on: \"timer.connection-timeout\",\n timer: \"connection_timeout\",\n errno: \"SQLTransientConnectionException\",\n note: \"'Connection is not available, request timed out after', with the SQLState of the last failed creation (08001 when the connects failed)\",\n source: \"HikariPool.java:183-184, :700-721\",\n },\n {\n id: \"hk.tcp-connected\",\n from: \"connecting\",\n to: \"negotiating\",\n on: \"socket.connect\",\n timer: \"ssl_response_timeout\",\n emits: [\"tx.ssl-request\"],\n source: \"ConnectionFactoryImpl.java:221-283, :646-720\",\n },\n {\n id: \"hk.refused\",\n from: \"connecting\",\n to: \"ended\",\n on: \"peer.rst\",\n errno: \"08001\",\n note: \"'Connection to … refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.' The creator tries again after its backoff\",\n source: \"ConnectionFactoryImpl.java:416-429, HikariPool.java:745-776\",\n },\n {\n id: \"hk.connect-timed-out\",\n from: \"connecting\",\n to: \"ended\",\n on: \"timer.connect-timeout\",\n timer: \"connect_timeout\",\n errno: \"08001\",\n note: \"At prefer, the SocketTimeoutException starts one more connect with SSL off, with 1 ms of the budget left. It fails: 'The connection attempt failed.'\",\n source: \"ConnectionFactoryImpl.java:141-159, :195-208, :378-382, :430-440\",\n },\n {\n id: \"hk.start-attempt-failed\",\n from: \"connecting\",\n to: \"start-check\",\n on: [\"peer.rst\", \"socket.error\", \"timer.connect-timeout\"],\n guard: \"the attempt is the check at the start of the pool, and initializationFailTimeout is 0 or more\",\n timer: \"start_check\",\n note: \"The attempt fails with 08001, and the start of the pool sleeps 1 s\",\n source: \"HikariPool.java:567-599, ConnectionFactoryImpl.java:365-455\",\n },\n {\n id: \"hk.start-failed\",\n from: \"start-check\",\n to: \"ended\",\n on: \"timer.start-check\",\n timer: \"start_check\",\n guard: \"initializationFailTimeout has passed, and it is above 0\",\n errno: \"PoolInitializationException\",\n note: \"'Failed to initialize pool:' with the error of the last attempt as its cause: 08001 for a connect. The constructor of HikariDataSource throws it\",\n source: \"HikariPool.java:592-598, :898-910\",\n },\n {\n id: \"hk.start-again\",\n from: \"start-check\",\n to: \"connecting\",\n on: \"timer.start-check\",\n timer: \"connect_timeout\",\n guard: \"initializationFailTimeout has not passed\",\n source: \"HikariPool.java:574-593\",\n },\n {\n id: \"hk.connect-failed\",\n from: \"connecting\",\n to: \"ended\",\n on: \"socket.error\",\n errno: \"08001\",\n note: \"'The connection attempt failed.': an ICMP error or a give-up of the kernel\",\n source: \"ConnectionFactoryImpl.java:430-440\",\n },\n { id: \"hk.plain\", from: \"negotiating\", to: \"startup\", on: \"rx.ssl-refused\", timer: \"socket_timeout\", source: \"ConnectionFactoryImpl.java:698-707, :290-309\" },\n {\n id: \"hk.ssl-timed-out\",\n from: \"negotiating\",\n to: \"connecting\",\n on: \"timer.ssl-response-timeout\",\n timer: \"connect_timeout\",\n note: \"A new socket, with SSL off, in what remains of the connect budget\",\n source: \"ConnectionFactoryImpl.java:141-159, :378-382\",\n },\n {\n id: \"hk.negotiation-failed\",\n from: \"negotiating\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\"],\n errno: \"08001\",\n source: \"ConnectionFactoryImpl.java:430-440\",\n },\n { id: \"hk.started\", from: \"startup\", to: \"setup\", on: \"local.connected\", timer: \"validation_timeout\", source: \"ConnectionFactoryImpl.java:398, :412, PoolBase.java:416-456\" },\n {\n id: \"hk.startup-failed\",\n from: \"startup\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\", \"rx.error-response\", \"timer.socket-timeout\"],\n errno: \"08001\",\n note: \"An ErrorResponse gives the SQLState of the server instead. At the defaults no timer bounds the startup: a server that stops answering holds it until the kernel gives up\",\n source: \"ConnectionFactoryImpl.java:365-455\",\n },\n { id: \"hk.created\", from: \"setup\", to: \"pooled\", on: \"local.created\", timer: \"keepalive\", source: \"PoolBase.java:416-456, HikariPool.java:490-504\" },\n {\n id: \"hk.setup-failed\",\n from: \"setup\",\n to: \"ended\",\n on: [\"timer.validation-timeout\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n errno: \"08006\",\n note: \"A ConnectionSetupException. At the start of the pool it ends the check of initializationFailTimeout at once (HikariPool.java:567-599)\",\n source: \"PoolBase.java:416-456, QueryExecutorImpl.java:471-475\",\n },\n {\n id: \"hk.borrow\",\n from: \"pooled\",\n to: \"held\",\n on: \"app.borrow\",\n guard: \"the connection was idle for no more than aliveBypassWindowMs\",\n note: \"No check: a dead connection goes out, and its first statement fails\",\n source: \"HikariPool.java:152-178\",\n },\n {\n id: \"hk.borrow-check\",\n from: \"pooled\",\n to: \"checking\",\n on: \"app.borrow\",\n guard: \"the connection was idle for more than aliveBypassWindowMs\",\n timer: \"validation_timeout\",\n emits: [\"tx.empty-query\"],\n source: \"HikariPool.java:166-169, PoolBase.java:157-192, PgConnection.java:1578-1621\",\n },\n { id: \"hk.checked\", from: \"checking\", to: \"held\", on: \"rx.valid\", source: \"PgConnection.java:1578-1621, HikariPool.java:170-178\" },\n {\n id: \"hk.check-failed\",\n from: \"checking\",\n to: \"ended\",\n on: [\"timer.validation-timeout\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n note: \"'(connection is dead)': the pool closes it, and the borrow takes another connection in what remains of connectionTimeout. The application sees no error\",\n source: \"HikariPool.java:166-169, PoolBase.java:157-192\",\n },\n {\n id: \"hk.keepalive\",\n from: \"pooled\",\n to: \"probing\",\n on: \"timer.keepalive\",\n timer: \"validation_timeout\",\n emits: [\"tx.empty-query\"],\n source: \"HikariPool.java:870-892, PoolBase.java:157-192\",\n },\n { id: \"hk.alive\", from: \"probing\", to: \"pooled\", on: \"rx.valid\", timer: \"keepalive\", source: \"HikariPool.java:886-890\" },\n {\n id: \"hk.probe-failed\",\n from: \"probing\",\n to: \"ended\",\n on: [\"timer.validation-timeout\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n note: \"'(connection is dead)': the pool closes it at once, and creates another to fill the pool\",\n source: \"HikariPool.java:879-885\",\n },\n {\n id: \"hk.keepalive-skipped\",\n from: \"held\",\n to: \"held\",\n on: \"timer.keepalive\",\n timer: \"keepalive\",\n note: \"The task cannot reserve a connection in use: it does nothing, and the next delay starts\",\n source: \"HikariPool.java:870-878\",\n },\n {\n id: \"hk.statement\",\n from: \"held\",\n to: \"querying\",\n on: \"app.statement\",\n timer: \"socket_timeout\",\n source: \"QueryExecutorImpl.java:471-475\",\n },\n { id: \"hk.replied\", from: \"querying\", to: \"held\", on: \"rx.ready-for-query\", source: \"QueryExecutorImpl.java:2880-2884\" },\n {\n id: \"hk.statement-failed\",\n from: \"querying\",\n to: \"held\",\n on: \"rx.error-response\",\n guard: \"the SQLState is not on the list of checkException\",\n errno: \"PSQLException\",\n note: \"The SQLState of the server, for example 57014 for a statement that the server cancelled. HikariCP keeps the connection\",\n source: \"QueryExecutorImpl.java:2654-2669, ProxyConnection.java:151-186\",\n },\n {\n id: \"hk.statement-fatal\",\n from: \"querying\",\n to: \"ended\",\n on: \"rx.error-response\",\n guard: \"the SQLState is of the class 08, or 57P01, 57P02 or 57P03\",\n errno: \"PSQLException\",\n note: \"HikariCP closes the connection at once and gives the exception to the application: an administrator or the server ended the session\",\n source: \"ProxyConnection.java:67-84, :151-186\",\n },\n {\n id: \"hk.statement-broken\",\n from: \"querying\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\", \"timer.socket-timeout\"],\n errno: \"08006\",\n note: \"'An I/O error occurred while sending to the backend.': pgjdbc closes the socket with no Terminate, and HikariCP closes the connection. The application gets the exception, and nothing sends the statement again\",\n source: \"QueryExecutorImpl.java:471-475, QueryExecutorCloseAction.java:42-54, ProxyConnection.java:151-186\",\n },\n {\n id: \"hk.query-timed-out\",\n from: \"querying\",\n to: \"cancelling\",\n on: \"timer.query-timeout\",\n timer: \"query_timeout\",\n emits: [\"tx.cancel\"],\n note: \"A server that is not reachable does not get the cancel: its connection fails in cancelSignalTimeout, and pgjdbc ignores the failure\",\n source: \"PgStatement.java:1032-1048, QueryExecutorBase.java:189-230\",\n },\n {\n id: \"hk.cancelled\",\n from: \"cancelling\",\n to: \"held\",\n on: [\"rx.error-response\", \"rx.ready-for-query\"],\n errno: \"57014\",\n note: \"The server ends the statement: 'canceling statement due to user request'. A reply that came first ends it with no error\",\n source: \"QueryExecutorImpl.java:2654-2669\",\n },\n {\n id: \"hk.cancel-broken\",\n from: \"cancelling\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\", \"timer.socket-timeout\"],\n errno: \"08006\",\n source: \"QueryExecutorImpl.java:471-475\",\n },\n {\n id: \"hk.return\",\n from: \"held\",\n to: \"pooled\",\n on: \"app.close\",\n guard: \"the pool did not mark the connection evicted\",\n timer: \"idle_timeout\",\n source: \"PoolEntry.java:77-83, HikariPool.java:434-439\",\n },\n {\n id: \"hk.return-evicted\",\n from: \"held\",\n to: \"ended\",\n on: \"app.close\",\n guard: \"the pool marked the connection evicted: its lifetime ended while it was in use\",\n emits: [\"tx.terminate\"],\n source: \"HikariPool.java:434-439, :626-635\",\n },\n {\n id: \"hk.lifetime-held\",\n from: \"held\",\n to: \"held\",\n on: \"timer.max-lifetime\",\n timer: \"max_lifetime\",\n note: \"The pool marks the connection evicted. It closes at its return\",\n source: \"HikariPool.java:853-868, :626-635\",\n },\n {\n id: \"hk.lifetime\",\n from: \"pooled\",\n to: \"ended\",\n on: \"timer.max-lifetime\",\n timer: \"max_lifetime\",\n emits: [\"tx.terminate\"],\n note: \"'(connection has passed maxLifetime)': the pool closes the idle connection at once, and creates another to fill the pool\",\n source: \"HikariPool.java:853-868, PoolBase.java:137-155\",\n },\n {\n id: \"hk.idle-evicted\",\n from: \"pooled\",\n to: \"ended\",\n on: \"timer.idle\",\n timer: \"idle_timeout\",\n guard: \"minimumIdle is below maximumPoolSize, and the pool has more than minimumIdle idle connections\",\n emits: [\"tx.terminate\"],\n note: \"'(connection has passed idleTimeout)'\",\n source: \"HikariPool.java:830-841\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: {\n connecting: \"SYN_SENT\",\n negotiating: \"ESTABLISHED\",\n startup: \"ESTABLISHED\",\n setup: \"ESTABLISHED\",\n pooled: \"ESTABLISHED\",\n checking: \"ESTABLISHED\",\n probing: \"ESTABLISHED\",\n held: \"ESTABLISHED\",\n querying: \"ESTABLISHED\",\n cancelling: \"ESTABLISHED\",\n },\n sets: {\n keepidle: { knob: \"keepalive_idle\", unit: \"s\" },\n },\n ends: \"socket.error\",\n note: \"Each socket of pgjdbc is a Linux TCP socket with TCP_NODELAY. At the defaults no socket has keepalive, thus keepidle has no bound. With tcpKeepAlive on, pgjdbc sets SO_KEEPALIVE only, thus the interval and the count of the namespace apply\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the JavaScript source of the npm packages pg at 8.23.1 (under\n// lib/), pg-pool at 3.14.0 and pg-protocol at 1.16.1 (under dist/), as npm publishes them. Each\n// line number is a line of that file in the package. Node's own facts are from the source of node\n// at the tag v24.21.0.\nconst AT = \"pg 8.23.1 lib\";\nconst POOL = \"pg-pool 3.14.0\";\nconst PROTOCOL = \"pg-protocol 1.16.1 dist\";\n\n/**\n * This document is node-postgres 8.23.1 (the npm package pg) with pg-pool 3.14.0, for one client\n * of a `pg.Pool`. It gives the states of the client, from its connect to its end, and the timers\n * that act on it. The pool hands out an idle client with no test of its connection. At the\n * defaults, the client turns no keepalive on and sends nothing on an idle connection. Neither\n * package sends a query again, and neither package connects again by itself.\n *\n * A knob of pg at 0 or false has no timer: give it as no bound (`infinite`). This is true of\n * `connectionTimeoutMillis`, `query_timeout`, `maxLifetimeSeconds` and `idleTimeoutMillis`. At the\n * defaults of a pool, only the idle timer of the pool runs, for 10000 ms. Thus no timer of pg\n * bounds the connect, the startup, a checkout from a full pool or a query.\n *\n * Three timeouts are not timers of the client: `statement_timeout`, `lock_timeout` and\n * `idle_in_transaction_session_timeout`. The client sends each one to the server in the startup\n * message, and only when it is set.\n *\n * The pool emits `error` when an idle client fails. A client that the application holds emits\n * `error` itself, and the pool does not listen to it. In Node, an `error` event with no listener\n * throws.\n */\nexport const NODE_POSTGRES: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"node-postgres\",\n title: \"node-postgres 8.23.1 with pg-pool 3.14.0: one client of a pg.Pool, its connect, its queries and its idle time\",\n layer: \"driver\",\n version: \"8.23.1\",\n conditions: {\n pg: \"8.23.1\",\n \"pg-pool\": \"3.14.0\",\n \"pg-protocol\": \"1.16.1\",\n node: \"24.21.0\",\n client: \"a pg.Pool with the defaults of pg-pool and pg, unless a knob says otherwise: the JavaScript client, not pg-native\",\n transport: \"TCP to a host and port, with no TLS (ssl false, and no PGSSLMODE) and no pipeline mode\",\n },\n sources: [\n { ref: `${POOL}/index.js:89-93 max 10, min 0, maxUses Infinity, allowExitOnIdle false, maxLifetimeSeconds 0, :98-100 idleTimeoutMillis 10000 when it is undefined`, rung: \"implemented\" },\n { ref: `${AT}/defaults.js:42 max 10 and :46 idleTimeoutMillis 30000: no line of pg or pg-pool reads them, thus a pool does not use them`, rung: \"implemented\" },\n { ref: `${AT}/defaults.js:65, :69, :73 and :76 statement_timeout, lock_timeout, idle_in_transaction_session_timeout and query_timeout are false`, rung: \"implemented\" },\n { ref: `${AT}/defaults.js:63-76 the comments of pg: each of the four is in milliseconds, false is no limit, and query_timeout is on the client side`, rung: \"documented\" },\n { ref: `${AT}/connection-parameters.js:9-23 val: the config, else the default of pg, :121-124 the three timeouts of the server and query_timeout, with no environment variable`, rung: \"implemented\" },\n { ref: `${AT}/client.js:89-98 the Connection gets keepAlive false and keepAliveInitialDelayMillis 0 when the config does not give them, :116 connectionTimeoutMillis 0`, rung: \"implemented\" },\n { ref: `${AT}/stream.js:20-24 and :78-83 outside Cloudflare Workers, the socket is a new net.Socket with no option`, rung: \"implemented\" },\n { ref: `${AT}/connection.js:40-52 setNoDelay(true) before the connect, and setKeepAlive(true, keepAliveInitialDelayMillis) at the connect only when keepAlive is true, :54-65 the error and the close of the socket`, rung: \"implemented\" },\n { ref: `${AT}/client.js:167-176 and :702-737 are the only timers of the client, and connection.js has none: the client sends nothing by itself on an idle connection`, rung: \"implemented\" },\n { ref: `${AT}/client.js:153-230 _connect: no second connect, the connect timer of the client ('timeout expired'), and 'Connection terminated unexpectedly' for an end that the client did not ask for`, rung: \"implemented\" },\n { ref: `${AT}/client.js:373-387 the first ReadyForQuery ends the connect and clears the timer, :398-423 an error before it goes to the connect callback, and an error after it makes the client unqueryable`, rung: \"implemented\" },\n { ref: `${AT}/client.js:426-442 an ErrorResponse fails the active query only, and with no active query it is an error of the client`, rung: \"implemented\" },\n { ref: `${AT}/connection.js:137-145 and ${PROTOCOL}/parser.js:142-144, :296-323 an ErrorResponse is a DatabaseError, with the severity and the code that the server gives`, rung: \"implemented\" },\n { ref: `${AT}/client.js:133-151 _errorAllQueries: each query of the client fails with the same error, on the next tick`, rung: \"implemented\" },\n { ref: `${AT}/query.js:122-150 a query gives its error or its result to its callback, at the error or at the ReadyForQuery`, rung: \"implemented\" },\n { ref: `${AT}/client.js:702-737 query_timeout: a Node timer for each query, 'Query read timeout'. The client sends no cancel, and it keeps the active query`, rung: \"implemented\" },\n { ref: `${AT}/client.js:616-641 the next query goes only after a ReadyForQuery, :765-777 a query on an unqueryable or ended client fails at once`, rung: \"implemented\" },\n { ref: `${AT}/client.js:799-836 end: a dead socket or an active query destroys the socket, else connection.js:217-227 sends Terminate and ends the socket`, rung: \"implemented\" },\n { ref: `${AT}/client.js:543-572 getStartupConf: statement_timeout, lock_timeout and idle_in_transaction_session_timeout go to the server only when they are set`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:190-238 connect: a checkout from a full pool waits in the queue with no bound at connectionTimeoutMillis 0, else 'timeout exceeded when trying to connect'`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:240-309 newClient: a connect timer of connectionTimeoutMillis destroys the socket, 'Connection terminated due to connection timeout', and the pool does not try again`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:127-170 _pulseQueue: the first waiter gets the last idle client (pop), with no test, :335-366 verify runs only on a new client`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:384-429 _release: an error, a client that is not queryable or ends, maxUses or an expired lifetime removes the client, else the idle timer arms above min`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:311-332 maxLifetimeSeconds: its timer marks the client expired, and an idle client goes at once`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:51-64 and :172-188 an idle client that emits error leaves the pool, and the pool emits error with it, :340-344 a checkout removes that listener`, rung: \"implemented\" },\n { ref: `${POOL}/index.js:431-486 pool.query: an error of the checkout, of the client or of the query fails pool.query with no second try, and a release with that error ends the client`, rung: \"implemented\" },\n { ref: `${POOL}/README.md:224-240 the pool emits error for an idle client, and the application must listen for it`, rung: \"documented\" },\n { ref: \"systems.machine.linux-tcp: a reset of an established socket is ECONNRESET, and a give-up of the kernel is ETIMEDOUT. pg gives the error of the socket to the application as it is (connection.js:54-61)\", rung: \"derived\" },\n { ref: \"node v24.21.0 lib/net.js:846-888 (setKeepAlive truncates the delay to whole seconds), src/tcp_wrap.cc:204-221 (interval 1 s and count 10 when none is given), deps/uv/src/unix/tcp.c:468-480 (SO_KEEPALIVE first, then EINVAL and no other option for an idle time below 1 s)\", rung: \"implemented\" },\n { ref: \"node v24.21.0 lib/net.js:589 (a socket has no timeout until setTimeout), :828-843 and :1987-1989 (a setNoDelay before the connect applies at the connect)\", rung: \"implemented\" },\n { ref: \"node v24.21.0 lib/net.js:600-604, lib/internal/streams/readable.js:1752-1790 and lib/internal/streams/writable.js:951-973: a socket allows no half-open connection, thus a FIN from the peer ends it and it closes\", rung: \"implemented\" },\n { ref: \"node v24.21.0 lib/events.js:489-506 an error event with no listener throws\", rung: \"implemented\" },\n { ref: \"node v24.21.0 lib/internal/timers.js:426-446 the timers of one duration go in one list, in the order that they start\", rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"Before the pool makes the client, or before a checkout gets one\" },\n waiting: {\n note: \"A checkout of the application waits in the queue of the pool, because the pool is full or has an idle client (pg-pool index.js:200-232)\",\n },\n connecting: { note: \"The TCP connect of a new client, with TCP_NODELAY and no keepalive at the defaults (connection.js:40-52)\" },\n startup: { note: \"The startup message and the authentication, until the first ReadyForQuery (client.js:185-199, :373-387)\" },\n held: {\n note: \"A client that the application holds after a checkout, with no query in flight. The pool does not listen to its errors (pg-pool index.js:344)\",\n },\n querying: { note: \"A query in flight: the client waits for its ReadyForQuery, and sends no other query (client.js:616-641)\" },\n orphaned: {\n note: \"The query failed to the application on its timer, but it stays the active query of the client. The client sends no cancel, and waits for the ReadyForQuery of that query (client.js:702-737)\",\n },\n pooled: { note: \"An idle client in the pool, with the idle timer of the pool (pg-pool index.js:407-427)\" },\n ended: {\n final: true,\n note: \"The socket closes, the pool removes the client, or a checkout fails. The client does not connect again, and a query on it fails at once (client.js:158-164, :765-777)\",\n },\n },\n events: {\n \"app.checkout\": { kind: \"app\", note: \"The application calls pool.connect, or pool.query before its query\" },\n \"app.query\": { kind: \"app\", note: \"The application calls client.query, or pool.query sends its query\" },\n \"app.release\": { kind: \"app\", note: \"The application calls client.release() with no error, or pool.query releases the client after a reply\" },\n \"app.release-error\": { kind: \"app\", note: \"The application calls client.release(err), or pool.query releases the client after an error of the query or of the client\" },\n \"local.handout\": { kind: \"local\", note: \"The pool gives an idle client to the first waiter of its queue (pg-pool index.js:156-165)\" },\n \"local.slot\": { kind: \"local\", note: \"A removal frees a place in a full pool, and the first waiter gets a new client (pg-pool index.js:166-168)\" },\n \"socket.connect\": { kind: \"local\" },\n \"local.connected\": { kind: \"local\", note: \"The first ReadyForQuery of the server: the end of the connect, and the connect callback of the client\" },\n \"rx.ready-for-query\": { kind: \"rx\", note: \"The ReadyForQuery that ends a query\" },\n \"rx.error-response\": { kind: \"rx\", note: \"An ErrorResponse of the server: a DatabaseError, with the severity and the code of the server\" },\n \"peer.fin\": { kind: \"peer\", note: \"The server or a middlebox closes the connection. Node ends the socket, and its close is the end of the connection\" },\n \"peer.rst\": { kind: \"peer\", note: \"A reset of the connection: the socket fails with ECONNRESET\" },\n \"socket.error\": { kind: \"local\", note: \"The socket fails with its own error: a reset, or a give-up of the kernel (ETIMEDOUT)\" },\n \"tx.terminate\": { kind: \"tx\", note: \"The Terminate message, then the end of the socket of the client (connection.js:217-227)\" },\n \"timer.connect-timeout\": { kind: \"timer\", note: \"The pool destroys the socket: 'Connection terminated due to connection timeout'\" },\n \"timer.checkout-timeout\": { kind: \"timer\", note: \"The checkout fails: 'timeout exceeded when trying to connect'\" },\n \"timer.idle\": { kind: \"timer\", note: \"The pool removes the idle client\" },\n \"timer.query-timeout\": { kind: \"timer\", note: \"The query fails to the application: 'Query read timeout'\" },\n \"timer.max-lifetime\": { kind: \"timer\", note: \"The pool marks the client expired\" },\n },\n knobs: {\n connectionTimeoutMillis: {\n key: \"pg-pool connectionTimeoutMillis\",\n scope: \"client\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"client.js:116 and pg-pool index.js:206, :250. 0 is no timeout, for the connect and for a checkout\",\n },\n idleTimeoutMillis: {\n key: \"pg-pool idleTimeoutMillis\",\n scope: \"client\",\n unit: \"ms\",\n default: 10000,\n off: 0,\n note: \"pg-pool index.js:98-100: 10000 when it is undefined, not the 30000 of pg.defaults. 0 is no idle timer (index.js:409)\",\n },\n query_timeout: {\n key: \"pg query_timeout\",\n scope: \"client\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"defaults.js:76 and client.js:702-703: false at the defaults, thus no timer\",\n },\n maxLifetimeSeconds: {\n key: \"pg-pool maxLifetimeSeconds\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"pg-pool index.js:93 and :312. 0 is no limit\",\n },\n max: { key: \"pg-pool max\", scope: \"client\", unit: \"count\", default: 10, note: \"pg-pool index.js:89\" },\n min: {\n key: \"pg-pool min\",\n scope: \"client\",\n unit: \"count\",\n default: 0,\n note: \"pg-pool index.js:90: the idle timer arms only when the pool has more clients than min (index.js:409-415)\",\n },\n maxUses: { key: \"pg-pool maxUses\", scope: \"client\", unit: \"count\", default: null, note: \"pg-pool index.js:91: Infinity at the defaults, thus no limit\" },\n allowExitOnIdle: {\n key: \"pg-pool allowExitOnIdle\",\n scope: \"client\",\n unit: null,\n default: 0,\n note: \"pg-pool index.js:92: off. When it is on, the idle timer and the idle socket do not hold the event loop (index.js:417-425)\",\n },\n keepAlive: {\n key: \"pg keepAlive\",\n scope: \"client\",\n unit: null,\n default: 0,\n note: \"client.js:95: off. Then the client calls no setKeepAlive, and the socket has no keepalive (connection.js:48-50)\",\n },\n keepAliveInitialDelayMillis: {\n key: \"pg keepAliveInitialDelayMillis\",\n scope: \"client\",\n unit: \"ms\",\n default: 0,\n note: \"client.js:96. The client gives it to setKeepAlive only when keepAlive is on (connection.js:48-50)\",\n },\n keepalive_idle: {\n key: \"the keepalive idle time of the socket of pg\",\n scope: \"client\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"A value of this document, from keepAlive and keepAliveInitialDelayMillis. 0 is no keepalive, as at the defaults. With keepAlive on and a delay of 1000 ms or more, give floor(keepAliveInitialDelayMillis / 1000). Below 1000 ms, libuv sets no idle time: give tcp_keepalive_time, and the interval and count of the namespace to the two knobs below\",\n },\n node_keepalive_interval: {\n key: \"node net.Socket setKeepAlive interval\",\n scope: \"client\",\n unit: \"s\",\n default: 1,\n note: \"Node passes 1 s to libuv when setKeepAlive gets no interval, as pg gives none\",\n },\n node_keepalive_count: {\n key: \"node net.Socket setKeepAlive count\",\n scope: \"client\",\n unit: \"count\",\n default: 10,\n note: \"Node passes 10 to libuv when setKeepAlive gets no count, as pg gives none\",\n },\n statement_timeout: {\n key: \"pg statement_timeout\",\n scope: \"session\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"defaults.js:63-65 and client.js:558-560: false at the defaults. When it is set, the client sends it to the server in the startup message. The client has no timer for it\",\n },\n lock_timeout: {\n key: \"pg lock_timeout\",\n scope: \"session\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"defaults.js:67-69 and client.js:561-563: false at the defaults. When it is set, the client sends it to the server in the startup message. The client has no timer for it\",\n },\n idle_in_transaction_session_timeout: {\n key: \"pg idle_in_transaction_session_timeout\",\n scope: \"session\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"defaults.js:71-73 and client.js:564-566: false at the defaults. When it is set, the client sends it to the server in the startup message. The client has no timer for it\",\n },\n slack: {\n key: \"the lateness of the event loop of Node for one step\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of pg: a timer or a callback of Node that comes late\",\n },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"The build option of the kernel: the keepalive of pg is the kernel's, thus the timer wheel rounds its firings\",\n },\n },\n timers: {\n connect_timeout: {\n duration: { knob: \"connectionTimeoutMillis\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n // The timer starts one time, at the connect, and runs through the startup. The arm at the entry to startup\n // lets a reader of one state find it: there, the time that remains is less by the time of the TCP connect.\n arms: [\"enter:connecting\", \"enter:startup\"],\n cancels: [\"local.connected\", \"socket.error\", \"peer.rst\", \"peer.fin\", \"rx.error-response\"],\n fires: \"timer.connect-timeout\",\n // The pool arms its timer (pg-pool index.js:250-263), and then the client arms its own (client.js:167-176).\n // The two have the same duration, thus the timer of the pool fires first (lib/internal/timers.js:426-446).\n note: \"One timer for the TCP connect, the startup and the authentication, until the first ReadyForQuery. No bound at the defaults: the TCP connect waits for the kernel, and the startup waits with no bound\",\n },\n checkout_timeout: {\n duration: { knob: \"connectionTimeoutMillis\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:waiting\"],\n cancels: [\"local.handout\", \"local.connected\"],\n fires: \"timer.checkout-timeout\",\n note: \"pg-pool index.js:206-232: no bound at the defaults. A waiter that gets a new client keeps this timer through the connect of that client. When it fires then, the new client goes to the pool after its connect (index.js:359-364)\",\n },\n idle_timeout: {\n duration: { knob: \"idleTimeoutMillis\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:pooled\"],\n cancels: [\"app.checkout\", \"socket.error\", \"peer.rst\", \"peer.fin\", \"rx.error-response\", \"timer.max-lifetime\"],\n fires: \"timer.idle\",\n note: \"pg-pool index.js:407-421: each release arms it when the pool has more clients than min. A checkout or a removal clears it (index.js:159, :176)\",\n },\n query_timeout: {\n duration: { knob: \"query_timeout\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"app.query\", \"enter:querying\"],\n cancels: [\"rx.ready-for-query\", \"rx.error-response\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.query-timeout\",\n note: \"client.js:702-737: one timer for each query, from client.query, thus the wait in the queue of the client counts too. No bound at the defaults\",\n },\n max_lifetime: {\n duration: { knob: \"maxLifetimeSeconds\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"local.connected\"],\n cancels: [\"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.max-lifetime\",\n note: \"pg-pool index.js:311-332: one timer for the life of the client, from its connect. No limit at the defaults. A held client goes at its next release (index.js:400-405)\",\n },\n },\n realizes: {\n \"systems.mechanism.connect-bound\": { timer: \"connect_timeout\" },\n \"systems.mechanism.pool-idle-expiry\": { timer: \"idle_timeout\" },\n \"systems.mechanism.request-timeout\": { timer: \"query_timeout\" },\n \"systems.mechanism.idle-refresh-interval\": {\n duration: { knob: \"keepalive_idle\", unit: \"s\" },\n lateness: { model: \"linux.wheel\", knobs: [\"keepalive_idle\", \"hz\"], unit: \"s\" },\n early: { model: \"linux.jiffy\", knobs: [\"hz\"], unit: \"s\" },\n note: \"The first keepalive probe of an idle client. Keepalive is off at the defaults, thus no bound: the client sends nothing on an idle connection\",\n },\n },\n transitions: [\n {\n id: \"pg.open\",\n from: \"[none]\",\n to: \"connecting\",\n on: \"app.checkout\",\n guard: \"the pool is not full and has no idle client\",\n timer: \"connect_timeout\",\n source: \"pg-pool index.js:200, :235, :240-266\",\n },\n {\n id: \"pg.wait\",\n from: \"[none]\",\n to: \"waiting\",\n on: \"app.checkout\",\n guard: \"the pool is full, or it has an idle client\",\n timer: \"checkout_timeout\",\n note: \"With an idle client, the pool gives it on the next tick (index.js:202-204)\",\n source: \"pg-pool index.js:200-232\",\n },\n { id: \"pg.handout\", from: \"waiting\", to: \"held\", on: \"local.handout\", source: \"pg-pool index.js:156-165, :335-366\" },\n {\n id: \"pg.slot\",\n from: \"waiting\",\n to: \"connecting\",\n on: \"local.slot\",\n timer: \"connect_timeout\",\n note: \"The waiter keeps its checkout timer, and the new client has its own connect timer\",\n source: \"pg-pool index.js:166-168, :240-266\",\n },\n {\n id: \"pg.checkout-timed-out\",\n from: \"waiting\",\n to: \"ended\",\n on: \"timer.checkout-timeout\",\n timer: \"checkout_timeout\",\n errno: \"timeout exceeded when trying to connect\",\n source: \"pg-pool index.js:219-225\",\n },\n {\n id: \"pg.connected\",\n from: \"connecting\",\n to: \"startup\",\n on: \"socket.connect\",\n note: \"The client sends the startup message at once\",\n source: \"connection.js:47-52, client.js:185-195\",\n },\n {\n id: \"pg.ready\",\n from: \"startup\",\n to: \"held\",\n on: \"local.connected\",\n note: \"The first ReadyForQuery clears the connect timers, and the pool gives the client to the checkout\",\n source: \"client.js:373-387, pg-pool index.js:266-309, :335-366\",\n },\n {\n id: \"pg.connect-timed-out\",\n from: [\"connecting\", \"startup\"],\n to: \"ended\",\n on: \"timer.connect-timeout\",\n timer: \"connect_timeout\",\n errno: \"Connection terminated due to connection timeout\",\n note: \"The cause of the error is the error of the client. The checkout fails, and the pool does not try again\",\n source: \"pg-pool index.js:250-284\",\n },\n {\n id: \"pg.connect-failed\",\n from: [\"connecting\", \"startup\"],\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\", \"rx.error-response\"],\n note: \"The checkout fails with the error: the error of the socket, 'Connection terminated unexpectedly' for a close, or the DatabaseError of the server. The pool does not try again\",\n source: \"client.js:203-230, :398-411, pg-pool index.js:266-284\",\n },\n {\n id: \"pg.query\",\n from: \"held\",\n to: \"querying\",\n on: \"app.query\",\n timer: \"query_timeout\",\n source: \"client.js:668-785, :616-641\",\n },\n {\n id: \"pg.replied\",\n from: \"querying\",\n to: \"held\",\n on: \"rx.ready-for-query\",\n note: \"Then pool.query releases the client\",\n source: \"client.js:373-396, query.js:136-150, pg-pool index.js:467-478\",\n },\n {\n id: \"pg.statement-failed\",\n from: \"querying\",\n to: \"held\",\n on: \"rx.error-response\",\n errno: \"DatabaseError\",\n note: \"The query fails, and the client stays queryable. Then pool.query releases the client with the error, thus the pool ends it\",\n source: \"client.js:426-442, query.js:122-134, pg-pool index.js:467-477\",\n },\n {\n id: \"pg.query-timed-out\",\n from: \"querying\",\n to: \"orphaned\",\n on: \"timer.query-timeout\",\n timer: \"query_timeout\",\n errno: \"Query read timeout\",\n note: \"The query fails to the application. The client sends no cancel and stays queryable. Then pool.query releases the client with the error\",\n source: \"client.js:702-737, pg-pool index.js:467-477\",\n },\n {\n id: \"pg.orphan-ended\",\n from: \"orphaned\",\n to: \"held\",\n on: [\"rx.ready-for-query\", \"rx.error-response\"],\n note: \"The old query ends, and its result goes to no one. Then the client sends the next query of its queue\",\n source: \"client.js:373-396, :426-442, :717\",\n },\n {\n id: \"pg.query-abandoned\",\n from: \"orphaned\",\n to: \"ended\",\n on: \"app.release-error\",\n note: \"The pool ends the client, and the active query makes end destroy the socket. The server gets no cancel\",\n source: \"pg-pool index.js:392-398, :172-188, client.js:822-824\",\n },\n {\n id: \"pg.release-busy\",\n from: \"orphaned\",\n to: \"pooled\",\n on: \"app.release\",\n guard: \"the application releases the client with no error\",\n note: \"The pool keeps the client. The next query on it waits for the ReadyForQuery of the old query\",\n source: \"pg-pool index.js:392-429, client.js:616-641\",\n },\n {\n id: \"pg.orphan-failed\",\n from: \"orphaned\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\"],\n note: \"The old query has no callback left, thus only the error event of the client tells of the failure\",\n source: \"client.js:717, :133-151, :203-230, :416-423\",\n },\n {\n id: \"pg.query-reset\",\n from: \"querying\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\"],\n errno: \"ECONNRESET\",\n note: \"The error of the socket, with its own code: ECONNRESET for a reset, ETIMEDOUT for a give-up of the kernel. Each query of the client fails with it, and the client emits it\",\n source: \"connection.js:54-61, client.js:133-151, :416-423\",\n },\n {\n id: \"pg.query-closed\",\n from: \"querying\",\n to: \"ended\",\n on: \"peer.fin\",\n errno: \"Connection terminated unexpectedly\",\n note: \"Each query of the client fails with this error, and the client emits it\",\n source: \"connection.js:63-65, client.js:203-230\",\n },\n {\n id: \"pg.release\",\n from: \"held\",\n to: \"pooled\",\n on: \"app.release\",\n guard: \"the client is queryable and its end did not start, it has fewer uses than maxUses, and the pool did not mark it expired\",\n timer: \"idle_timeout\",\n source: \"pg-pool index.js:384-429\",\n },\n {\n id: \"pg.release-removed\",\n from: \"held\",\n to: \"ended\",\n on: \"app.release\",\n guard: \"the client is not queryable or its end started, it reached maxUses, or the pool marked it expired\",\n note: \"The pool removes the client. Its end sends Terminate, or destroys a dead socket\",\n source: \"pg-pool index.js:392-405, :172-188, client.js:799-836\",\n },\n {\n id: \"pg.release-error\",\n from: \"held\",\n to: \"ended\",\n on: \"app.release-error\",\n note: \"The pool removes the client. Its end sends Terminate, or destroys a dead socket\",\n source: \"pg-pool index.js:392-398, :172-188, client.js:799-836\",\n },\n {\n id: \"pg.held-failed\",\n from: \"held\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\", \"peer.fin\", \"rx.error-response\"],\n note: \"The client emits error, and the pool does not listen. With no listener of the application, the error throws. After a socket error, the close of the socket emits a second error: 'Connection terminated unexpectedly'\",\n source: \"pg-pool index.js:340-344, client.js:203-230, :398-435, node lib/events.js:489-506\",\n },\n {\n id: \"pg.checkout\",\n from: \"pooled\",\n to: \"held\",\n on: \"app.checkout\",\n note: \"The last client that went back to the pool goes out first. The pool sends no test query, thus a dead connection goes out too\",\n source: \"pg-pool index.js:156-165, :335-366\",\n },\n {\n id: \"pg.idle-expired\",\n from: \"pooled\",\n to: \"ended\",\n on: \"timer.idle\",\n timer: \"idle_timeout\",\n guard: \"the pool has more clients than min\",\n emits: [\"tx.terminate\"],\n note: \"The pool emits remove only in the callback of the end of the client, when the socket closes (pg-pool index.js:181-187). Behind a black hole the FIN gets no answer, thus the socket stays open and remove does not come\",\n source: \"pg-pool index.js:409-416, :172-188, client.js:825-827, connection.js:217-227\",\n },\n {\n id: \"pg.lifetime-expired\",\n from: \"pooled\",\n to: \"ended\",\n on: \"timer.max-lifetime\",\n timer: \"max_lifetime\",\n emits: [\"tx.terminate\"],\n note: \"The pool checks out the idle client and releases it at once, thus it removes it\",\n source: \"pg-pool index.js:313-326, :400-405\",\n },\n {\n id: \"pg.idle-reset\",\n from: \"pooled\",\n to: \"ended\",\n on: [\"socket.error\", \"peer.rst\"],\n errno: \"ECONNRESET\",\n note: \"The pool removes the client, and emits error with the error of the socket and the client. With no listener of the pool, the error throws\",\n source: \"connection.js:54-61, client.js:416-423, pg-pool index.js:51-64, node lib/events.js:489-506\",\n },\n {\n id: \"pg.idle-closed\",\n from: \"pooled\",\n to: \"ended\",\n on: \"peer.fin\",\n errno: \"Connection terminated unexpectedly\",\n note: \"The pool removes the client and emits error with this error\",\n source: \"connection.js:63-65, client.js:203-230, pg-pool index.js:51-64\",\n },\n {\n id: \"pg.idle-fatal\",\n from: \"pooled\",\n to: \"ended\",\n on: \"rx.error-response\",\n errno: \"DatabaseError\",\n note: \"An ErrorResponse with no active query is an error of the client: the pool removes the client and emits error with the DatabaseError\",\n source: \"client.js:426-435, :416-423, pg-pool index.js:51-64\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: {\n connecting: \"SYN_SENT\",\n startup: \"ESTABLISHED\",\n held: \"ESTABLISHED\",\n querying: \"ESTABLISHED\",\n orphaned: \"ESTABLISHED\",\n pooled: \"ESTABLISHED\",\n },\n sets: {\n keepidle: { knob: \"keepalive_idle\", unit: \"s\" },\n keepintvl: { knob: \"node_keepalive_interval\", unit: \"s\" },\n keepcnt: { knob: \"node_keepalive_count\", unit: \"count\" },\n },\n ends: \"socket.error\",\n note: \"Each socket of pg is a Linux TCP socket with TCP_NODELAY. At the defaults pg turns keepalive on for no socket, thus keepidle has no bound. With keepAlive on and a delay of 1 s or more, Node gives libuv the delay in whole seconds, with 1 s and 10 probes. With a delay below 1 s, libuv sets SO_KEEPALIVE and no other option, thus the three keepalive sysctls of the namespace apply\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the C source of PgBouncer at the tag pgbouncer_1_26_1 (commit\n// f03e9bf263d7, the tarball of GitHub with SHA-256 2e659b12...a64ea6bc38). Each line number is a\n// line of that file at the tag. The tag holds libusual in lib/. A fact of libevent or of the kernel\n// is an assumption of this document, and its note says so.\nexport const PB = \"pgbouncer_1_26_1\";\n\n/** These are the sources of both documents: the defaults, the janitor and its clock. */\nexport const PB_COMMON: Machine[\"sources\"] = [\n { ref: `${PB} src/main.c:260-365 the defaults of the configuration: client_login_timeout 60 s, query_wait_timeout 120 s, client_idle_timeout 0, query_timeout 0, idle_transaction_timeout 0, transaction_timeout 0, server_connect_timeout 15 s, server_login_retry 15 s, server_idle_timeout 600 s, server_lifetime 3600 s, server_check_delay 30 s, server_check_query <empty>, pool_mode session, tcp_keepalive 1`, rung: \"implemented\" },\n { ref: `${PB} lib/usual/cfparser.c:530-556 a time of the configuration is seconds as a double, kept in microseconds. src/loader.c:349-358, :558-573 a setting of a database or a user takes whole seconds`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:27-28, :780-786 and src/main.c:1088 the janitor: a persistent libevent timer of USEC / 3, thus each 333.3 ms`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:694-777 each pass of the janitor: the maintenance of the servers and then of the clients of each pool, then the logins of the clients`, rung: \"implemented\" },\n { ref: `${PB} lib/usual/time.c:67-89 and src/main.c:868-889 the time of a pass is gettimeofday, cached for each loop of the events`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:307, :341, :343, :368, :416, :549, :552, :567, :619 each timer compares its age with > its limit: a timer fires at the first pass of the janitor after its limit`, rung: \"implemented\" },\n { ref: `${PB} src/util.c:162-236 and lib/usual/socket.c:78-147 each TCP socket gets SO_KEEPALIVE and TCP_NODELAY. TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT only when they are not 0, thus the values of the namespace apply at the defaults`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:267-292 the effective pool mode: of the user, then of the database, then the global one`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1451-1465, :1593-1600 and src/proto.c:260-275 a close of a client with a reason sends an ErrorResponse: severity FATAL, SQLSTATE 08P01, the reason as its message, and no ReadyForQuery`, rung: \"implemented\" },\n];\n\n/**\n * This document is PgBouncer 1.26.1 in transaction pooling, for one client connection. It gives the\n * states of the client, from its accept to its close, and the timers that act on it.\n *\n * In transaction pooling, a client holds a server connection only for a transaction. Between two\n * transactions the client is idle, and PgBouncer reads its socket: the end of the stream or a reset\n * closes it at once. A query that finds no idle server waits in a queue, and PgBouncer does not read\n * the socket of a waiting client. It finds a client that left the queue only when it serves it.\n *\n * Each timer of a client is a check of the janitor, which runs each 333.3 ms. A timer thus fires up\n * to one period after its limit, and a busy loop of events delays it more. At the defaults only two\n * timers act on a client: client_login_timeout (60 s) and query_wait_timeout (120 s). A timer that\n * fires, and the failure of the linked server, close the client with a FATAL error of SQLSTATE 08P01.\n */\nexport const PGBOUNCER_CLIENT: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"pgbouncer-client\",\n title: \"PgBouncer 1.26.1 in transaction pooling: one client connection, its login, its queue and its transactions\",\n layer: \"proxy\",\n version: \"1.26.1\",\n conditions: {\n pgbouncer: \"1.26.1\",\n pool_mode: \"transaction, set for the database or the user, or globally\",\n client: \"a PostgreSQL client over TCP, with no TLS\",\n server: \"one PostgreSQL server for the database of the client\",\n },\n sources: [\n ...PB_COMMON,\n { ref: `${PB} include/bouncer.h:69-89 and src/objects.c:222-289 the states of a client, each a list: CL_LOGIN, CL_WAITING, CL_WAITING_LOGIN, CL_ACTIVE`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:272-275 a client that waits goes to the end of the queue, and it gets the time of its wait`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:606-622 client_login_timeout: a client in CL_LOGIN for longer than it, from its accept, is closed: 'client_login_timeout'`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:2077-2085 and src/janitor.c:361-371 a client that logs in before the pool has a welcome message waits for it. client_login_timeout from its accept closes it: 'client_login_timeout (server down)'`, rung: \"implemented\" },\n { ref: `${PB} src/client.c:1639-1662 each packet of the client: the start of the query and of the transaction, then find_server. The server is no longer ready`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:915-988 find_server: the first idle server, else check_fast_fail and a wait in the queue`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:805-817 and src/sbuf.c:218-229 a client that waits is paused: its socket is not read`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:838-850 and src/sbuf.c:232-257, :494-506 an active client keeps the read of its socket`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:116-170 and src/objects.c:994-1014 the first waiting client gets the next idle server: first in, first out`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:313-347 query_wait_timeout: a waiting client for longer than it, from the start of its query, is closed: 'query_wait_timeout'. query_timeout acts there first: 'query_timeout'`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:293-310 client_idle_timeout acts only on an active client with no server: 'client_idle_timeout'`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:500-556 on each active server: query_timeout from the start of the query, the queue included, then idle_transaction_timeout, then transaction_timeout. Each closes the server and the client`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:433-455, :642-668 ReadyForQuery I makes the server ready and ends the query and the transaction. T or E keeps the server linked, idle in a transaction`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:861-921 and src/objects.c:1213-1322 the release: a ready server whose data the client got goes back to the pool`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:869-900 check_fast_fail: when the last login of the pool failed and it has no server outside a login, a client that needs one is closed at once: 'server login has been failing, cached error: ... (server_login_retry)'`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:808-813 and src/objects.c:1324-1344, :1375-1379 a linked server whose socket fails: the client gets 'server conn crashed?' and is closed`, rung: \"implemented\" },\n { ref: `${PB} src/client.c:1789-1800 the end of the stream or an error of the socket of a client closes it: 'client unexpected eof'. A send to its server that fails: 'server connection closed'`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1493-1534 a client that goes while linked: its server is closed when it was not ready, else it goes back to the pool`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:788-813 and src/admin.c:1202-1244 KILL closes each client of the database: 'database removed'`, rung: \"implemented\" },\n { ref: `${PB} src/admin.c:1017-1045 and src/objects.c:920-921 during PAUSE a new query gets no server, thus it waits. The janitor still runs query_wait_timeout (src/janitor.c:722-728)`, rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"Before PgBouncer accepts the connection\" },\n login: { note: \"CL_LOGIN: the startup packet and the authentication. PgBouncer reads the socket\" },\n welcome: {\n note: \"CL_WAITING_LOGIN: the client logged in before any server of the pool logged in, and it waits for the parameters of the server. Its socket is not read (src/objects.c:2077-2085)\",\n },\n idle: { note: \"CL_ACTIVE with no server: between two transactions. PgBouncer reads the socket, thus it notices a close at once\" },\n waiting: { note: \"CL_WAITING: a query found no idle server, and the client waits in the queue. PgBouncer does not read its socket\" },\n linked: { note: \"CL_ACTIVE with a server: a query or a transaction in flight. PgBouncer forwards each packet both ways\" },\n ended: { final: true, note: \"PgBouncer closed the client, with a FATAL ErrorResponse for a reason, or the client went\" },\n },\n events: {\n \"local.accept\": { kind: \"local\", note: \"PgBouncer accepts the TCP connection\" },\n \"local.logged-in\": { kind: \"local\", note: \"The authentication of the client ends\" },\n \"local.welcome\": { kind: \"local\", note: \"The first server of the pool logs in: the pool has its welcome message\" },\n \"rx.query\": { kind: \"rx\", note: \"The first packet of a query of the client\" },\n \"local.attached\": { kind: \"local\", note: \"The client gets an idle server of the pool\" },\n \"rx.ready-in-transaction\": { kind: \"rx\", note: \"The server sends ReadyForQuery with the status T or E: the client keeps the server\" },\n \"local.released\": { kind: \"local\", note: \"The server sends ReadyForQuery with the status I, and the client got all of its data: the server goes back to the pool\" },\n \"server.crashed\": { kind: \"peer\", note: \"The socket of the linked server fails: the end of the stream, a reset, or an error\" },\n \"server.send-failed\": { kind: \"peer\", note: \"A send of a packet of the client to its server fails\" },\n \"peer.fin\": { kind: \"peer\", note: \"The client closes its connection: a read gets the end of the stream\" },\n \"peer.rst\": { kind: \"peer\", note: \"A reset of the connection of the client\" },\n \"socket.error\": { kind: \"local\", note: \"The socket of the client fails with its own error\" },\n \"rx.terminate\": { kind: \"rx\", note: \"The Terminate message of the client\" },\n \"admin.kill\": { kind: \"app\", note: \"The KILL command of the console, for the database of the client\" },\n \"tx.fatal\": { kind: \"tx\", note: \"An ErrorResponse with severity FATAL and SQLSTATE 08P01, then the close of the socket\" },\n \"timer.login\": { kind: \"timer\", note: \"A pass of the janitor finds the login older than client_login_timeout\" },\n \"timer.query-wait\": { kind: \"timer\", note: \"A pass of the janitor finds the wait older than query_wait_timeout\" },\n \"timer.idle\": { kind: \"timer\", note: \"A pass of the janitor finds the idle client older than client_idle_timeout\" },\n \"timer.query\": { kind: \"timer\", note: \"A pass of the janitor finds the query older than query_timeout\" },\n \"timer.idle-transaction\": { kind: \"timer\", note: \"A pass of the janitor finds the server idle in the transaction for longer than idle_transaction_timeout\" },\n \"timer.transaction\": { kind: \"timer\", note: \"A pass of the janitor finds the transaction older than transaction_timeout\" },\n },\n knobs: {\n client_login_timeout: { key: \"pgbouncer client_login_timeout\", scope: \"proxy\", unit: \"s\", default: 60, off: 0, note: \"src/main.c:273\" },\n query_wait_timeout: {\n key: \"pgbouncer query_wait_timeout\",\n scope: \"proxy\",\n unit: \"s\",\n default: 120,\n off: 0,\n note: \"src/main.c:316. A setting of the database, then of the user, replaces it (src/janitor.c:328-337)\",\n },\n client_idle_timeout: { key: \"pgbouncer client_idle_timeout\", scope: \"proxy\", unit: \"s\", default: 0, off: 0, note: \"src/main.c:272\" },\n query_timeout: { key: \"pgbouncer query_timeout\", scope: \"proxy\", unit: \"s\", default: 0, off: 0, note: \"src/main.c:314\" },\n idle_transaction_timeout: { key: \"pgbouncer idle_transaction_timeout\", scope: \"proxy\", unit: \"s\", default: 0, off: 0, note: \"src/main.c:289\" },\n transaction_timeout: { key: \"pgbouncer transaction_timeout\", scope: \"proxy\", unit: \"s\", default: 0, off: 0, note: \"src/main.c:356\" },\n janitor: {\n key: \"the period of the janitor of PgBouncer\",\n scope: \"process\",\n unit: \"ms\",\n default: 333.333,\n note: \"src/janitor.c:27-28: USEC / 3 in whole microseconds, 333333 µs. Each timer of a client is a check of a pass, thus it is up to one period late\",\n },\n slack: {\n key: \"the lateness of the loop of events of PgBouncer for one pass\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of PgBouncer: libevent runs the janitor in the one thread of the loop, thus a busy loop delays it\",\n },\n },\n timers: {\n client_login_timeout: {\n duration: { knob: \"client_login_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:login\", \"enter:welcome\"],\n cancels: [\"local.logged-in\", \"local.welcome\"],\n fires: \"timer.login\",\n note: \"src/janitor.c:361-371, :606-622: it counts from the accept of the client in both states, thus the time of the login comes before the wait for the welcome message\",\n },\n query_wait_timeout: {\n duration: { knob: \"query_wait_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:waiting\"],\n cancels: [\"local.attached\"],\n fires: \"timer.query-wait\",\n note: \"src/janitor.c:316-347: from the start of the query, which is the entry to the queue. PAUSE does not stop it\",\n },\n client_idle_timeout: {\n duration: { knob: \"client_idle_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:idle\"],\n cancels: [\"rx.query\"],\n fires: \"timer.idle\",\n note: \"src/janitor.c:293-310: from the last packet of the client. No bound at the defaults\",\n },\n query_timeout: {\n duration: { knob: \"query_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:waiting\", \"enter:linked\"],\n cancels: [\"local.released\", \"rx.ready-in-transaction\"],\n fires: \"timer.query\",\n note: \"src/client.c:1640-1656, src/janitor.c:341-342, :545-546: from the arrival of the query, thus its time in the queue counts. PgBouncer sends no CancelRequest: it closes the server and the client. No bound at the defaults\",\n },\n idle_transaction_timeout: {\n duration: { knob: \"idle_transaction_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"rx.ready-in-transaction\"],\n cancels: [\"rx.query\", \"local.released\"],\n fires: \"timer.idle-transaction\",\n note: \"src/janitor.c:547-550, src/server.c:452-454: from the last packet of the server, while the client sends nothing in its transaction. No bound at the defaults\",\n },\n transaction_timeout: {\n duration: { knob: \"transaction_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:linked\"],\n cancels: [\"local.released\"],\n fires: \"timer.transaction\",\n note: \"src/janitor.c:526, :551-553, src/client.c:1646-1649: from the first query of the transaction. No bound at the defaults\",\n },\n },\n realizes: {\n \"systems.mechanism.server-idle-close\": { timer: \"client_idle_timeout\" },\n \"systems.mechanism.request-timeout\": { timer: \"query_timeout\" },\n },\n transitions: [\n { id: \"pbc.accept\", from: \"[none]\", to: \"login\", on: \"local.accept\", timer: \"client_login_timeout\", source: \"src/objects.c:2025\" },\n { id: \"pbc.logged-in\", from: \"login\", to: \"idle\", on: \"local.logged-in\", guard: \"the pool has its welcome message: a server of the pool logged in before\", source: \"src/objects.c:2077-2085\" },\n {\n id: \"pbc.wait-welcome\",\n from: \"login\",\n to: \"welcome\",\n on: \"local.logged-in\",\n guard: \"no server of the pool logged in yet\",\n note: \"The client is paused, and the pool starts a connection to the server\",\n source: \"src/objects.c:2077-2085\",\n },\n { id: \"pbc.welcome\", from: \"welcome\", to: \"idle\", on: \"local.welcome\", source: \"src/objects.c:1246-1248\" },\n {\n id: \"pbc.login-timed-out\",\n from: \"login\",\n to: \"ended\",\n on: \"timer.login\",\n timer: \"client_login_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'client_login_timeout'\",\n source: \"src/janitor.c:606-622\",\n },\n {\n id: \"pbc.welcome-timed-out\",\n from: \"welcome\",\n to: \"ended\",\n on: \"timer.login\",\n timer: \"client_login_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'client_login_timeout (server down)': no server of the pool logged in\",\n source: \"src/janitor.c:361-371\",\n },\n {\n id: \"pbc.attach\",\n from: \"idle\",\n to: \"linked\",\n on: \"rx.query\",\n guard: \"an idle server is in the pool, and the pool is not paused\",\n timer: \"query_timeout\",\n source: \"src/objects.c:915-975\",\n },\n {\n id: \"pbc.queue\",\n from: \"idle\",\n to: \"waiting\",\n on: \"rx.query\",\n guard: \"no idle server, and no failed login of the pool, or the pool is paused\",\n timer: \"query_wait_timeout\",\n note: \"The client goes to the end of the queue, and its socket is no longer read. The pool starts a connection when it can\",\n source: \"src/objects.c:805-817, :947-988\",\n },\n {\n id: \"pbc.fast-fail\",\n from: \"idle\",\n to: \"ended\",\n on: \"rx.query\",\n guard: \"the last login of the pool failed, and the pool has no server outside a login\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'server login has been failing, cached error: <reason> (server_login_retry)', at once\",\n source: \"src/objects.c:869-900\",\n },\n {\n id: \"pbc.attached\",\n from: \"waiting\",\n to: \"linked\",\n on: \"local.attached\",\n note: \"A server becomes idle or logs in, and the first waiting client gets it. The client then reads its socket again\",\n source: \"src/janitor.c:116-170, src/objects.c:994-1014\",\n },\n {\n id: \"pbc.wait-timed-out\",\n from: \"waiting\",\n to: \"ended\",\n on: \"timer.query-wait\",\n timer: \"query_wait_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'query_wait_timeout'\",\n source: \"src/janitor.c:343-344\",\n },\n {\n id: \"pbc.queued-query-timed-out\",\n from: \"waiting\",\n to: \"ended\",\n on: \"timer.query\",\n timer: \"query_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'query_timeout', before query_wait_timeout\",\n source: \"src/janitor.c:341-342\",\n },\n { id: \"pbc.released\", from: \"linked\", to: \"idle\", on: \"local.released\", timer: \"client_idle_timeout\", source: \"src/server.c:861-921, src/objects.c:1213-1322\" },\n { id: \"pbc.in-transaction\", from: \"linked\", to: \"linked\", on: \"rx.ready-in-transaction\", timer: \"idle_transaction_timeout\", source: \"src/server.c:433-455\" },\n {\n id: \"pbc.server-crashed\",\n from: \"linked\",\n to: \"ended\",\n on: \"server.crashed\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'server conn crashed?'. An ErrorResponse that the server sent before its close reaches the client first\",\n source: \"src/server.c:808-813, src/objects.c:1324-1344, :1375-1379\",\n },\n {\n id: \"pbc.server-send-failed\",\n from: \"linked\",\n to: \"ended\",\n on: \"server.send-failed\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'server connection closed'\",\n source: \"src/client.c:1799-1800\",\n },\n {\n id: \"pbc.query-timed-out\",\n from: \"linked\",\n to: \"ended\",\n on: \"timer.query\",\n timer: \"query_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'query timeout': PgBouncer sends Terminate to the server and closes it\",\n source: \"src/janitor.c:545-546\",\n },\n {\n id: \"pbc.idle-transaction-timed-out\",\n from: \"linked\",\n to: \"ended\",\n on: \"timer.idle-transaction\",\n timer: \"idle_transaction_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'idle transaction timeout'\",\n source: \"src/janitor.c:547-550\",\n },\n {\n id: \"pbc.transaction-timed-out\",\n from: \"linked\",\n to: \"ended\",\n on: \"timer.transaction\",\n timer: \"transaction_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'transaction timeout'\",\n source: \"src/janitor.c:551-553\",\n },\n {\n id: \"pbc.idle-timed-out\",\n from: \"idle\",\n to: \"ended\",\n on: \"timer.idle\",\n timer: \"client_idle_timeout\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'client_idle_timeout'\",\n source: \"src/janitor.c:307-308\",\n },\n {\n id: \"pbc.gone\",\n from: [\"login\", \"idle\", \"linked\"],\n to: \"ended\",\n on: [\"peer.fin\", \"peer.rst\", \"socket.error\", \"rx.terminate\"],\n note: \"'client unexpected eof', or 'client close request' for a Terminate. A linked server that was not ready is closed too\",\n source: \"src/client.c:1558-1560, :1789-1798, src/objects.c:1493-1534\",\n },\n {\n id: \"pbc.killed\",\n from: [\"login\", \"welcome\", \"idle\", \"waiting\", \"linked\"],\n to: \"ended\",\n on: \"admin.kill\",\n errno: \"08P01\",\n emits: [\"tx.fatal\"],\n note: \"'database removed'\",\n source: \"src/janitor.c:788-813\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { login: \"ESTABLISHED\", welcome: \"ESTABLISHED\", idle: \"ESTABLISHED\", waiting: \"ESTABLISHED\", linked: \"ESTABLISHED\" },\n sets: {},\n ends: \"socket.error\",\n note: \"Each socket has TCP_NODELAY and SO_KEEPALIVE. At the defaults PgBouncer sets no time of the keepalive, thus the keepidle, the interval and the count of the namespace apply. A waiting client is not read: the kernel takes its FIN, and PgBouncer does not see it\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { PB, PB_COMMON } from \"./pgbouncer.ts\";\n\n/**\n * This document is PgBouncer 1.26.1 in transaction pooling, for one server connection of a pool:\n * from its launch to its close. It also gives the wait of the pool before its next connection after\n * a failed login.\n *\n * PgBouncer reads the socket of each idle server, thus the end of the stream or a reset of an idle\n * server closes it at once. A black hole stops nothing that PgBouncer reads. Only a check of the\n * server, a timer of the kernel, server_idle_timeout or server_lifetime removes such a server. The\n * check is the empty query before a reuse, when the server was idle for longer than\n * server_check_delay (30 s). It acts at the defaults, and no timer bounds its reply. Thus behind a\n * black hole, the client that waits for the check stays in the queue until its query_wait_timeout.\n *\n * The TCP connect has a timer of libevent of server_connect_timeout, in whole seconds. The janitor\n * also bounds the whole login by server_connect_timeout, from the launch. After a failed login the\n * pool starts no connection for server_login_retry from the launch of the failed one. In that time\n * each client that needs a server fails at once, and a waiting client stays in the queue.\n */\nexport const PGBOUNCER_SERVER: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"pgbouncer-server\",\n title: \"PgBouncer 1.26.1 in transaction pooling: one server connection of a pool, its login, its checks and its close\",\n layer: \"proxy\",\n version: \"1.26.1\",\n conditions: {\n pgbouncer: \"1.26.1\",\n pool_mode: \"transaction, set for the database or the user, or globally\",\n server: \"one PostgreSQL server over TCP, with no TLS, at an address that the configuration gives\",\n },\n sources: [\n ...PB_COMMON,\n { ref: `${PB} include/bouncer.h:69-89 and src/objects.c:292-369 the states of a server, each a list: SV_LOGIN, SV_IDLE, SV_ACTIVE, SV_USED, SV_TESTED. An idle server goes to the head of its list`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1876-1897 launch_new_connection: one connect of a pool at a time, and none for server_login_retry from the launch of a failed one`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1990-2008 the launch sets the time of the connect, before the DNS lookup and the TCP connect`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1638-1641 and src/sbuf.c:163-203, :1064-1102 the TCP connect waits for EV_WRITE with a timeout of libevent of server_connect_timeout in whole seconds. A timeout or an error is 'connect failed' (src/server.c:851-853)`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:558-570 the janitor closes a server in SV_LOGIN that is older than server_connect_timeout, from its launch: 'connect timeout'`, rung: \"implemented\" },\n {\n ref: \"run 39160356281 of mark1russell7/systems: with server_connect_timeout 128 s, the connect timer closed the socket 127.998993 s after its SYN in 1 of 11 runs, 1.007 ms before 128 s. libevent 2.1 counts a timeout from its cached time of the pass (event.c event_add_nolock, gettime with tv_cache)\",\n rung: \"observed\",\n },\n { ref: `${PB} src/objects.c:1385-1393, :1246-1248 a server in a login that closes marks the pool as failing, with the reason. A login that ends clears it`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:74-119, :176-199 an ErrorResponse at the login closes each waiting client of a pool with no server, except for 57P03`, rung: \"implemented\" },\n { ref: `${PB} src/sbuf.c:494-506, :965-973 the socket of a server is always read: an idle server is not paused`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:806-815 the end of the stream or an error of the socket of a server: 'server conn crashed?', with no Terminate`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:394-431, :469-478 the unused servers: server_idle_timeout from the last packet of the server, then server_lifetime from the launch, then server_check_delay, which makes an idle server SV_USED`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:59-99 launch_recheck: a client that finds only SV_USED servers makes the pool send the check query, SV_TESTED. The default <empty> sends the empty query (src/main.c:490-492), and only an empty string turns the check off (src/janitor.c:77-78, :426)`, rung: \"implemented\" },\n { ref: `${PB} src/server.c:888-914 the reply of the check makes the server idle again`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1186-1210, :1268-1273 server_lifetime also closes a server at its release, one at a time each server_lifetime / pool_size`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1213-1322 the release: the server goes back to the head of the idle list, and the first waiting client gets it at once`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:1498-1532 a client that goes while linked: a server that was not ready is closed with Terminate, else it goes back to the pool`, rung: \"implemented\" },\n { ref: `${PB} src/janitor.c:177-192, :424-425 PAUSE closes each idle server: 'pause mode'`, rung: \"implemented\" },\n { ref: `${PB} src/objects.c:2311-2424 and src/loader.c:394-419 RECONNECT, or a RELOAD that changes the connection of a database, marks each server: an idle one closes at the next pass, a linked one at its release`, rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"No connection: the pool starts one for a waiting client, or for min_pool_size\" },\n connecting: { note: \"SV_LOGIN: the TCP connect, with the timer of libevent\" },\n login: { note: \"SV_LOGIN: the startup, the authentication and the first ReadyForQuery. The janitor bounds it from the launch\" },\n idle: { note: \"SV_IDLE: in the pool, ready for a client. PgBouncer reads its socket, thus it notices a close at once\" },\n used: { note: \"SV_USED: idle for longer than server_check_delay. A client that finds it waits for its check\" },\n tested: { note: \"SV_TESTED: the check query in flight. No timer bounds the wait for its reply\" },\n active: { note: \"SV_ACTIVE: linked to a client, for a query or a transaction\" },\n backoff: { note: \"The last login of the pool failed: no new connection for server_login_retry from the launch of that one\" },\n ended: { final: true, note: \"PgBouncer closed the server, with Terminate for a timer, or with no message after an error of the socket\" },\n },\n events: {\n \"local.launch\": { kind: \"local\", note: \"The pool starts a connection to the server\" },\n \"socket.connect\": { kind: \"local\", note: \"The TCP connect ends\" },\n \"rx.error-response\": { kind: \"rx\", note: \"An ErrorResponse of the server at the login\" },\n \"rx.ready-for-query\": { kind: \"rx\", note: \"A ReadyForQuery of the server\" },\n \"local.attached\": { kind: \"local\", note: \"A client gets the server\" },\n \"local.check\": { kind: \"local\", note: \"A client finds only servers that need a check\" },\n \"local.released\": { kind: \"local\", note: \"The server sends ReadyForQuery with the status I, and its data has gone to the client\" },\n \"client.gone\": { kind: \"peer\", note: \"The linked client closes or fails\" },\n \"client.timed-out\": { kind: \"local\", note: \"query_timeout, idle_transaction_timeout or transaction_timeout of the linked client\" },\n \"peer.fin\": { kind: \"peer\", note: \"The server closes the connection: a read gets the end of the stream\" },\n \"peer.rst\": { kind: \"peer\", note: \"A reset of the connection of the server\" },\n \"socket.error\": { kind: \"local\", note: \"The socket of the server fails with its own error\" },\n \"admin.pause\": { kind: \"app\", note: \"The PAUSE command of the console\" },\n \"admin.reconnect\": { kind: \"app\", note: \"RECONNECT, or a RELOAD that changes the connection of the database\" },\n \"tx.check\": { kind: \"tx\", note: \"The check query: the empty query at the defaults\" },\n \"tx.terminate\": { kind: \"tx\", note: \"The Terminate message, then the close of the socket\" },\n \"timer.connect-timeout\": { kind: \"timer\", note: \"The timer of libevent of the TCP connect fires\" },\n \"timer.login-timeout\": { kind: \"timer\", note: \"A pass of the janitor finds the login older than server_connect_timeout\" },\n \"timer.login-retry\": { kind: \"timer\", note: \"server_login_retry has passed since the launch of the failed connection\" },\n \"timer.idle\": { kind: \"timer\", note: \"A pass of the janitor finds the server idle for longer than server_idle_timeout\" },\n \"timer.lifetime\": { kind: \"timer\", note: \"A pass of the janitor finds the server older than server_lifetime\" },\n \"timer.check-delay\": { kind: \"timer\", note: \"A pass of the janitor finds the server idle for longer than server_check_delay\" },\n },\n knobs: {\n server_connect_timeout: {\n key: \"pgbouncer server_connect_timeout\",\n scope: \"proxy\",\n unit: \"s\",\n default: 15,\n off: 0,\n note: \"src/main.c:324. The TCP connect gets it in whole seconds (src/objects.c:1640-1641). At 0 the janitor does not bound the login (src/janitor.c:559)\",\n },\n server_login_retry: { key: \"pgbouncer server_login_retry\", scope: \"proxy\", unit: \"s\", default: 15, note: \"src/main.c:328\" },\n server_idle_timeout: {\n key: \"pgbouncer server_idle_timeout\",\n scope: \"proxy\",\n unit: \"s\",\n default: 600,\n off: 0,\n note: \"src/main.c:326. It has no effect while the pool is at min_pool_size or below (src/janitor.c:417)\",\n },\n server_lifetime: { key: \"pgbouncer server_lifetime\", scope: \"proxy\", unit: \"s\", default: 3600, note: \"src/main.c:327. At 0 a server is used one time (src/objects.c:1195-1207)\" },\n server_check_delay: {\n key: \"pgbouncer server_check_delay\",\n scope: \"proxy\",\n unit: \"s\",\n default: 30,\n note: \"src/main.c:322. The check needs a server_check_query that is not the empty string. Its default, the literal <empty>, sends the empty query, thus the check acts at the defaults (src/main.c:323, :490-492, src/janitor.c:77-91, :426)\",\n },\n janitor: { key: \"the period of the janitor of PgBouncer\", scope: \"process\", unit: \"ms\", default: 333.333, note: \"src/janitor.c:27-28: USEC / 3 in whole microseconds, 333333 µs\" },\n slack: {\n key: \"the lateness of the loop of events of PgBouncer for one pass\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of PgBouncer, as for the client\",\n },\n },\n timers: {\n connect_timeout: {\n duration: { knob: \"server_connect_timeout\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n early: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:connecting\"],\n cancels: [\"socket.connect\", \"socket.error\", \"peer.rst\"],\n fires: \"timer.connect-timeout\",\n note: \"src/objects.c:1640-1641, src/sbuf.c:163-203: a timeout of libevent on the wait for EV_WRITE, in whole seconds. Which clock libevent reads is an assumption of this document: the monotonic one. libevent counts the timeout from the time that it caches for the callbacks of one pass of its loop, thus from up to one pass before the connect: the timer can fire up to that pass early\",\n },\n login_timeout: {\n duration: { knob: \"server_connect_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:login\"],\n cancels: [\"rx.ready-for-query\", \"rx.error-response\", \"socket.error\", \"peer.rst\", \"peer.fin\"],\n fires: \"timer.login-timeout\",\n note: \"src/janitor.c:558-570: from the launch, thus the DNS lookup and the TCP connect come first. In the connect the timer of libevent fires first\",\n },\n login_retry: {\n duration: { knob: \"server_login_retry\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:backoff\"],\n fires: \"timer.login-retry\",\n note: \"src/objects.c:1889-1897: from the launch of the failed connection, not from its failure. A pool with a waiting client starts the next connection at the first loop after it\",\n },\n server_idle_timeout: {\n duration: { knob: \"server_idle_timeout\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:idle\"],\n cancels: [\"local.attached\"],\n fires: \"timer.idle\",\n note: \"src/janitor.c:408, :416-418: from the last packet of the server\",\n },\n server_lifetime: {\n duration: { knob: \"server_lifetime\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"local.launch\"],\n fires: \"timer.lifetime\",\n note: \"src/janitor.c:419-423, src/objects.c:1186-1210: from the launch, on an unused server. A linked server is not closed for its lifetime until its release\",\n },\n check_delay: {\n duration: { knob: \"server_check_delay\", unit: \"s\" },\n lateness: { expr: \"janitor + slack\", unit: \"ms\" },\n arms: [\"enter:idle\"],\n cancels: [\"local.attached\"],\n fires: \"timer.check-delay\",\n note: \"src/janitor.c:426-428: at the defaults, the check of the empty query. A server_check_query of the empty string turns it off\",\n },\n },\n realizes: {\n \"systems.mechanism.connect-bound\": { timer: \"connect_timeout\" },\n \"systems.mechanism.pool-idle-expiry\": { timer: \"server_idle_timeout\" },\n \"systems.mechanism.max-connection-age\": { timer: \"server_lifetime\" },\n },\n transitions: [\n {\n id: \"pbs.launch\",\n from: \"[none]\",\n to: \"connecting\",\n on: \"local.launch\",\n guard: \"no connect of the pool is in progress\",\n timer: \"connect_timeout\",\n source: \"src/objects.c:1876-1887, :1990-2008\",\n },\n { id: \"pbs.connected\", from: \"connecting\", to: \"login\", on: \"socket.connect\", timer: \"login_timeout\", source: \"src/sbuf.c:1064-1102, src/server.c:851-858\" },\n {\n id: \"pbs.connect-failed\",\n from: \"connecting\",\n to: \"backoff\",\n on: [\"socket.error\", \"peer.rst\", \"timer.connect-timeout\"],\n timer: \"login_retry\",\n errno: \"connect failed\",\n note: \"The pool caches the reason. A client that needs a server and finds none then fails at once\",\n source: \"src/server.c:851-853, src/objects.c:1385-1393, :869-900\",\n },\n {\n id: \"pbs.login-timed-out\",\n from: \"login\",\n to: \"backoff\",\n on: \"timer.login-timeout\",\n timer: \"login_retry\",\n errno: \"connect timeout\",\n source: \"src/janitor.c:558-570, src/objects.c:1385-1393\",\n },\n {\n id: \"pbs.login-failed\",\n from: \"login\",\n to: \"backoff\",\n on: [\"rx.error-response\", \"peer.fin\", \"peer.rst\", \"socket.error\"],\n timer: \"login_retry\",\n note: \"An ErrorResponse closes each waiting client of a pool with no server, with the SQLSTATE of the server, except 57P03\",\n source: \"src/server.c:74-119, :176-199\",\n },\n { id: \"pbs.retry\", from: \"backoff\", to: \"connecting\", on: \"timer.login-retry\", guard: \"a client waits for a server\", timer: \"connect_timeout\", source: \"src/objects.c:1889-1897, src/janitor.c:166-170\" },\n {\n id: \"pbs.logged-in\",\n from: \"login\",\n to: \"idle\",\n on: \"rx.ready-for-query\",\n timer: \"server_idle_timeout\",\n note: \"The pool gets its welcome message, and the first waiting client gets the server at once\",\n source: \"src/objects.c:1246-1248, :994-1014\",\n },\n { id: \"pbs.attach\", from: \"idle\", to: \"active\", on: \"local.attached\", source: \"src/objects.c:934-975\" },\n {\n id: \"pbs.release\",\n from: \"active\",\n to: \"idle\",\n on: \"local.released\",\n guard: \"the server is younger than server_lifetime and has no close_needed\",\n timer: \"server_idle_timeout\",\n source: \"src/server.c:861-921, src/objects.c:1213-1322\",\n },\n {\n id: \"pbs.close-at-release\",\n from: \"active\",\n to: \"ended\",\n on: \"local.released\",\n guard: \"the server is older than server_lifetime, or has close_needed\",\n emits: [\"tx.terminate\"],\n note: \"'server lifetime over' or 'close_needed'\",\n source: \"src/objects.c:1268-1291\",\n },\n {\n id: \"pbs.crashed\",\n from: [\"login\", \"idle\", \"used\", \"tested\", \"active\"],\n to: \"ended\",\n on: [\"peer.fin\", \"peer.rst\", \"socket.error\"],\n note: \"'server conn crashed?'. A linked client gets it as FATAL 08P01 and is closed. An idle server goes with no effect on a client\",\n source: \"src/server.c:806-815, src/objects.c:1375-1384\",\n },\n { id: \"pbs.idle-timed-out\", from: [\"idle\", \"used\", \"tested\"], to: \"ended\", on: \"timer.idle\", emits: [\"tx.terminate\"], note: \"'server idle timeout'\", source: \"src/janitor.c:416-418\" },\n { id: \"pbs.lifetime-over\", from: [\"idle\", \"used\", \"tested\"], to: \"ended\", on: \"timer.lifetime\", emits: [\"tx.terminate\"], note: \"'server lifetime over'\", source: \"src/janitor.c:419-423\" },\n { id: \"pbs.check-due\", from: \"idle\", to: \"used\", on: \"timer.check-delay\", guard: \"server_check_query is not the empty string: its default <empty> is the empty query\", source: \"src/janitor.c:426-428, src/main.c:490-492\" },\n { id: \"pbs.check\", from: \"used\", to: \"tested\", on: \"local.check\", emits: [\"tx.check\"], source: \"src/janitor.c:59-99\" },\n { id: \"pbs.checked\", from: \"tested\", to: \"idle\", on: \"rx.ready-for-query\", timer: \"server_idle_timeout\", source: \"src/server.c:888-914\" },\n {\n id: \"pbs.client-gone-dirty\",\n from: \"active\",\n to: \"ended\",\n on: \"client.gone\",\n guard: \"the server was not ready: a query or a transaction in flight\",\n emits: [\"tx.terminate\"],\n note: \"'client disconnect while server was not ready'\",\n source: \"src/objects.c:1498-1512\",\n },\n { id: \"pbs.client-gone-clean\", from: \"active\", to: \"idle\", on: \"client.gone\", guard: \"the server was ready\", timer: \"server_idle_timeout\", source: \"src/objects.c:1529-1532\" },\n { id: \"pbs.client-timed-out\", from: \"active\", to: \"ended\", on: \"client.timed-out\", emits: [\"tx.terminate\"], note: \"The timer of the client closes the server too\", source: \"src/janitor.c:545-553\" },\n { id: \"pbs.paused\", from: [\"idle\", \"used\"], to: \"ended\", on: \"admin.pause\", emits: [\"tx.terminate\"], note: \"'pause mode'. A linked server stays until its release\", source: \"src/janitor.c:177-192\" },\n {\n id: \"pbs.reconnect\",\n from: [\"idle\", \"used\"],\n to: \"ended\",\n on: \"admin.reconnect\",\n emits: [\"tx.terminate\"],\n note: \"'database configuration changed'. A linked server closes at its release\",\n source: \"src/janitor.c:410-411, src/objects.c:1287-1291\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { connecting: \"SYN_SENT\", login: \"ESTABLISHED\", idle: \"ESTABLISHED\", used: \"ESTABLISHED\", tested: \"ESTABLISHED\", active: \"ESTABLISHED\" },\n sets: {},\n ends: \"socket.error\",\n note: \"As for the client: TCP_NODELAY and SO_KEEPALIVE, with the times of the keepalive of the namespace at the defaults. PgBouncer reads each server socket, thus the kernel's end of a socket reaches it at once\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the C source of Pgpool-II at the tag V4_7_3 (commit\n// 07d24655e42dfdbfe2e7549df6166e057b99b622, the tarball of GitHub with SHA-256 e48ff26f...e2acd2).\n// Each line number is a line of that file at the tag. A fact of the kernel is an assumption of this\n// document, and its note says so.\nexport const PP = \"V4_7_3\";\n\n/**\n * This document is Pgpool-II 4.7.3 with one backend, for one session of a client. It gives the states\n * of the session in its child process, from the accept of the client to its close. It also gives the\n * timers that act on it.\n *\n * A child process serves one client at a time. Between two queries it waits in one select() on the\n * client and on the backend. Thus the close of either side ends the session at once. At the defaults\n * no timer bounds an idle session: client_idle_limit is 0.\n *\n * While a query is in flight, the child waits on the backend only. It does not read the client, and\n * no timer of Pgpool-II ends the query. Each 30 s of that wait, it writes a dummy ParameterStatus to\n * the client, and a failed write ends the session.\n *\n * An error of a session reaches the client as an ErrorResponse, with the SQLSTATE of Pgpool-II or\n * XX000. The FIN of the backend ends the session with a FATAL error. A failed read of the backend,\n * for example a reset, and a failed connect to the backend ask the main process for a failover\n * (failover_on_backend_error).\n */\nexport const PGPOOL_SESSION: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"pgpool-session\",\n title: \"Pgpool-II 4.7.3 with one backend: one session of a client in its child process\",\n layer: \"proxy\",\n version: \"4.7.3\",\n conditions: {\n pgpool: \"4.7.3\",\n backend_clustering_mode: \"streaming_replication, the default, with one backend\",\n client: \"a PostgreSQL client over TCP, with no TLS\",\n backend: \"one PostgreSQL server\",\n },\n sources: [\n {\n ref: `${PP} src/config/pool_config_variables.c:570-607, :1661-1761, :2003-2121, :2388-2396 the defaults: connection_cache on, failover_on_backend_error on, failover_on_backend_shutdown off, health_check_period 0, health_check_timeout 20 s, connect_timeout 10000 ms, num_init_children 32, child_life_time 300 s, client_idle_limit 0, connection_life_time 0, authentication_timeout 60 s, max_pool 4, backend_clustering_mode streaming_replication`,\n rung: \"implemented\",\n },\n { ref: `${PP} src/protocol/pool_connection_pool.c:849 and src/protocol/child.c:1789, :1981 each socket to the backend and to the client gets TCP_NODELAY. Only the watchdog sets SO_KEEPALIVE (src/watchdog/watchdog.c:961, :1089)`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/child.c:163-516 do_child: wait for a client, check that a backend is up, connect or reuse the backend, then the loop of pool_process_query until the session ends`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/child.c:617-632, :800, :1281-1310 authentication_timeout: an alarm over the read of the startup packet. Its expiry exits the child`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/child.c:2016-2170 get_backend_connection: the startup packet, then a connection of the pool of the child for the same user, database and startup packet, else a new connect. With enable_pool_hba off, the backend does the authentication`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/child.c:344-353, :1670-1691 child_life_time counts the 1 s timeouts of a child that waits for a client: it never ends a session`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/pool_connection_pool.c:590-669 the connect to the backend is non-blocking, and one select() bounds it by connect_timeout. At 0 it has no bound`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/pool_connection_pool.c:953-1012 a failed connect to the backend: with failover_on_backend_error, a request of failover, then FATAL 'failed to create a backend connection'`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/pool_process_query.c:4867-5002 between two queries: one select() on the client and on each backend. With client_idle_limit, its timeout is 1 s, and more than client_idle_limit timeouts end the session with 57000`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/pool_process_query.c:5004-5146 a backend that is readable between two queries: its error or its end is read at once`, rung: \"implemented\" },\n { ref: `${PP} src/protocol/pool_process_query.c:539-627 and src/context/pool_query_context.c:658-693, :877-911 each query waits for its backend in steps of 30 s. After each step with no data, a dummy ParameterStatus goes to the client, and a failed flush ends the session`, rung: \"implemented\" },\n { ref: `${PP} src/utils/pool_stream.c:1303-1387 pool_check_fd: one select() with the timeout of the step, or none`, rung: \"implemented\" },\n { ref: `${PP} src/utils/pool_stream.c:225-248 a failed read of the backend: with failover_on_backend_error, a request of failover, then the child exits`, rung: \"implemented\" },\n { ref: `${PP} src/utils/pool_stream.c:263-276 a read of 0 bytes from the backend, its FIN: FATAL 'unable to read data from DB node', and no failover`, rung: \"implemented\" },\n { ref: `${PP} src/utils/error/elog.c:1888-2007 an error of the session goes to the client as an ErrorResponse: its severity, the SQLSTATE of Pgpool-II or XX000, and the message`, rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"Before the child accepts the connection\" },\n login: { note: \"The read of the startup packet. The alarm of authentication_timeout runs\" },\n connecting: { note: \"The connect to the backend and its authentication, when the pool of the child has no connection for the user and the database. The select() of the connect is bounded by connect_timeout\" },\n idle: { note: \"Between two queries: one select() on the client and on the backend, thus a close of either side is read at once\" },\n waiting: { note: \"A query in flight: the child waits on the backend only, in steps of 30 s. It does not read the client\" },\n ended: { final: true, note: \"The child closed the client, after an ErrorResponse for an error, or the client went\" },\n },\n events: {\n \"local.accept\": { kind: \"local\", note: \"The child accepts the TCP connection\" },\n \"rx.startup\": { kind: \"rx\", note: \"The startup packet of the client\" },\n \"local.cached\": { kind: \"local\", note: \"The pool of the child has a connection for the user and the database: no connect\" },\n \"local.connected\": { kind: \"local\", note: \"The connect to the backend succeeds\" },\n \"rx.query\": { kind: \"rx\", note: \"The first packet of a query of the client\" },\n \"rx.ready-for-query\": { kind: \"rx\", note: \"The backend sends ReadyForQuery: the end of the query\" },\n \"backend.eof\": { kind: \"peer\", note: \"A read of the backend gets 0 bytes: its FIN\" },\n \"backend.error\": { kind: \"peer\", note: \"A read or a select() of the backend fails: a reset, or an error of the socket\" },\n \"frontend.eof\": { kind: \"peer\", note: \"The client closes its connection, or a write to it fails\" },\n \"timer.auth\": { kind: \"timer\", note: \"The alarm of authentication_timeout\" },\n \"timer.connect\": { kind: \"timer\", note: \"The select() of the connect to the backend times out\" },\n \"timer.idle\": { kind: \"timer\", note: \"More than client_idle_limit timeouts of 1 s of the select() between two queries\" },\n \"timer.probe\": { kind: \"timer\", note: \"A step of 30 s of the wait for the backend ends with no data\" },\n \"tx.error\": { kind: \"tx\", note: \"An ErrorResponse: its severity, the SQLSTATE of Pgpool-II or XX000, and the message\" },\n \"tx.probe\": { kind: \"tx\", note: \"A dummy ParameterStatus to the client: pgpool_dummy_param = pgpool_dummy_value\" },\n \"tx.failover\": { kind: \"local\", note: \"A request of failover for the backend to the main process\" },\n },\n knobs: {\n authentication_timeout: { key: \"pgpool authentication_timeout\", scope: \"proxy\", unit: \"s\", default: 60, off: 0, note: \"src/config/pool_config_variables.c:2102-2110\" },\n connect_timeout: { key: \"pgpool connect_timeout\", scope: \"proxy\", unit: \"ms\", default: 10000, off: 0, note: \"src/config/pool_config_variables.c:1745-1761. It bounds the connect to the backend\" },\n client_idle_limit: { key: \"pgpool client_idle_limit\", scope: \"proxy\", unit: \"s\", default: 0, off: 0, note: \"src/config/pool_config_variables.c:2069-2077\" },\n tick: {\n key: \"the timeout of the select() between two queries when client_idle_limit is set\",\n scope: \"process\",\n unit: \"s\",\n default: 1,\n note: \"src/protocol/pool_process_query.c:4938-4947: a constant of the source, not a setting\",\n },\n probe: {\n key: \"the step of the wait for the backend of a query\",\n scope: \"process\",\n unit: \"s\",\n default: 30,\n note: \"src/protocol/pool_process_query.c:561: a constant of the source, not a setting\",\n },\n slack: {\n key: \"the lateness of the loop of the child for one step\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of Pgpool-II: the child does each step in one process with no other work\",\n },\n },\n timers: {\n authentication_timeout: {\n duration: { knob: \"authentication_timeout\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:login\"],\n cancels: [\"rx.startup\"],\n fires: \"timer.auth\",\n note: \"src/protocol/child.c:617-632, :1281-1310: alarm() in whole seconds\",\n },\n connect_timeout: {\n duration: { knob: \"connect_timeout\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:connecting\"],\n cancels: [\"local.connected\", \"backend.error\"],\n fires: \"timer.connect\",\n note: \"src/protocol/pool_connection_pool.c:645-669\",\n },\n client_idle_limit: {\n duration: { expr: \"client_idle_limit + tick\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:idle\"],\n cancels: [\"rx.query\"],\n fires: \"timer.idle\",\n note: \"src/protocol/pool_process_query.c:4962-4976: each timeout of 1 s counts, and the count must exceed client_idle_limit, thus the session ends one tick after the limit. Each packet starts the count again. No bound at the defaults\",\n },\n probe: {\n duration: { knob: \"probe\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:waiting\"],\n cancels: [\"rx.ready-for-query\"],\n fires: \"timer.probe\",\n backoff: { resets: [\"enter:waiting\"] },\n note: \"src/protocol/pool_process_query.c:558-595: each wait is 30 s, the same each time. It does not end the query: it checks the client\",\n },\n },\n transitions: [\n { id: \"pps.accept\", from: \"[none]\", to: \"login\", on: \"local.accept\", timer: \"authentication_timeout\", source: \"src/protocol/child.c:342-398\" },\n { id: \"pps.reuse\", from: \"login\", to: \"idle\", on: \"local.cached\", guard: \"the pool of the child has a connection for the user, the database and the same startup packet (connection_cache)\", timer: \"client_idle_limit\", source: \"src/protocol/child.c:2112-2166\" },\n { id: \"pps.connect\", from: \"login\", to: \"connecting\", on: \"rx.startup\", guard: \"no connection in the pool of the child\", timer: \"connect_timeout\", source: \"src/protocol/child.c:2153-2160, src/protocol/pool_connection_pool.c:907-955\" },\n { id: \"pps.connected\", from: \"connecting\", to: \"idle\", on: \"local.connected\", timer: \"client_idle_limit\", source: \"src/protocol/pool_connection_pool.c:1013-1019\" },\n {\n id: \"pps.connect-failed\",\n from: \"connecting\",\n to: \"ended\",\n on: [\"timer.connect\", \"backend.error\"],\n errno: \"XX000\",\n emits: [\"tx.failover\", \"tx.error\"],\n note: \"FATAL 'failed to create a backend connection', 'executing failover on backend'\",\n source: \"src/protocol/pool_connection_pool.c:953-969\",\n },\n {\n id: \"pps.auth-timed-out\",\n from: \"login\",\n to: \"ended\",\n on: \"timer.auth\",\n timer: \"authentication_timeout\",\n note: \"The child exits\",\n source: \"src/protocol/child.c:1281-1287\",\n },\n { id: \"pps.query\", from: \"idle\", to: \"waiting\", on: \"rx.query\", timer: \"probe\", source: \"src/context/pool_query_context.c:658-693, :877-911\" },\n { id: \"pps.reply\", from: \"waiting\", to: \"idle\", on: \"rx.ready-for-query\", timer: \"client_idle_limit\", source: \"src/protocol/pool_process_query.c:558-626\" },\n { id: \"pps.probe\", from: \"waiting\", to: \"waiting\", on: \"timer.probe\", timer: \"probe\", emits: [\"tx.probe\"], note: \"The dummy ParameterStatus, each 30 s of the wait\", source: \"src/protocol/pool_process_query.c:570-595\" },\n {\n id: \"pps.idle-timed-out\",\n from: \"idle\",\n to: \"ended\",\n on: \"timer.idle\",\n timer: \"client_idle_limit\",\n errno: \"57000\",\n emits: [\"tx.error\"],\n note: \"'child connection forced to terminate due to client_idle_limit:%d is reached'\",\n source: \"src/protocol/pool_process_query.c:4965-4976\",\n },\n {\n id: \"pps.backend-eof\",\n from: [\"idle\", \"waiting\"],\n to: \"ended\",\n on: \"backend.eof\",\n errno: \"XX000\",\n emits: [\"tx.error\"],\n note: \"FATAL 'unable to read data from DB node', 'EOF encountered with backend', with no request of failover\",\n source: \"src/utils/pool_stream.c:263-276, src/protocol/pool_process_query.c:5021-5146\",\n },\n {\n id: \"pps.backend-error\",\n from: [\"idle\", \"waiting\"],\n to: \"ended\",\n on: \"backend.error\",\n emits: [\"tx.failover\"],\n note: \"The child exits before it reports the error, thus the client gets the close only\",\n source: \"src/utils/pool_stream.c:225-248\",\n },\n {\n id: \"pps.gone\",\n from: [\"login\", \"idle\", \"waiting\"],\n to: \"ended\",\n on: \"frontend.eof\",\n note: \"Between two queries the child reads the close at once. In a wait it finds it only at the write of a probe or of the reply\",\n source: \"src/protocol/pool_process_query.c:570-595, :4895-4933\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { login: \"ESTABLISHED\", connecting: \"ESTABLISHED\", idle: \"ESTABLISHED\", waiting: \"ESTABLISHED\" },\n sets: {},\n ends: \"frontend.eof\",\n note: \"The socket of the client. It has TCP_NODELAY and no SO_KEEPALIVE. In a wait the child does not read it: the kernel takes its FIN, and Pgpool-II finds it at the next write\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the source of PostgreSQL at the tag REL_17_11. Each line number\n// is a line of that file at that tag. A ref under doc/ is the documentation at the same tag.\nconst AT = \"postgresql REL_17_11 src\";\nconst DOC = \"postgresql REL_17_11 doc/src/sgml\";\n\n/**\n * This document is the hold of a PostgreSQL 17.11 backend on one client connection, over its TCP\n * socket on Linux. The backend turns on SO_KEEPALIVE for each TCP socket. At the defaults of its\n * four TCP GUCs, it changes no keepalive option and no user timeout. Thus the namespace sysctls\n * give the idle time, the interval and the count. A GUC above 0 sets its socket option.\n *\n * Each timer of a backend is a SIGALRM timeout. At startup, the handler ends the process at once.\n * After the startup packet, each handler sets a flag and the latch, directly or by a signal. The\n * backend then acts at its next CHECK_FOR_INTERRUPTS. An idle timer and the transaction timer end\n * the session with FATAL. The statement timer and the lock timer end the statement with ERROR.\n *\n * A send to a slow or a lost client waits for the socket with no timeout. In that wait the\n * backend acts on SIGTERM and on the death of the postmaster only. A timer that fires there takes\n * effect after the send. Thus PostgreSQL gives no bound to a send: the kernel ends it, or SIGTERM\n * does.\n *\n * A timeout knob at 0 has no timer: give it as no bound (`infinite`). This is true of\n * `statement_timeout`, `lock_timeout`, `transaction_timeout`, `idle_in_transaction_session_timeout`,\n * `idle_session_timeout` and `client_connection_check_interval`.\n */\nexport const POSTGRES_SESSION: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"postgres-session\",\n title: \"A client connection as a PostgreSQL 17.11 backend holds it, over its Linux socket\",\n layer: \"server\",\n version: \"17.11\",\n conditions: {\n postgresql: \"17.11\",\n os: \"linux\",\n image: \"postgres:17.11 (Debian trixie), index sha256:2d2b8998d31037bf721cfdf764d76ba74171b4fab3431b7f72c27c56ddbdf9e3\",\n socket: \"TCP: on a Unix-domain socket the backend sets no keepalive option\",\n },\n sources: [\n { ref: \"postgresql REL_17_11 meson.build:11 version 17.11\", rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/backend_startup.c:157-161 BackendInitialize calls pq_init in the backend, before the startup packet`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:793-817 AcceptConnection in the postmaster, :180 the Port starts at zeros, :195-220 TCP_NODELAY and SO_KEEPALIVE on each socket that is not AF_UNIX, a failure is FATAL, :264-274 then the four TCP GUCs, a failure is a LOG only`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:1663-1711 pq_setkeepalivesidle: no call at a value equal to the Port's, and 0 sets the value that getsockopt read first; :1748-1795, :1827-1870 and :1902-1945 the same for TCP_KEEPINTVL, TCP_KEEPCNT and TCP_USER_TIMEOUT`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:87-90 TCP_KEEPIDLE on Linux, :1947-2047 an assign hook sets the socket of the session at once, and a show hook reads the kernel`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/misc/guc_tables.c:3452-3461 tcp_keepalives_idle 0 s, :3463-3472 tcp_keepalives_interval 0 s, :3485-3495 tcp_keepalives_count 0, :3587-3596 tcp_user_timeout 0 ms: each PGC_USERSET, 0 to INT_MAX, 0 is the system default`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/misc/guc_tables.c:2611-2620 statement_timeout, :2622-2631 lock_timeout, :2633-2642 idle_in_transaction_session_timeout, :2644-2653 transaction_timeout, :2655-2664 idle_session_timeout: each 0 ms, 0 to INT_MAX, PGC_USERSET, 0 turns it off`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/misc/guc_tables.c:2774-2783 authentication_timeout 60 s, 1 to 600, PGC_SIGHUP; :3632-3641 client_connection_check_interval 0 ms, 0 to INT_MAX, PGC_USERSET`, rung: \"implemented\" },\n { ref: `${AT}/backend/storage/lmgr/proc.c:58-62, backend/tcop/postgres.c:106 and backend/postmaster/postmaster.c:228 the C defaults agree: 0 ms for each timeout, 0 ms for the client check, 60 s for authentication`, rung: \"implemented\" },\n { ref: `${AT}/include/utils/timeout.h:3-4 and :23-43 one SIGALRM for each timeout id, STARTUP_PACKET_TIMEOUT to CLIENT_CONNECTION_CHECK_TIMEOUT`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/misc/timeout.c:559-575 enable_timeout_after: the deadline is the current time + the delay in ms, :209-350 schedule_alarm: setitimer(ITIMER_REAL) for the nearest deadline, :363-453 handle_sig_alarm sets the latch and calls each handler that is due`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/init/postinit.c:770-782 the handlers of a backend, :1374-1407 the statement timer sends SIGINT, or SIGTERM in authentication, and the lock timer sends SIGINT, :1409-1447 each other handler sets a flag and the latch`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:2999-3023 die (SIGTERM) sets ProcDiePending, :3029-3043 StatementCancelHandler (SIGINT) sets QueryCancelPending, :4292-4294 the two handlers`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:3271-3319 ProcessInterrupts acts on a die request first: FATAL 57014 \"canceling authentication due to timeout\" in authentication, else FATAL 57P01 \"terminating connection due to administrator command\"`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:3321-3350 then the client check, then a lost connection: FATAL 08006 \"connection to client lost\", with no message to the client`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:3372-3430 a cancel: ERROR 55P03 \"canceling statement due to lock timeout\", ERROR 57014 \"canceling statement due to statement timeout\"`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:3435-3477 FATAL 25P03 \"terminating connection due to idle-in-transaction timeout\", FATAL 25P04 \"terminating connection due to transaction timeout\", FATAL 57P05 \"terminating connection due to idle-session timeout\"`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/errcodes.txt:106-107 08003 and 08006, :111 08P01, :254-255 25P03 and 25P04, :421 55P03, :428-429 57014 and 57P01, :433 57P05`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:4618-4706 at ReadyForQuery the backend arms idle_in_transaction_session_timeout in a transaction block, open or aborted, and idle_session_timeout outside one; :4714-4750 after a message it disarms them, then checks for interrupts`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:2770-2796 start_xact_command arms statement_timeout and the client check, each only when not active, :2798-2802 finish_xact_command disarms statement_timeout, :5251-5278 no statement timer when statement_timeout >= transaction_timeout > 0`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/adt/misc.c:391-412 pg_sleep: CHECK_FOR_INTERRUPTS before each WaitLatch on the latch of the backend, thus the SIGALRM of a timeout ends its wait`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:4446-4502 an ERROR: disable_all_timeouts, the error to the client, AbortCurrentTransaction; :4562-4563 then ReadyForQuery`, rung: \"implemented\" },\n { ref: `${AT}/backend/access/transam/xact.c:2174-2176 StartTransaction arms transaction_timeout, :2315-2317, :2592-2594 and :2768-2770 commit, prepare and abort disarm it, :3472-3477 an error in a transaction block aborts the transaction and keeps the block`, rung: \"implemented\" },\n { ref: `${AT}/backend/storage/lmgr/proc.c:1292-1307 ProcSleep arms lock_timeout with the deadlock timer, :1652-1666 and disarms it after the wait`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:3652-3661 a client_connection_check_interval above 0 needs a wait set that reports a close`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:2049-2084 pq_check_connection: a wait of 0 ms for WL_SOCKET_CLOSED`, rung: \"implemented\" },\n { ref: `${AT}/backend/storage/ipc/latch.c:72-85 epoll where sys/epoll.h exists, :1131-1156 WL_SOCKET_CLOSED adds EPOLLRDHUP, and EPOLLERR and EPOLLHUP are always on, :1661-1680 EPOLLERR or EPOLLHUP make the socket readable, writable and closed, :2253-2263 epoll can report a close`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/be-secure.c:174-261 secure_read and :300-370 secure_write: a wait for the socket or the latch with no timeout; at the latch, ProcessClientReadInterrupt or ProcessClientWriteInterrupt; :234-237 and :343-346 FATAL 57P01 at the death of the postmaster`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:513-548 ProcessClientReadInterrupt: each interrupt in the wait for a command, a die request in another read; :559-600 ProcessClientWriteInterrupt: a die request only, with no message to the client`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:287-297 the socket has O_NONBLOCK, and the latch gives the waits; :896-956 pq_recvbuf: 0 bytes or an error is EOF, and an error logs COMMERROR \"could not receive data from client: %m\"`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:364-396 SocketBackend: EOF in a transaction logs COMMERROR 08006 \"unexpected EOF on client connection with an open transaction\", else DEBUG1 08003; :4988-5016 EOF or Terminate: proc_exit(0)`, rung: \"implemented\" },\n { ref: `${AT}/backend/access/transam/xact.c:383-396 IsTransactionState is TRANS_INPROGRESS only; backend/utils/init/postinit.c:1360-1371 ShutdownPostgres aborts the transaction at exit`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:1275-1336 a full buffer flushes, and the flush waits for the socket, :1358-1423 internal_flush_buffer: an error logs COMMERROR \"could not send data to client: %m\" once for each errno, drops the buffer and sets ClientConnectionLost`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/postgres.c:4310-4316 the backend ignores SIGPIPE`, rung: \"implemented\" },\n { ref: `${AT}/include/utils/elog.h:31-38 COMMERROR is LOG_SERVER_ONLY; backend/utils/error/elog.c:205-228 it goes to the log at log_min_messages WARNING (guc_tables.c:534), and DEBUG1 does not`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/error/elog.c:245-262 and :1726-1732 an error goes to the client while the output is DestRemote, :3643-3651 the backend flushes it, :559-590 FATAL ends the process with proc_exit(1)`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/pqcomm.c:347-392 socket_close keeps the socket open until the process exits`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/backend_startup.c:237-253 the startup timer: authentication_timeout, after the DNS lookup, :311-314 the end of the startup packet disarms it, :895-922 its handler and SIGTERM call _exit(1), with no log and no message`, rung: \"implemented\" },\n { ref: `${AT}/backend/tcop/backend_startup.c:460-519 ProcessStartupPacket: no byte is a silent end, a part of a packet logs COMMERROR 08P01 \"incomplete startup packet\"; :328-333 proc_exit(0)`, rung: \"implemented\" },\n { ref: `${AT}/backend/utils/init/postinit.c:235-251 PerformAuthentication arms the statement timer at authentication_timeout * 1000 ms, :305 ClientAuthInProgress ends after it, :1210-1215 the GUCs of the startup packet apply after it`, rung: \"implemented\" },\n { ref: `${AT}/backend/libpq/auth.c:260-271 an EOF from the client in authentication: proc_exit(0), with no log; :714-744 recv_password_packet gives an EOF as NULL`, rung: \"implemented\" },\n { ref: `${DOC}/config.sgml:961-972, :984-995, :1007-1016 and :1027-1037 a value of 0 selects the default of the OS; :1047-1073 the client check polls the socket, and without it the server sees a loss only at its next read or send`, rung: \"documented\" },\n { ref: `${DOC}/config.sgml:9474-9482 statement_timeout counts from the arrival of a command, :9501-9504 transaction_timeout is for a transaction block and for the transaction of one statement, :9510-9512 a transaction_timeout at or below another timeout makes the server ignore the other one, :9521-9525 a prepared transaction has no transaction timer`, rung: \"documented\" },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n STARTUP: { note: \"The backend reads the startup packet. Its timer is authentication_timeout (backend_startup.c:237-253)\" },\n AUTHENTICATING: { note: \"The authentication exchange, with a second timer of authentication_timeout (postinit.c:235-251)\" },\n IDLE: { note: \"The backend waits for a message, outside a transaction block (postgres.c:4648-4699)\" },\n IDLE_IN_TRANSACTION: { note: \"The backend waits for a message in a transaction block, open or aborted (postgres.c:4620-4647)\" },\n RUNNING: {\n note: \"The backend runs a command. Without the client check, it sees a loss of the client only at its next read or send (config.sgml:1059-1063)\",\n },\n SENDING: {\n note: \"A send gives EAGAIN, and the backend waits for the socket with no timeout (be-secure.c:331-361). In this wait it acts on SIGTERM and on the death of the postmaster only (postgres.c:559-600, be-secure.c:343-346). A timer that fires here sets its flag, and the backend acts on it after the send\",\n },\n GONE: { final: true, note: \"The backend exits, and the socket closes with the process (pqcomm.c:380-390)\" },\n },\n events: {\n accept: { kind: \"local\", note: \"The postmaster accepts the connection. The backend sets TCP_NODELAY and SO_KEEPALIVE in pq_init\" },\n \"rx.startup\": { kind: \"rx\", note: \"The startup packet of the client, with its GUCs\" },\n \"local.authenticated\": { kind: \"local\", note: \"ClientAuthentication returns, and InitPostgres continues to ReadyForQuery\" },\n \"rx.message\": { kind: \"rx\", note: \"A message of a command: Query, Parse, Bind, Execute or another\" },\n \"rx.terminate\": { kind: \"rx\", note: \"A Terminate message: the client ends the session\" },\n \"tx.ready-for-query\": { kind: \"tx\", note: \"ReadyForQuery: the backend waits for the next message\" },\n \"tx.error\": { kind: \"tx\", note: \"An ErrorResponse: the backend aborts the transaction, then sends ReadyForQuery\" },\n \"local.statement-done\": { kind: \"local\", note: \"finish_xact_command at the end of a statement\" },\n \"local.lock-wait\": { kind: \"local\", note: \"ProcSleep: the backend waits for a heavyweight lock\" },\n \"local.lock-granted\": { kind: \"local\" },\n \"local.transaction-start\": { kind: \"local\", note: \"StartTransaction, for a transaction block or for one statement\" },\n \"local.transaction-end\": { kind: \"local\", note: \"A commit, a prepare or an abort\" },\n \"local.send-blocked\": { kind: \"local\", note: \"The send buffer is full, and send gives EAGAIN\" },\n \"local.writable\": { kind: \"local\", note: \"The socket takes bytes again\" },\n \"local.die\": { kind: \"local\", note: \"SIGTERM: the die handler sets ProcDiePending\" },\n \"peer.fin\": { kind: \"peer\", note: \"A read gives 0 bytes: the client closed\" },\n \"peer.rst\": { kind: \"peer\" },\n \"socket.error\": { kind: \"local\", note: \"A read or a send fails with the error of the socket: the machine below ended it\" },\n \"timer.startup-packet\": { kind: \"timer\" },\n \"timer.authentication\": { kind: \"timer\" },\n \"timer.statement\": { kind: \"timer\" },\n \"timer.lock\": { kind: \"timer\" },\n \"timer.transaction\": { kind: \"timer\" },\n \"timer.idle-in-transaction\": { kind: \"timer\" },\n \"timer.idle-session\": { kind: \"timer\" },\n \"timer.client-check\": { kind: \"timer\", note: \"A poll of 0 ms for a close of the socket\" },\n },\n knobs: {\n tcp_keepalive_time: { key: \"net.ipv4.tcp_keepalive_time\", scope: \"netns\", unit: \"s\", default: 7200, note: \"The value of a new socket, which the backend keeps at tcp_keepalives_idle 0\" },\n tcp_keepalive_intvl: { key: \"net.ipv4.tcp_keepalive_intvl\", scope: \"netns\", unit: \"s\", default: 75, note: \"The value of a new socket, which the backend keeps at tcp_keepalives_interval 0\" },\n tcp_keepalive_probes: { key: \"net.ipv4.tcp_keepalive_probes\", scope: \"netns\", unit: \"count\", default: 9, note: \"The value of a new socket, which the backend keeps at tcp_keepalives_count 0\" },\n tcp_keepalives_idle: {\n key: \"postgresql tcp_keepalives_idle\",\n scope: \"session\",\n unit: \"s\",\n default: 0,\n note: \"guc_tables.c:3452-3461. At 0 the backend makes no call, and the socket keeps tcp_keepalive_time (pqcomm.c:1671-1672). Above 0 it sets TCP_KEEPIDLE\",\n },\n tcp_keepalives_interval: {\n key: \"postgresql tcp_keepalives_interval\",\n scope: \"session\",\n unit: \"s\",\n default: 0,\n note: \"guc_tables.c:3463-3472. At 0 the socket keeps tcp_keepalive_intvl (pqcomm.c:1755-1756). Above 0 the backend sets TCP_KEEPINTVL\",\n },\n tcp_keepalives_count: {\n key: \"postgresql tcp_keepalives_count\",\n scope: \"session\",\n unit: \"count\",\n default: 0,\n note: \"guc_tables.c:3485-3495. At 0 the socket keeps tcp_keepalive_probes (pqcomm.c:1834-1835). Above 0 the backend sets TCP_KEEPCNT\",\n },\n tcp_user_timeout: {\n key: \"postgresql tcp_user_timeout\",\n scope: \"session\",\n unit: \"ms\",\n default: 0,\n note: \"guc_tables.c:3587-3596. At 0 the backend makes no call, and the socket keeps its own value (pqcomm.c:1909-1910). Above 0 it sets TCP_USER_TIMEOUT\",\n },\n statement_timeout: { key: \"postgresql statement_timeout\", scope: \"session\", unit: \"ms\", default: 0, off: 0, note: \"guc_tables.c:2611-2620. 0 is no timeout (postgres.c:5257-5258)\" },\n lock_timeout: { key: \"postgresql lock_timeout\", scope: \"session\", unit: \"ms\", default: 0, off: 0, note: \"guc_tables.c:2622-2631. 0 is no timeout (proc.c:1294)\" },\n transaction_timeout: { key: \"postgresql transaction_timeout\", scope: \"session\", unit: \"ms\", default: 0, off: 0, note: \"guc_tables.c:2644-2653, new in 17. 0 is no timeout (xact.c:2175)\" },\n idle_in_transaction_session_timeout: {\n key: \"postgresql idle_in_transaction_session_timeout\",\n scope: \"session\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"guc_tables.c:2633-2642. 0 is no timeout (postgres.c:4626)\",\n },\n idle_session_timeout: { key: \"postgresql idle_session_timeout\", scope: \"session\", unit: \"ms\", default: 0, off: 0, note: \"guc_tables.c:2655-2664. 0 is no timeout (postgres.c:4693)\" },\n client_connection_check_interval: {\n key: \"postgresql client_connection_check_interval\",\n scope: \"session\",\n unit: \"ms\",\n default: 0,\n off: 0,\n note: \"guc_tables.c:3632-3641. 0 is no check (postgres.c:2790, :3331)\",\n },\n authentication_timeout: {\n key: \"postgresql authentication_timeout\",\n scope: \"server\",\n unit: \"s\",\n default: 60,\n note: \"guc_tables.c:2774-2783: 1 s to 600 s, PGC_SIGHUP. It bounds the startup packet and then the authentication, each on its own (backend_startup.c:243-246)\",\n },\n hz: { key: \"CONFIG_HZ\", scope: \"global\", unit: \"Hz\", default: null, note: \"The build option of the kernel: the timer wheel rounds the keepalive of the socket\" },\n alarm_slack: {\n key: \"the lateness of a SIGALRM timeout of a backend\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document: the source gives no bound. setitimer(ITIMER_REAL) raises SIGALRM (timeout.c:338-339), and the backend acts at its next CHECK_FOR_INTERRUPTS. The handler sets the latch of the backend (timeout.c:364-377), thus a wait on the latch ends at once. pg_sleep waits on the latch, and it calls CHECK_FOR_INTERRUPTS before each wait (adt/misc.c:391-412)\",\n },\n },\n timers: {\n startup_packet: {\n duration: { knob: \"authentication_timeout\", unit: \"s\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"enter:STARTUP\"],\n cancels: [\"rx.startup\"],\n fires: \"timer.startup-packet\",\n note: \"backend_startup.c:252-253 and :314. Its handler calls _exit(1) from the SIGALRM handler (backend_startup.c:918-922, timeout.c:413-414)\",\n },\n authentication: {\n duration: { knob: \"authentication_timeout\", unit: \"s\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"enter:AUTHENTICATING\"],\n cancels: [\"local.authenticated\"],\n fires: \"timer.authentication\",\n note: \"postinit.c:240 and :251: the statement timer, which sends SIGTERM while ClientAuthInProgress (postinit.c:1386-1387)\",\n },\n statement_timeout: {\n duration: { knob: \"statement_timeout\", unit: \"ms\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"rx.message\"],\n cancels: [\"local.statement-done\", \"tx.error\"],\n fires: \"timer.statement\",\n note: \"postgres.c:2787 and :2802. A timer that is active keeps its deadline across Parse, Bind and Execute (postgres.c:2780-2786). No timer when statement_timeout >= transaction_timeout > 0 (postgres.c:5257-5267)\",\n },\n lock_timeout: {\n duration: { knob: \"lock_timeout\", unit: \"ms\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"local.lock-wait\"],\n cancels: [\"local.lock-granted\", \"tx.error\"],\n fires: \"timer.lock\",\n note: \"proc.c:1294-1304 and :1654-1662: each wait for a lock has its own timer\",\n },\n transaction_timeout: {\n duration: { knob: \"transaction_timeout\", unit: \"ms\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"local.transaction-start\"],\n cancels: [\"local.transaction-end\", \"tx.error\"],\n fires: \"timer.transaction\",\n note: \"xact.c:2174-2176 and :2768-2770. An ERROR in a transaction block aborts the transaction, and the block stays (xact.c:3472-3477). Thus an aborted block has no transaction timer\",\n },\n idle_in_transaction: {\n duration: { knob: \"idle_in_transaction_session_timeout\", unit: \"ms\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"enter:IDLE_IN_TRANSACTION\"],\n cancels: [\"rx.message\"],\n fires: \"timer.idle-in-transaction\",\n note: \"postgres.c:4626-4646 and :4729-4733. No timer when idle_in_transaction_session_timeout >= transaction_timeout > 0. A timeout at the arrival of the message still ends the session (postgres.c:4721-4749)\",\n },\n idle_session: {\n duration: { knob: \"idle_session_timeout\", unit: \"ms\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"enter:IDLE\"],\n cancels: [\"rx.message\"],\n fires: \"timer.idle-session\",\n note: \"postgres.c:4693-4698 and :4734-4738\",\n },\n client_check: {\n duration: { knob: \"client_connection_check_interval\", unit: \"ms\" },\n lateness: { knob: \"alarm_slack\", unit: \"ms\" },\n arms: [\"rx.message\", \"timer.client-check\"],\n cancels: [\"tx.error\"],\n fires: \"timer.client-check\",\n note: \"postgres.c:2790-2795: a command arms it when it is not active. A check that passes arms it again. When it fires in the wait for a command, it does nothing and does not arm again (postgres.c:3331-3338)\",\n },\n },\n realizes: {\n \"systems.mechanism.idle-refresh-interval\": {\n duration: { knob: \"tcp_keepalive_time\", unit: \"s\" },\n lateness: { model: \"linux.wheel\", knobs: [\"tcp_keepalive_time\", \"hz\"], unit: \"s\" },\n early: { model: \"linux.jiffy\", knobs: [\"hz\"], unit: \"s\" },\n note: \"The first probe of an idle connection. At tcp_keepalives_idle 0 the backend keeps the idle time of the namespace\",\n },\n \"systems.mechanism.keepalive-detection-window\": { timer: \"keepalive\" },\n },\n transitions: [\n { id: \"pg.accept\", from: \"ABSENT\", to: \"STARTUP\", on: \"accept\", source: \"backend_startup.c:157-161, pqcomm.c:195-274\" },\n { id: \"pg.startup\", from: \"STARTUP\", to: \"AUTHENTICATING\", on: \"rx.startup\", source: \"backend_startup.c:255-314\" },\n {\n id: \"pg.startup-timed-out\",\n from: \"STARTUP\",\n to: \"GONE\",\n on: \"timer.startup-packet\",\n timer: \"startup_packet\",\n note: \"The backend calls _exit(1). It writes no log and sends no message\",\n source: \"backend_startup.c:895-922\",\n },\n {\n id: \"pg.startup-ended\",\n from: \"STARTUP\",\n to: \"GONE\",\n on: [\"peer.fin\", \"peer.rst\", \"socket.error\"],\n note: \"When no byte arrives, the backend writes no log. A part of a packet logs COMMERROR 08P01 \\\"incomplete startup packet\\\". Then proc_exit(0)\",\n source: \"backend_startup.c:460-519, :328-333\",\n },\n {\n id: \"pg.authenticated\",\n from: \"AUTHENTICATING\",\n to: \"IDLE\",\n on: \"local.authenticated\",\n note: \"The GUCs of the startup packet apply here (postinit.c:1210-1215). Thus a keepalive GUC of the client reaches the socket only after the authentication\",\n source: \"postinit.c:246-251, postgres.c:4618-4706\",\n },\n {\n id: \"pg.auth-timed-out\",\n from: \"AUTHENTICATING\",\n to: \"GONE\",\n on: \"timer.authentication\",\n timer: \"authentication\",\n errno: \"57014\",\n note: \"SIGTERM, then FATAL \\\"canceling authentication due to timeout\\\". The backend does not send it to the client\",\n source: \"postinit.c:1374-1394, postgres.c:3279-3290\",\n },\n {\n id: \"pg.auth-ended\",\n from: \"AUTHENTICATING\",\n to: \"GONE\",\n on: [\"peer.fin\", \"peer.rst\", \"socket.error\"],\n note: \"An EOF in the password exchange ends the backend with proc_exit(0). It writes no log for the EOF\",\n source: \"auth.c:260-271, :714-744\",\n },\n {\n id: \"pg.command\",\n from: [\"IDLE\", \"IDLE_IN_TRANSACTION\"],\n to: \"RUNNING\",\n on: \"rx.message\",\n note: \"The backend disarms the idle timers. Then it arms statement_timeout and the client check\",\n source: \"postgres.c:4719-4738, :2770-2796\",\n },\n { id: \"pg.ready\", from: \"RUNNING\", to: \"IDLE\", on: \"tx.ready-for-query\", guard: \"no transaction block\", source: \"postgres.c:4648-4704\" },\n {\n id: \"pg.ready-in-transaction\",\n from: \"RUNNING\",\n to: \"IDLE_IN_TRANSACTION\",\n on: \"tx.ready-for-query\",\n guard: \"a transaction block, open or aborted\",\n source: \"postgres.c:4620-4647\",\n },\n {\n id: \"pg.statement-timed-out\",\n from: \"RUNNING\",\n to: \"RUNNING\",\n on: \"timer.statement\",\n timer: \"statement_timeout\",\n errno: \"57014\",\n emits: [\"tx.error\"],\n note: \"ERROR \\\"canceling statement due to statement timeout\\\". The session stays\",\n source: \"postgres.c:3403-3409, :4446-4502\",\n },\n {\n id: \"pg.lock-timed-out\",\n from: \"RUNNING\",\n to: \"RUNNING\",\n on: \"timer.lock\",\n timer: \"lock_timeout\",\n errno: \"55P03\",\n emits: [\"tx.error\"],\n note: \"ERROR \\\"canceling statement due to lock timeout\\\". The session stays\",\n source: \"postgres.c:3396-3402\",\n },\n {\n id: \"pg.transaction-timed-out\",\n from: [\"RUNNING\", \"IDLE_IN_TRANSACTION\"],\n to: \"GONE\",\n on: \"timer.transaction\",\n timer: \"transaction_timeout\",\n guard: \"from IDLE_IN_TRANSACTION, the block is open: an aborted block has no transaction timer\",\n errno: \"25P04\",\n note: \"FATAL \\\"terminating connection due to transaction timeout\\\". The backend sends it to the client, then exits\",\n source: \"postgres.c:3453-3464, elog.c:1726-1732, :3643-3651\",\n },\n {\n id: \"pg.idle-in-transaction-timed-out\",\n from: \"IDLE_IN_TRANSACTION\",\n to: \"GONE\",\n on: \"timer.idle-in-transaction\",\n timer: \"idle_in_transaction\",\n errno: \"25P03\",\n note: \"FATAL \\\"terminating connection due to idle-in-transaction timeout\\\". The backend sends it to the client, then exits\",\n source: \"postgres.c:3435-3451\",\n },\n {\n id: \"pg.idle-timed-out\",\n from: \"IDLE\",\n to: \"GONE\",\n on: \"timer.idle-session\",\n timer: \"idle_session\",\n errno: \"57P05\",\n note: \"FATAL \\\"terminating connection due to idle-session timeout\\\". The backend sends it to the client, then exits\",\n source: \"postgres.c:3466-3477\",\n },\n {\n id: \"pg.client-check\",\n from: \"RUNNING\",\n to: \"RUNNING\",\n on: \"timer.client-check\",\n timer: \"client_check\",\n guard: \"the poll reports no close\",\n source: \"postgres.c:3321-3339\",\n },\n {\n id: \"pg.client-gone\",\n from: \"RUNNING\",\n to: \"GONE\",\n on: \"timer.client-check\",\n timer: \"client_check\",\n guard: \"the poll reports WL_SOCKET_CLOSED: EPOLLRDHUP, EPOLLERR or EPOLLHUP\",\n errno: \"08006\",\n note: \"FATAL \\\"connection to client lost\\\". The backend does not send it\",\n source: \"postgres.c:3333-3350, pqcomm.c:2053-2084, latch.c:1675-1680\",\n },\n { id: \"pg.send-blocked\", from: \"RUNNING\", to: \"SENDING\", on: \"local.send-blocked\", source: \"pqcomm.c:1275-1300, be-secure.c:331-340\" },\n { id: \"pg.send-resumed\", from: \"SENDING\", to: \"RUNNING\", on: \"local.writable\", source: \"be-secure.c:331-361\" },\n {\n id: \"pg.send-failed\",\n from: [\"RUNNING\", \"SENDING\"],\n to: \"GONE\",\n on: \"socket.error\",\n errno: \"08006\",\n note: \"COMMERROR \\\"could not send data to client: %m\\\" and ClientConnectionLost. At the next CHECK_FOR_INTERRUPTS: FATAL \\\"connection to client lost\\\", not sent. SIGPIPE has no effect (postgres.c:4310-4316)\",\n source: \"pqcomm.c:1396-1413, postgres.c:3341-3350\",\n },\n {\n id: \"pg.client-eof\",\n from: [\"IDLE\", \"IDLE_IN_TRANSACTION\"],\n to: \"GONE\",\n on: [\"peer.fin\", \"peer.rst\", \"socket.error\"],\n note: \"The read gives EOF, and the backend calls proc_exit(0), which aborts the transaction. A read error first logs COMMERROR \\\"could not receive data from client: %m\\\". In an open transaction the backend logs COMMERROR 08006 \\\"unexpected EOF on client connection with an open transaction\\\". Else, and in an aborted block, it logs DEBUG1 08003, which the default log level hides\",\n source: \"pqcomm.c:896-956, postgres.c:364-396, :4988-5016, postinit.c:1360-1371, xact.c:383-396, elog.c:205-228\",\n },\n { id: \"pg.terminate\", from: [\"IDLE\", \"IDLE_IN_TRANSACTION\"], to: \"GONE\", on: \"rx.terminate\", source: \"postgres.c:4988-5016\" },\n {\n id: \"pg.die\",\n from: [\"IDLE\", \"IDLE_IN_TRANSACTION\", \"RUNNING\", \"SENDING\"],\n to: \"GONE\",\n on: \"local.die\",\n errno: \"57P01\",\n note: \"FATAL \\\"terminating connection due to administrator command\\\". From SENDING the backend does not send it (postgres.c:589-590)\",\n source: \"postgres.c:2999-3023, :559-600, :3315-3318\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: {\n STARTUP: \"ESTABLISHED\",\n AUTHENTICATING: \"ESTABLISHED\",\n IDLE: \"ESTABLISHED\",\n IDLE_IN_TRANSACTION: \"ESTABLISHED\",\n RUNNING: \"ESTABLISHED\",\n SENDING: \"ESTABLISHED\",\n },\n sets: {\n keepidle: { knob: \"tcp_keepalive_time\", unit: \"s\" },\n keepintvl: { knob: \"tcp_keepalive_intvl\", unit: \"s\" },\n keepcnt: { knob: \"tcp_keepalive_probes\", unit: \"count\" },\n tcp_user_timeout: { knob: \"tcp_user_timeout\", unit: \"ms\" },\n },\n ends: \"socket.error\",\n note: \"These sets hold at the GUC defaults: the backend turns on SO_KEEPALIVE and keeps each keepalive option of the namespace. A keepalive GUC above 0 replaces its sysctl here. In SENDING no timer of PostgreSQL acts. Thus the timers of the machine below end a send to a lost client, or SIGTERM does\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is the Elixir source of Supavisor at the tag v2.9.13 of\n// github.com/supabase/supavisor. Each line number is a line of that file at the tag. A fact of the\n// kernel or of the BEAM is an assumption of this document, and its note says so.\nexport const SV = \"v2.9.13\";\n\n/**\n * This document is Supavisor 2.9.13 in transaction mode, for one client connection. It gives the\n * states of the client handler (a gen_statem) from the accept to the close, and the timers that act\n * on it.\n *\n * Between two transactions the client holds no server connection. A message of the client checks one\n * out of the pool of the tenant, and ReadyForQuery of the server checks it in. Thus a fault of the\n * server reaches an idle client only through the pool. Its next query meets the pool, or the pool\n * shuts down and closes it, as after 57P03 at a login of the pool.\n *\n * At the defaults the handler writes a heartbeat to an idle client each 60 s: a ParameterStatus of\n * application_name. A failed write ends the client. client_idle_timeout does not end a session in\n * 2.9.13: its timer fires an event that no clause handles. Each client socket has SO_KEEPALIVE.\n *\n * Each client socket also has the send timeout of ranch: a write to the client that waits 30 s fails,\n * and the BEAM closes the socket. This document gives it no timer. A write waits when the client takes no\n * data: a broken path, or a client that reads nothing. On a broken path, the FIN of the close waits\n * behind the data that the kernel did not send.\n */\nexport const SUPAVISOR_CLIENT: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"supavisor-client\",\n title: \"Supavisor 2.9.13 in transaction mode: one client connection, its checkout of a server and its heartbeat\",\n layer: \"proxy\",\n version: \"2.9.13\",\n conditions: {\n supavisor: \"2.9.13\",\n mode: \"transaction, the mode of the user of the tenant\",\n client: \"a PostgreSQL client over TCP, with no TLS, as the user <db_user>.<tenant>\",\n tenant: \"one tenant with one user and one server, client_heartbeat_interval 60 s and client_idle_timeout 0 at the defaults\",\n },\n sources: [\n { ref: `${SV} lib/supavisor/tenants/tenant.ex:28-32 the defaults of a tenant: default_pool_size 15, default_max_clients 1000, client_idle_timeout 0, client_heartbeat_interval 60 s`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/tenants/user.ex:16-19 a user: mode_type transaction or session, pool_size, pool_checkout_timeout 60_000 ms, max_clients`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/application.ex:71-83 each listener is ranch_tcp with keepalive true: each client socket has SO_KEEPALIVE`, rung: \"implemented\" },\n {\n ref: `ranch 2.2.0, the version of mix.lock at ${SV}: src/ranch_tcp.erl:108-109 a listener sets send_timeout 30000 and send_timeout_close true, and each accepted socket has the options of its listener. Thus a write to the client that waits 30 s fails, and the BEAM closes the socket. The server connection ignores the result of each write of a reply to the client (lib/supavisor/db_handler.ex:890-905)`,\n rung: \"implemented\",\n },\n {\n ref: `${SV} run 39170773426 of mark1russell7/systems, T03.defaults.59: behind an MTU black hole at a router, each of 11 runs had a reply of 2 MB in flight. The client socket of Supavisor left ESTABLISHED for FIN_WAIT1 30.068 to 30.086 s after the fault, and the client got nothing in 60 s`,\n rung: \"observed\",\n },\n { ref: `${SV} lib/supavisor/client_handler.ex:21-23, :123, :198 a state_timeout of 5_000 ms in :handshake, and 2_500 ms for a TLS handshake`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:315, :600, :627 an event timeout of 15_000 ms on each wait of the authentication`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:901-911 handle_actions arms the event timeout of client_idle_timeout, then the event timeout of the heartbeat. A gen_statem has one event timeout: the second action replaces the first`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:430-433, :734-744 the timer of client_idle_timeout fires :idle_timeout, but the clause matches :idle_terminate. The catch-all clause logs 'Undefined msg' and keeps the state`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:435-445, :1006 the heartbeat writes the ParameterStatus application_name each client_heartbeat_interval, and a failed write ends the client`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:705-716, :836-870, :966-971 a message in :idle checks out a server: poolboy with pool_checkout_timeout, then DbHandler.checkout with its call timeout of 15 s (lib/supavisor/db_handler.ex:101-110). A server connection that connects postpones the call (db_handler.ex:500-516)`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/errors/checkout_timeout_error.ex and lib/supavisor/error.ex:83-84 a checkout timeout reaches the client as FATAL XX000 'unable to check out connection from the pool after <ms>ms in Transaction mode'`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:523-537, :872-876 ReadyForQuery of the server: the client checks the server in and goes to :idle, and handle_actions arms the heartbeat`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:697-703 a Sync of the client in :busy goes to the server, and handle_actions arms the heartbeat in :busy too`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:90, :485-497 and lib/supavisor/errors/db_handler_exited_error.ex:15-25 the handler traps exits. The exit of its server connection ends the client: after a fatal error of the server that the client got, or with no ErrorResponse for the close of the server (db_termination)`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:556-566, :1016-1022 a close or an error of the client socket ends the client`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/client_handler.ex:545-556 and lib/supavisor/protocol/server.ex:183-190 the graceful shutdown of the pool: a client outside a transaction gets FATAL 57P01 'terminating connection due to administrator command' and its close, and a client in a transaction waits for its end (postpone)`, rung: \"implemented\" },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"Before ranch accepts the connection\" },\n handshake: { note: \"The startup packet, with a state timeout of 5 s\" },\n auth: { note: \"The authentication of the client by the password of its user, with a timeout of 15 s on each wait\" },\n idle: { note: \"Between two transactions: no server connection. The heartbeat runs\" },\n checkout: { note: \"A message of the client waits for a server connection of the pool. The handler does nothing else in this wait\" },\n busy: { note: \"A transaction: the client holds a server connection, and the server connection sends the replies to the client\" },\n ended: { final: true, note: \"The handler closed the client, with an ErrorResponse when it has one\" },\n },\n events: {\n \"local.accept\": { kind: \"local\", note: \"ranch accepts the TCP connection\" },\n \"rx.startup\": { kind: \"rx\", note: \"The startup packet of the client\" },\n \"local.authenticated\": { kind: \"local\", note: \"The password of the client matches, and the pool of the tenant serves\" },\n \"rx.query\": { kind: \"rx\", note: \"A message of the client between two transactions\" },\n \"local.checked-out\": { kind: \"local\", note: \"The pool gives a server connection, and it takes the client\" },\n \"server.ready\": { kind: \"local\", note: \"The server connection reads ReadyForQuery: the end of the transaction\" },\n \"server.exit\": { kind: \"peer\", note: \"The server connection of the client ends: the server closed it, reset it, or sent a fatal error\" },\n \"client.gone\": { kind: \"peer\", note: \"The client closes its connection, or a read or a write of its socket fails\" },\n \"pool.shutdown\": { kind: \"local\", note: \"The pool of the tenant shuts down gracefully, for example after 57P03 at a login of the pool\" },\n \"timer.handshake\": { kind: \"timer\", note: \"The state timeout of the handshake\" },\n \"timer.auth\": { kind: \"timer\", note: \"The timeout of a wait of the authentication\" },\n \"timer.heartbeat\": { kind: \"timer\", note: \"client_heartbeat_interval with no event of the handler\" },\n \"timer.checkout\": { kind: \"timer\", note: \"The pool gives no server connection in pool_checkout_timeout, or the server connection does not take the client in 15 s\" },\n \"tx.heartbeat\": { kind: \"tx\", note: \"The ParameterStatus application_name to the client\" },\n \"tx.error\": { kind: \"tx\", note: \"An ErrorResponse: FATAL with the SQLSTATE of the error, XX000 for an error of Supavisor\" },\n },\n knobs: {\n client_heartbeat_interval: { key: \"supavisor client_heartbeat_interval of the tenant\", scope: \"proxy\", unit: \"s\", default: 60, off: 0, note: \"lib/supavisor/tenants/tenant.ex:32\" },\n client_idle_timeout: {\n key: \"supavisor client_idle_timeout of the tenant\",\n scope: \"proxy\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"lib/supavisor/tenants/tenant.ex:31. It ends no session in 2.9.13, thus this document gives it no timer. Its event timeout is armed only when the heartbeat is off, and it fires :idle_timeout, which goes to the catch-all clause (lib/supavisor/client_handler.ex:430-433, :734-744, :901-911)\",\n },\n pool_checkout_timeout: { key: \"supavisor pool_checkout_timeout of the user\", scope: \"proxy\", unit: \"ms\", default: 60000, note: \"lib/supavisor/tenants/user.ex:18\" },\n handshake: { key: \"the state timeout of the handshake\", scope: \"process\", unit: \"ms\", default: 5000, note: \"lib/supavisor/client_handler.ex:23: a constant of the source\" },\n auth: { key: \"the timeout of a wait of the authentication\", scope: \"process\", unit: \"ms\", default: 15000, note: \"lib/supavisor/client_handler.ex:315: a constant of the source\" },\n checkout_call: { key: \"the call timeout of DbHandler.checkout\", scope: \"process\", unit: \"ms\", default: 15000, note: \"lib/supavisor/db_handler.ex:106: a constant of the source\" },\n slack: {\n key: \"the lateness of the scheduler of the BEAM for one timer of a gen_statem\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of Supavisor\",\n },\n },\n timers: {\n handshake_timeout: {\n duration: { knob: \"handshake\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:handshake\"],\n cancels: [\"rx.startup\"],\n fires: \"timer.handshake\",\n note: \"lib/supavisor/client_handler.ex:123, :198: a state timeout\",\n },\n auth_timeout: {\n duration: { knob: \"auth\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:auth\"],\n cancels: [\"local.authenticated\"],\n fires: \"timer.auth\",\n note: \"lib/supavisor/client_handler.ex:315, :600, :627\",\n },\n heartbeat: {\n duration: { knob: \"client_heartbeat_interval\", unit: \"s\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:idle\"],\n cancels: [\"rx.query\"],\n fires: \"timer.heartbeat\",\n backoff: { resets: [\"enter:idle\"] },\n note: \"lib/supavisor/client_handler.ex:435-445, :901-911: an event timeout, thus any event of the handler cancels it. Each heartbeat arms the next, the same each time. A Sync in a transaction arms it too\",\n },\n checkout_timeout: {\n duration: { knob: \"checkout_call\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:checkout\"],\n cancels: [\"local.checked-out\"],\n fires: \"timer.checkout\",\n note: \"lib/supavisor/client_handler.ex:848-851, lib/supavisor/db_handler.ex:101-110: poolboy gives a worker of the pool at once while the pool has one, and the call to that worker waits up to 15 s while it connects. With each worker checked out, poolboy waits up to pool_checkout_timeout\",\n },\n },\n transitions: [\n { id: \"scl.accept\", from: \"[none]\", to: \"handshake\", on: \"local.accept\", timer: \"handshake_timeout\", source: \"lib/supavisor/client_handler.ex:89-125\" },\n { id: \"scl.startup\", from: \"handshake\", to: \"auth\", on: \"rx.startup\", timer: \"auth_timeout\", source: \"lib/supavisor/client_handler.ex:211-315\" },\n { id: \"scl.handshake-timed-out\", from: \"handshake\", to: \"ended\", on: \"timer.handshake\", source: \"lib/supavisor/client_handler.ex:198-200\" },\n { id: \"scl.auth-timed-out\", from: \"auth\", to: \"ended\", on: \"timer.auth\", errno: \"XX000\", emits: [\"tx.error\"], source: \"lib/supavisor/client_handler.ex:627-635\" },\n { id: \"scl.authenticated\", from: \"auth\", to: \"idle\", on: \"local.authenticated\", timer: \"heartbeat\", source: \"lib/supavisor/client_handler.ex:340-410\" },\n { id: \"scl.heartbeat\", from: [\"idle\", \"busy\"], to: \"idle\", on: \"timer.heartbeat\", guard: \"the write of the heartbeat succeeds\", timer: \"heartbeat\", emits: [\"tx.heartbeat\"], source: \"lib/supavisor/client_handler.ex:435-440\" },\n { id: \"scl.query\", from: \"idle\", to: \"checkout\", on: \"rx.query\", timer: \"checkout_timeout\", source: \"lib/supavisor/client_handler.ex:705-716\" },\n { id: \"scl.checked-out\", from: \"checkout\", to: \"busy\", on: \"local.checked-out\", source: \"lib/supavisor/client_handler.ex:708-711, :851-856\" },\n {\n id: \"scl.checkout-timed-out\",\n from: \"checkout\",\n to: \"ended\",\n on: \"timer.checkout\",\n errno: \"XX000\",\n emits: [\"tx.error\"],\n note: \"FATAL 'unable to check out connection from the pool after <ms>ms in Transaction mode'\",\n source: \"lib/supavisor/client_handler.ex:712-714, :966-971, lib/supavisor/errors/checkout_timeout_error.ex\",\n },\n { id: \"scl.ready\", from: \"busy\", to: \"idle\", on: \"server.ready\", timer: \"heartbeat\", source: \"lib/supavisor/client_handler.ex:523-537\" },\n {\n id: \"scl.server-gone\",\n from: \"busy\",\n to: \"ended\",\n on: \"server.exit\",\n note: \"A fatal error of the server reaches the client first. A close or a reset of the server has no ErrorResponse: the client gets the close only\",\n source: \"lib/supavisor/client_handler.ex:485-497, lib/supavisor/errors/db_handler_exited_error.ex:15-25\",\n },\n { id: \"scl.gone\", from: [\"handshake\", \"auth\", \"idle\", \"checkout\", \"busy\"], to: \"ended\", on: \"client.gone\", source: \"lib/supavisor/client_handler.ex:556-566, :1016-1022\" },\n {\n id: \"scl.pool-shutdown\",\n from: \"idle\",\n to: \"ended\",\n on: \"pool.shutdown\",\n errno: \"57P01\",\n emits: [\"tx.error\"],\n note: \"FATAL 57P01 'terminating connection due to administrator command', then the close. A client in a transaction gets it at the end of the transaction\",\n source: \"lib/supavisor/client_handler.ex:545-556, lib/supavisor/protocol/server.ex:183-190\",\n },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { handshake: \"ESTABLISHED\", auth: \"ESTABLISHED\", idle: \"ESTABLISHED\", checkout: \"ESTABLISHED\", busy: \"ESTABLISHED\" },\n sets: {},\n ends: \"client.gone\",\n note: \"The socket of the client. ranch sets SO_KEEPALIVE and no other keepalive option, thus the three keepalive sysctls of the namespace apply. It also sets a send timeout of 30 s that closes the socket. That close has no timer here: the kernel sends the FIN only after the data before it, an assumption of this document\",\n },\n});\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { SV } from \"./supavisor-client.ts\";\n\n/**\n * This document is Supavisor 2.9.13 in transaction mode, for one server connection of the pool of a\n * tenant. It is one DbHandler, a gen_statem, from its start by the pool to its end.\n *\n * The connect to the server has a timeout of 5 s, and the authentication 15 s. A failed connect ends the\n * DbHandler with FATAL 08006 'Failed to connect to database'. A client that waits for this connection gets\n * that error at once. The pool then starts a new DbHandler, which waits the rest of 2.5 s from the last\n * failure before it connects.\n *\n * The DbHandler reads its socket in each state. Thus a close or a reset of the server ends it at once, idle\n * or with a client. A client that holds the connection then gets the close. The server socket has\n * TCP_NODELAY and no keepalive, and no timer of Supavisor bounds a query.\n */\nexport const SUPAVISOR_SERVER: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"supavisor-server\",\n title: \"Supavisor 2.9.13 in transaction mode: one server connection of the pool of a tenant\",\n layer: \"proxy\",\n version: \"2.9.13\",\n conditions: {\n supavisor: \"2.9.13\",\n mode: \"transaction, the mode of the user of the tenant\",\n server: \"one PostgreSQL server over TCP, with no TLS, at the address of the tenant\",\n },\n sources: [\n { ref: `${SV} lib/supavisor/tenant_supervisor.ex:72-80 the pool of a tenant: poolboy, worker DbHandler, size min_size, max_overflow pool_size, lifo, an overflow worker stops after 5 min idle`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:66, :205-224, :1111-1119 a new DbHandler waits the rest of 2.5 s from the last failed connect of its pool (connect_cooldown)`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:226-289 the connect: gen_tcp with nodelay and no keepalive, and a timeout of 5_000 ms (1_000 ms in proxy mode). Then the startup message, and a state timeout of 15_000 ms on the authentication`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:1072-1085, :292-321 a failed connect: the circuit breaker and the backoff of the pool record it, FATAL 08006 'Failed to connect to database', and the DbHandler goes to terminating_with_error, then stops`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:480-516 a checkout in :idle or :busy links the client and gives it the socket. In another state the call waits (postpone), and in terminating_with_error it gets the error`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:551-574 a close of the server socket: in the authentication a failed connect, else the DbHandler stops with db_termination`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:575-585 the exit of the client that holds the connection: Terminate to the server, close, stop`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/circuit_breaker.ex:28-35 100 failed connects of a tenant in 150 s block its new connections for 30 s`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/db_handler.ex:69-76, :362-372, :297-301 an ErrorResponse at the authentication: 57P03 (the server shuts down) shuts the pool down gracefully, 3D000, 42501 and 22023 shut it down, and 28P01 and 28000 keep it`, rung: \"implemented\" },\n { ref: `${SV} lib/supavisor/manager.ex:107-118, lib/supavisor/client_handler.ex:545-556 the graceful shutdown of a pool: each client outside a transaction gets FATAL 57P01 'terminating connection due to administrator command' and its close. A client in a transaction gets it after the transaction`, rung: \"implemented\" },\n {\n ref: `${SV} run 39164922565 of mark1russell7/systems: the server stopped, and the next connect of the pool got 57P03 in 6 of 11 runs. Each idle client then got FATAL 57P01 and its close, 8 to 10 ms after the server closed its connections. In 5 runs the connect came after the server, and the pool stayed`,\n rung: \"observed\",\n },\n ],\n states: {\n \"[none]\": { initial: true, pseudo: true, note: \"The pool starts a DbHandler\" },\n cooldown: { note: \"The pool had a failed connect in the last 2.5 s: the DbHandler waits for the rest\" },\n connecting: { note: \"The TCP connect, with its timeout of 5 s\" },\n authentication: { note: \"The startup message and the authentication, with a state timeout of 15 s\" },\n idle: { note: \"In the pool, ready for a client. The DbHandler reads the socket\" },\n busy: { note: \"Checked out by a client for a transaction: the DbHandler sends each message of the server to the client\" },\n ended: { final: true, note: \"The DbHandler stopped, and the pool starts a new one\" },\n },\n events: {\n \"local.start\": { kind: \"local\", note: \"The pool starts the DbHandler\" },\n \"socket.connect\": { kind: \"local\", note: \"The TCP connect ends\" },\n \"rx.ready-for-query\": { kind: \"rx\", note: \"ReadyForQuery of the server: the end of the authentication or of a transaction\" },\n \"local.checkout\": { kind: \"local\", note: \"A client checks the connection out of the pool\" },\n \"client.gone\": { kind: \"peer\", note: \"The client that holds the connection ends\" },\n \"peer.fin\": { kind: \"peer\", note: \"The server closes the connection\" },\n \"peer.rst\": { kind: \"peer\", note: \"A reset of the connection of the server\" },\n \"socket.error\": { kind: \"local\", note: \"The socket of the server fails with its own error\" },\n \"rx.shutting-down\": { kind: \"rx\", note: \"An ErrorResponse 57P03 at the authentication: the server shuts down\" },\n \"timer.cooldown\": { kind: \"timer\", note: \"The rest of 2.5 s from the last failed connect of the pool\" },\n \"timer.connect\": { kind: \"timer\", note: \"The timeout of gen_tcp.connect\" },\n \"timer.auth\": { kind: \"timer\", note: \"The state timeout of the authentication\" },\n \"tx.terminate\": { kind: \"tx\", note: \"The Terminate message, then the close of the socket\" },\n \"tx.error\": { kind: \"tx\", note: \"FATAL 08006 'Failed to connect to database' to the client that waits for the connection\" },\n \"tx.pool-shutdown\": { kind: \"local\", note: \"The graceful shutdown of the pool: FATAL 57P01 and the close of each client outside a transaction\" },\n },\n knobs: {\n cooldown: { key: \"the cooldown of the pool after a failed connect\", scope: \"process\", unit: \"ms\", default: 2500, note: \"lib/supavisor/db_handler.ex:66: a constant of the source\" },\n connect: { key: \"the timeout of the TCP connect to the server\", scope: \"process\", unit: \"ms\", default: 5000, note: \"lib/supavisor/db_handler.ex:240: a constant of the source, 1_000 ms in proxy mode\" },\n auth: { key: \"the state timeout of the authentication to the server\", scope: \"process\", unit: \"ms\", default: 15000, note: \"lib/supavisor/db_handler.ex:67: a constant of the source\" },\n keepalive_idle: {\n key: \"the keepalive idle time of the server socket of Supavisor\",\n scope: \"proxy\",\n unit: \"s\",\n default: 0,\n off: 0,\n note: \"lib/supavisor/db_handler.ex:229-236: Supavisor sets no SO_KEEPALIVE on a server socket, thus no bound\",\n },\n slack: {\n key: \"the lateness of the scheduler of the BEAM for one timer of a gen_statem\",\n scope: \"process\",\n unit: \"ms\",\n default: 10,\n note: \"An assumption of this document, not a value of Supavisor\",\n },\n },\n timers: {\n cooldown: {\n duration: { knob: \"cooldown\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:cooldown\"],\n fires: \"timer.cooldown\",\n note: \"lib/supavisor/db_handler.ex:205-224, :1111-1119: the rest of 2.5 s from the last failure, thus at most 2.5 s\",\n },\n connect_timeout: {\n duration: { knob: \"connect\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:connecting\"],\n cancels: [\"socket.connect\", \"socket.error\", \"peer.rst\"],\n fires: \"timer.connect\",\n note: \"lib/supavisor/db_handler.ex:240-248: the timeout of gen_tcp.connect. Its end closes the socket in SYN_SENT\",\n },\n authentication_timeout: {\n duration: { knob: \"auth\", unit: \"ms\" },\n lateness: { knob: \"slack\", unit: \"ms\" },\n arms: [\"enter:authentication\"],\n cancels: [\"rx.ready-for-query\", \"peer.fin\", \"peer.rst\", \"socket.error\"],\n fires: \"timer.auth\",\n note: \"lib/supavisor/db_handler.ex:272, :329-331\",\n },\n },\n transitions: [\n { id: \"ssv.start\", from: \"[none]\", to: \"connecting\", on: \"local.start\", guard: \"no failed connect of the pool in the last 2.5 s\", timer: \"connect_timeout\", source: \"lib/supavisor/db_handler.ex:205-228\" },\n { id: \"ssv.start-late\", from: \"[none]\", to: \"cooldown\", on: \"local.start\", guard: \"a failed connect of the pool in the last 2.5 s\", timer: \"cooldown\", source: \"lib/supavisor/db_handler.ex:205-211\" },\n { id: \"ssv.cooldown-over\", from: \"cooldown\", to: \"connecting\", on: \"timer.cooldown\", timer: \"connect_timeout\", source: \"lib/supavisor/db_handler.ex:222-224\" },\n { id: \"ssv.connected\", from: \"connecting\", to: \"authentication\", on: \"socket.connect\", timer: \"authentication_timeout\", source: \"lib/supavisor/db_handler.ex:248-273\" },\n {\n id: \"ssv.connect-failed\",\n from: [\"connecting\", \"authentication\"],\n to: \"ended\",\n on: [\"timer.connect\", \"socket.error\", \"peer.rst\", \"peer.fin\", \"timer.auth\"],\n errno: \"08006\",\n emits: [\"tx.error\"],\n note: \"FATAL 'Failed to connect to database: <reason>' to a client that waits for the connection, then the DbHandler stops\",\n source: \"lib/supavisor/db_handler.ex:282-289, :329-331, :551-555, :1072-1085, :292-321\",\n },\n { id: \"ssv.authenticated\", from: \"authentication\", to: \"idle\", on: \"rx.ready-for-query\", source: \"lib/supavisor/db_handler.ex:380-390\" },\n {\n id: \"ssv.server-shutting-down\",\n from: \"authentication\",\n to: \"ended\",\n on: \"rx.shutting-down\",\n emits: [\"tx.pool-shutdown\"],\n note: \"57P03 at the login: Supavisor shuts the whole pool down gracefully, thus a server that shuts down can end each idle client of the tenant\",\n source: \"lib/supavisor/db_handler.ex:69-76, :362-372, :297-301\",\n },\n { id: \"ssv.checkout\", from: \"idle\", to: \"busy\", on: \"local.checkout\", source: \"lib/supavisor/db_handler.ex:500-512\" },\n { id: \"ssv.release\", from: \"busy\", to: \"idle\", on: \"rx.ready-for-query\", source: \"lib/supavisor/db_handler.ex:415-425\" },\n {\n id: \"ssv.closed\",\n from: [\"idle\", \"busy\"],\n to: \"ended\",\n on: [\"peer.fin\", \"peer.rst\", \"socket.error\"],\n note: \"db_termination: a client that holds the connection gets the close, with no ErrorResponse\",\n source: \"lib/supavisor/db_handler.ex:557-574\",\n },\n { id: \"ssv.client-gone\", from: \"busy\", to: \"ended\", on: \"client.gone\", emits: [\"tx.terminate\"], source: \"lib/supavisor/db_handler.ex:575-585\" },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { connecting: \"SYN_SENT\", authentication: \"ESTABLISHED\", idle: \"ESTABLISHED\", busy: \"ESTABLISHED\" },\n sets: { keepidle: { knob: \"keepalive_idle\", unit: \"s\" } },\n ends: \"socket.error\",\n note: \"The server socket, with TCP_NODELAY and no SO_KEEPALIVE. The DbHandler reads it in each state, thus the end of the socket reaches it at once\",\n },\n});\n","import type { Expr, Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\nimport { NODE_TIMER_EARLY, nodeTimerLateness } from \"./http/timers.ts\";\n\n/**\n * This module holds the machine documents of the WebSocket transport of `@procedures/client`\n * 0.3.0, the release on npm. Each fact comes from the files of that release, from\n * `@mark1russell7/service` 0.4.0, or from Node v24.21.0 and its undici 7.29.1. The comments and the\n * sources give the file and the line.\n *\n * The client repository has a document of the connection at commit 1f50f47:\n * `WEBSOCKET_CONNECTION_MACHINE` in `packages/client/src/machines.ts`. This document takes its\n * states and its events, and the code of 0.3.0 gives the timers.\n */\n\n/** This function gives the arithmetic of a duration in ms. */\nconst arithmetic = (duration: Expr): string => {\n if (!(\"expr\" in duration) || duration.unit !== \"ms\") throw new Error(\"not arithmetic in ms\");\n return duration.expr;\n};\n\n/** This text is the backoff of try n + 1 of the reconnect, in ms: `fired` is n. It reads the arithmetic of `backoffDelay`. */\nconst RECONNECT_WAIT = \"min(reconnect_initial_delay * pow(reconnect_backoff_multiplier, fired), reconnect_max_delay)\";\n\n/** This text is the late bound of one Node timer, in ms, for a time in ms. */\nconst late = (ms: string): string => arithmetic(nodeTimerLateness(ms));\n/** This text is the early bound of one Node timer, in ms. */\nconst EARLY = arithmetic(NODE_TIMER_EARLY);\n\n/**\n * This document is the connection of the WebSocket client of `@procedures/client` 0.3.0\n * (`WebSocketTransport`), over its socket class and its Linux TCP socket.\n *\n * - The heartbeat is `heartbeat()` of `@mark1russell7/service` 0.4.0. A tick each interval sends a\n * ping only when no pong is awaited. The timeout of the ping starts before its send. A\n * ping without a pong at its timeout is a miss, and `misses` misses in sequence drop the\n * connection. With a timeout below the interval, each tick after a miss sends the next ping.\n * Thus the drop comes (misses − 1) intervals and one timeout after the first ping without an answer.\n * - A drop ends the socket with `terminate()` when its class has it: the `ws` package. The global\n * `WebSocket` of Node has only `close()`, which writes a close frame and destroys nothing.\n * - Each end of a socket starts the reconnect. The wait of try n is the backoff\n * min(initialDelay × multiplier^(n − 1), maxDelay), less a random part: jitter × backoff × r.\n * - The handshake has a time limit (`connectionTimeout`), and a failed handshake drops at once.\n * - The heartbeat refreshes an idle flow. Each tick writes a ping, whatever data the connection\n * carries, and the pong comes back. Thus the ping timer realizes the idle refresh of O03.\n */\nexport const PROCEDURES_WS_CLIENT: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"procedures-ws-client\",\n title: \"The connection of the WebSocket client of @procedures/client 0.3.0\",\n layer: \"driver\",\n version: \"0.3.0\",\n conditions: { \"@procedures/client\": \"0.3.0\", \"@mark1russell7/service\": \"0.4.0\", node: \"24.21.0\", undici: \"7.29.1\", ws: \"8.22.0\", kernel: \"Linux 6.6\" },\n sources: [\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/client/transport.js:161-193 (the options: each time a duration; the misses of the heartbeat, the jitter of the reconnect, the class of the sockets)\",\n rung: \"implemented\",\n },\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/client/transport.js:379-399 startHeartbeat: heartbeat() of @mark1russell7/service with the interval, the timeout and the misses; a tick sends a ping only when CONNECTED\",\n rung: \"implemented\",\n },\n {\n ref: \"@mark1russell7/service 0.4.0 src/heartbeat.ts:129-135 (each tick starts the next one first), :96-125 (the timeout starts before the send of the ping; a send that throws is a miss), :81-94 (misses in sequence)\",\n rung: \"implemented\",\n },\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/client/transport.js:302-325 dropConnection: the handlers go, terminate() when the class has it, else close(), and handleClose at once\",\n rung: \"implemented\",\n },\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/client/transport.js:120-127 and :357-377: reconnectDelay is backoffDelay of @mark1russell7/service, with a subtracted jitter; an open sets the attempts to 0\",\n rung: \"implemented\",\n },\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/client/transport.js:221-236 and :283-289: the time limit of the handshake, and a failed handshake drops at once\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 deps/undici/src/lib/web/websocket/connection.js:227-296 closeWebSocketConnection: close() on an open socket writes a close frame and destroys nothing\",\n rung: \"implemented\",\n },\n {\n ref: \"ws 8.22.0 lib/websocket.js:505-517 terminate(): the socket is destroyed at once\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 deps/undici/src/lib/core/connect.js:120-129 setKeepAlive(true, 60000); deps/uv/src/unix/tcp.c:591-593 uv_tcp_keepalive: 1 s and 10 probes. The ws package sets no keepalive on its socket.\",\n rung: \"implemented\",\n },\n {\n ref: \"client main 1f50f47 packages/client/src/machines.ts WEBSOCKET_CONNECTION_MACHINE: the states and the events of this document\",\n rung: \"documented\",\n },\n ],\n states: {\n DISCONNECTED: { initial: true, note: \"no socket\" },\n CONNECTING: { note: \"the handshake, with its time limit\" },\n CONNECTED: { note: \"the calls; no pong is awaited\" },\n AWAITING_PONG: { note: \"a ping went out and its timeout runs: a tick of the interval sends nothing\" },\n RECONNECTING: { note: \"the wait before the next try\" },\n DISCONNECTING: { note: \"close() of the application ends the socket and the calls\" },\n },\n events: {\n connect: { kind: \"app\", note: \"the transport starts\" },\n open: { kind: \"rx\", note: \"the handshake ends: the attempts go back to 0\" },\n \"handshake-timeout\": { kind: \"timer\" },\n \"ping-due\": { kind: \"timer\", note: \"a tick of the interval\" },\n pong: { kind: \"rx\" },\n \"pong-timeout\": { kind: \"timer\", note: \"the last miss of `misses` in sequence\" },\n drop: { kind: \"local\", note: \"the close event of the socket: a FIN, a reset, a give-up of the kernel, or a failed handshake\" },\n \"reconnect-due\": { kind: \"timer\" },\n \"give-up\": { kind: \"local\", note: \"an end without reconnect, or without tries left\" },\n \"tx.request\": { kind: \"tx\", note: \"the transport writes a call\" },\n \"rx.reply\": { kind: \"rx\", note: \"the first frame of the reply to a call\" },\n \"request-timeout\": { kind: \"timer\" },\n close: { kind: \"app\", note: \"close() of the application\" },\n closed: { kind: \"local\" },\n },\n knobs: {\n heartbeat_interval: { key: \"heartbeat.interval\", scope: \"client\", unit: \"ms\", default: 20000 },\n heartbeat_timeout: { key: \"heartbeat.timeout\", scope: \"client\", unit: \"ms\", default: 5000 },\n heartbeat_misses: { key: \"heartbeat.misses\", scope: \"client\", unit: \"count\", default: 1 },\n reconnect_initial_delay: { key: \"reconnect.initialDelay\", scope: \"client\", unit: \"ms\", default: 1000 },\n reconnect_backoff_multiplier: { key: \"reconnect.backoffMultiplier\", scope: \"client\", unit: \"count\", default: 1.5 },\n reconnect_max_delay: { key: \"reconnect.maxDelay\", scope: \"client\", unit: \"ms\", default: 30000 },\n reconnect_max_attempts: { key: \"reconnect.maxAttempts\", scope: \"client\", unit: \"count\", default: null, note: \"Infinity at the default\" },\n reconnect_jitter: {\n key: \"reconnect.jitter\",\n scope: \"client\",\n unit: \"count\",\n default: 1,\n note: \"the random part of each wait, from 0 to 1: a wait is the backoff less jitter × backoff × r\",\n },\n request_timeout: { key: \"requestTimeout\", scope: \"client\", unit: \"ms\", default: 30000 },\n connection_timeout: { key: \"connectionTimeout\", scope: \"client\", unit: \"ms\", default: 10000, note: \"the time limit of the handshake, and the wait of a call for a connection\" },\n socket_keepidle: {\n key: \"the keepalive of the socket class\",\n scope: \"client\",\n unit: \"s\",\n default: 60,\n note: \"undici sets 60 s on the socket of the global WebSocket. The ws package sets none: a reader gives no bound\",\n },\n hz: {\n key: \"CONFIG_HZ\",\n scope: \"global\",\n unit: \"Hz\",\n default: null,\n note: \"the HZ of the kernel, for the step of the coarse loop clock of libuv (http/timers.ts)\",\n },\n },\n timers: {\n ping: {\n duration: { knob: \"heartbeat_interval\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"heartbeat_interval\"),\n early: NODE_TIMER_EARLY,\n arms: [\"enter:CONNECTED\"],\n cancels: [\"drop\", \"close\"],\n fires: \"ping-due\",\n backoff: { resets: [\"open\"] },\n note: \"each tick starts the next one first, from the loop clock of that tick: a late tick moves each later tick. The data of the connection does not move a tick (service src/heartbeat.ts:129-135), thus an idle flow gets a ping and a pong each interval\",\n },\n pong: {\n duration: { expr: \"(heartbeat_misses - 1) * heartbeat_interval + heartbeat_timeout\", unit: \"ms\" },\n lateness: { expr: `(heartbeat_misses - 1) * (${late(\"heartbeat_interval\")}) + ${late(\"heartbeat_timeout\")}`, unit: \"ms\" },\n early: { expr: `heartbeat_misses * (${EARLY})`, unit: \"ms\" },\n arms: [\"enter:AWAITING_PONG\"],\n cancels: [\"pong\", \"drop\", \"close\"],\n fires: \"pong-timeout\",\n note: \"from the first ping without an answer: (misses − 1) ticks, then the timeout of the last ping. The timeout starts before the send of its ping\",\n },\n reconnect: {\n duration: { expr: RECONNECT_WAIT, unit: \"ms\" },\n lateness: nodeTimerLateness(RECONNECT_WAIT),\n early: { expr: `reconnect_jitter * ${RECONNECT_WAIT} + ${EARLY}`, unit: \"ms\" },\n arms: [\"enter:RECONNECTING\"],\n cancels: [\"close\"],\n fires: \"reconnect-due\",\n backoff: { resets: [\"open\"] },\n note: \"the jitter subtracts a random part of the backoff: its early bound\",\n },\n handshake: {\n duration: { knob: \"connection_timeout\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"connection_timeout\"),\n early: NODE_TIMER_EARLY,\n arms: [\"enter:CONNECTING\"],\n cancels: [\"open\", \"drop\", \"close\"],\n fires: \"handshake-timeout\",\n },\n request: {\n duration: { knob: \"request_timeout\", unit: \"ms\" },\n lateness: nodeTimerLateness(\"request_timeout\"),\n early: NODE_TIMER_EARLY,\n arms: [\"tx.request\"],\n cancels: [\"rx.reply\", \"drop\", \"close\"],\n fires: \"request-timeout\",\n note: \"one timer for each call: it fails the call, and the connection stays\",\n },\n },\n realizes: {\n // each ping and its pong refresh the flow at a middlebox: O03 reads the interval at its latest\n \"systems.mechanism.idle-refresh-interval\": { timer: \"ping\" },\n },\n transitions: [\n { id: \"pw.connect\",from: \"DISCONNECTED\", on: \"connect\", to: \"CONNECTING\" },\n { id: \"pw.open\", from: \"CONNECTING\", on: \"open\", to: \"CONNECTED\", source: \"transport.js:237-262\" },\n {\n id: \"pw.handshake-timeout\",\n from: \"CONNECTING\",\n on: \"handshake-timeout\",\n to: \"RECONNECTING\",\n timer: \"handshake\",\n source: \"transport.js:229-236\",\n },\n {\n id: \"pw.ping\",\n from: \"CONNECTED\",\n on: \"ping-due\",\n to: \"AWAITING_PONG\",\n timer: \"ping\",\n emits: [\"tx.ping\"],\n source: \"transport.js:379-399\",\n },\n {\n id: \"pw.skip\",\n from: \"AWAITING_PONG\",\n on: \"ping-due\",\n to: \"AWAITING_PONG\",\n timer: \"ping\",\n note: \"one ping at a time: the tick sends nothing\",\n source: \"service src/heartbeat.ts:129-133\",\n },\n { id: \"pw.pong\", from: \"AWAITING_PONG\", on: \"pong\", to: \"CONNECTED\", source: \"transport.js:449-452\" },\n {\n id: \"pw.pong-timeout\",\n from: \"AWAITING_PONG\",\n on: \"pong-timeout\",\n to: \"RECONNECTING\",\n timer: \"pong\",\n emits: [\"tx.close-frame\"],\n note: \"dropConnection: terminate() destroys the socket of ws at once; close() of the global WebSocket writes a close frame, and its socket stays open below\",\n source: \"transport.js:302-325\",\n },\n {\n id: \"pw.drop\",\n from: [\"CONNECTING\", \"CONNECTED\", \"AWAITING_PONG\"],\n on: \"drop\",\n to: \"RECONNECTING\",\n guard: \"the reconnect is on, and tries are left\",\n source: \"transport.js:269-273, :336-355\",\n },\n {\n id: \"pw.give-up\",\n from: [\"CONNECTING\", \"CONNECTED\", \"AWAITING_PONG\"],\n on: \"give-up\",\n to: \"DISCONNECTED\",\n source: \"transport.js:341-343\",\n },\n {\n id: \"pw.reconnect\",\n from: \"RECONNECTING\",\n on: \"reconnect-due\",\n to: \"CONNECTING\",\n timer: \"reconnect\",\n source: \"transport.js:357-377\",\n },\n {\n id: \"pw.request-timeout\",\n from: \"CONNECTED\",\n on: \"request-timeout\",\n to: \"CONNECTED\",\n timer: \"request\",\n errno: \"TIMEOUT\",\n source: \"transport.js:598-607\",\n },\n {\n id: \"pw.request-timeout-pinged\",\n from: \"AWAITING_PONG\",\n on: \"request-timeout\",\n to: \"AWAITING_PONG\",\n timer: \"request\",\n errno: \"TIMEOUT\",\n source: \"transport.js:598-607\",\n },\n {\n id: \"pw.close\",\n from: [\"DISCONNECTED\", \"CONNECTING\", \"CONNECTED\", \"AWAITING_PONG\", \"RECONNECTING\"],\n on: \"close\",\n to: \"DISCONNECTING\",\n },\n { id: \"pw.closed\", from: \"DISCONNECTING\", on: \"closed\", to: \"DISCONNECTED\" },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { CONNECTING: \"SYN_SENT\", CONNECTED: \"ESTABLISHED\", AWAITING_PONG: \"ESTABLISHED\" },\n sets: {\n keepidle: { knob: \"socket_keepidle\", unit: \"s\" },\n keepintvl: { const: 1, unit: \"s\" },\n keepcnt: { const: 10, unit: \"count\" },\n },\n ends: \"drop\",\n note: \"The connector of undici turns keepalive on with a delay of 60 s, and libuv adds 1 s and 10 probes. The ws package turns no keepalive on. Thus the keepalive sysctls of the namespace do not reach the socket.\",\n },\n} satisfies Machine);\n\n/**\n * This document is one connection as the WebSocket server of `@procedures/client` 0.3.0 holds it\n * (`WebSocketServerTransport` on the `ws` package), over its Linux TCP socket.\n *\n * The heartbeat of the server (roadmap R3) is a `setInterval`. Each beat pings each connection,\n * and the server ends a connection after `misses` beats without a pong (`terminate()`). Thus the\n * drop comes `misses` beats after the first ping without an answer, and the lateness of each beat\n * adds. Its `http.Server` sets no SO_KEEPALIVE when `keepAlive` is off, the default of Node.\n */\nexport const PROCEDURES_WS_SERVER: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"procedures-ws-server\",\n title: \"One connection as the WebSocket server of @procedures/client 0.3.0 holds it\",\n layer: \"server\",\n version: \"0.3.0\",\n conditions: { \"@procedures/client\": \"0.3.0\", ws: \"8.22.0\", node: \"24.21.0\", kernel: \"Linux 6.6\" },\n sources: [\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/server/transport.js:81-87 (the heartbeat: interval and misses, or false), :93-111 beat(): terminate after misses, or count a miss and ping; :147-149 setInterval of the interval; :240 a pong sets the misses to 0\",\n rung: \"implemented\",\n },\n {\n ref: \"@procedures/client 0.3.0 dist/timers.js:29 webSocketServer: heartbeatIntervalMs 15000, heartbeatMisses 2\",\n rung: \"implemented\",\n },\n {\n ref: \"@procedures/client 0.3.0 dist/adapters/websocket/server/transport.js:318-322: a ping of a client gets a pong\",\n rung: \"implemented\",\n },\n {\n ref: \"node v24.21.0 lib/_http_server.js:646-651 and lib/net.js:2753-2756: keepAlive of http.Server is off at the default, thus an accepted socket has no SO_KEEPALIVE\",\n rung: \"implemented\",\n },\n ],\n states: {\n ABSENT: { initial: true, pseudo: true },\n OPEN: { note: \"each beat pings the connection\" },\n MISSING: { note: \"a ping got no pong: each beat counts a miss\" },\n CLOSED: { final: true },\n },\n events: {\n accept: { kind: \"local\" },\n \"beat.unanswered\": { kind: \"timer\", note: \"a beat after a ping that got no pong\" },\n \"rx.pong\": { kind: \"rx\" },\n \"rx.ping\": { kind: \"rx\", note: \"a ping of the heartbeat of the client\" },\n \"misses-reached\": { kind: \"timer\" },\n close: { kind: \"peer\", note: \"the close event of the socket of ws\" },\n \"socket.error\": { kind: \"local\", note: \"the kernel beneath gave up on the socket, or a reset arrived\" },\n },\n knobs: {\n heartbeat_interval: { key: \"heartbeat.interval\", scope: \"server\", unit: \"ms\", default: 15000, note: \"no bound when the heartbeat is off\" },\n heartbeat_misses: { key: \"heartbeat.misses\", scope: \"server\", unit: \"count\", default: 2 },\n tcp_keepalive: {\n key: \"keepAlive of http.Server (server-ws --tcp-keepalive)\",\n scope: \"server\",\n unit: null,\n default: 0,\n note: \"off: a reader gives the keepalive of the kernel no bound\",\n },\n hz: { key: \"CONFIG_HZ\", scope: \"global\", unit: \"Hz\", default: null },\n },\n timers: {\n heartbeat: {\n duration: { expr: \"heartbeat_misses * heartbeat_interval\", unit: \"ms\" },\n lateness: { expr: `heartbeat_misses * (${late(\"heartbeat_interval\")})`, unit: \"ms\" },\n early: { expr: `heartbeat_misses * (${EARLY})`, unit: \"ms\" },\n arms: [\"enter:MISSING\"],\n cancels: [\"rx.pong\"],\n fires: \"misses-reached\",\n note: \"from the first ping without an answer: misses beats of the interval, then terminate()\",\n },\n },\n transitions: [\n { id: \"ps.accept\", from: \"ABSENT\", on: \"accept\", to: \"OPEN\" },\n { id: \"ps.miss\", from: \"OPEN\", on: \"beat.unanswered\", to: \"MISSING\" },\n { id: \"ps.pong\", from: \"MISSING\", on: \"rx.pong\", to: \"OPEN\" },\n { id: \"ps.ping\", from: [\"OPEN\", \"MISSING\"], on: \"rx.ping\", to: \"OPEN\", emits: [\"tx.pong\"], source: \"transport.js:318-322\" },\n { id: \"ps.terminate\", from: \"MISSING\", on: \"misses-reached\", to: \"CLOSED\", timer: \"heartbeat\", emits: [\"tx.fin\"], source: \"transport.js:97-101\" },\n { id: \"ps.close\", from: [\"OPEN\", \"MISSING\"], on: [\"close\", \"socket.error\"], to: \"CLOSED\" },\n ],\n over: {\n machine: \"systems.machine.linux-tcp\",\n states: { OPEN: \"ESTABLISHED\", MISSING: \"ESTABLISHED\" },\n sets: {},\n ends: \"socket.error\",\n },\n} satisfies Machine);\n","import type { Machine } from \"@mark1russell7/algebra\";\nimport { machineSchema } from \"@mark1russell7/algebra\";\n\n// The source of each fact below is src/sentinel.c of Valkey at the tag 9.1.2, unless a line names\n// src/server.c or src/server.h. Each line number is a line of that file at that tag.\nconst AT = \"valkey 9.1.2 src/sentinel.c\";\n\n/**\n * This document is the Sentinel of Valkey 9.1.2. It gives the view of one Sentinel on the primary\n * of a group that it monitors, and the failover that it can lead. The states are the down states\n * and the states of the failover. The timers are the periods and the timeouts of the Sentinel.\n * Each timer of a period checks at the next tick of the Sentinel, thus its lateness is one tick.\n */\nexport const SENTINEL: Machine = machineSchema.parse({\n format: \"mark1russell7.machine/1\",\n id: \"valkey-sentinel\",\n title: \"Valkey 9.1 Sentinel: one Sentinel's view of its primary, and the failover it leads\",\n layer: \"server\",\n version: \"9.1.2\",\n conditions: { valkey: \"9.1.2\", image: \"valkey/valkey:9.1 (Debian 13)\" },\n sources: [\n { ref: `${AT}:84-98 (the periods and timeouts of a Sentinel)`, rung: \"implemented\" },\n { ref: `${AT}:5465-5479 sentinelTimer, and src/server.c:1673 and :1724 (the tick at 1000 / hz ms, hz = 10 + rand() % 10)`, rung: \"implemented\" },\n { ref: `${AT}:3012-3071 sentinelSendPeriodicCommands (PING, INFO, hello)`, rung: \"implemented\" },\n { ref: `${AT}:4443-4540 the subjective and the objective down`, rung: \"implemented\" },\n { ref: `${AT}:4581-4760 the asks, the votes and the leader`, rung: \"implemented\" },\n { ref: `${AT}:4938-5357 the failover state machine`, rung: \"implemented\" },\n { ref: `${AT}:2440-2690 sentinelRefreshInstanceInfo (the promotion, the conversion of an old primary)`, rung: \"implemented\" },\n { ref: `${AT}:2772-2876 sentinelProcessHelloMessage (a newer configuration switches the other Sentinels)`, rung: \"implemented\" },\n { ref: \"measured by @mark1russell7/harness on 2026-10-16: one planned failover, its events 52-100 ms apart\", rung: \"observed\" },\n ],\n states: {\n up: { initial: true, note: \"the primary answers PING; no failover\" },\n sdown: { note: \"subjectively down: no PONG for down-after-milliseconds (sentinel.c:4482-4491)\" },\n odown: { note: \"objectively down: quorum Sentinels say it is down (sentinel.c:4508-4540)\" },\n \"wait-start\": { note: \"SENTINEL_FAILOVER_STATE_WAIT_START: the election (sentinel.c:5090-5119)\" },\n \"select-replica\": { note: \"SENTINEL_FAILOVER_STATE_SELECT_REPLICA (sentinel.c:5121-5137)\" },\n \"send-replicaof-noone\": { note: \"SENTINEL_FAILOVER_STATE_SEND_REPLICAOF_NOONE (sentinel.c:5171-5196)\" },\n \"wait-promotion\": { note: \"SENTINEL_FAILOVER_STATE_WAIT_PROMOTION: INFO of the replica tells its new role (sentinel.c:5198-5205)\" },\n \"reconf-replicas\": { note: \"SENTINEL_FAILOVER_STATE_RECONF_REPLICAS: the other replicas follow the new primary (sentinel.c:5269-5321)\" },\n \"update-config\": { note: \"SENTINEL_FAILOVER_STATE_UPDATE_CONFIG: +switch-master, then the new primary is the primary (sentinel.c:5324-5332)\" },\n },\n events: {\n \"timer.tick\": { kind: \"timer\", note: \"sentinelTimer, from serverCron (server.c:1673)\" },\n \"tx.ping\": { kind: \"tx\", note: \"a PING to the primary; act_ping_time is its time until a PONG (sentinel.c:2994-3008)\" },\n \"rx.pong\": { kind: \"rx\", note: \"a PONG; act_ping_time goes to 0 (sentinel.c:2731-2732)\" },\n \"timer.down-after\": { kind: \"timer\" },\n \"tx.ask\": { kind: \"tx\", note: \"SENTINEL is-master-down-by-addr to each other Sentinel (sentinel.c:4581-4624)\" },\n \"rx.down-reply\": { kind: \"rx\", note: \"another Sentinel says that the primary is down\" },\n \"local.quorum\": { kind: \"local\", note: \"quorum Sentinels say down, this one too (sentinel.c:4512-4524)\" },\n \"local.start\": { kind: \"local\", note: \"+try-failover: ODOWN, no failover in progress, none in 2 × failover-timeout (sentinel.c:4961-4985)\" },\n \"app.failover\": { kind: \"app\", note: \"SENTINEL FAILOVER <group>: no ODOWN, and no election (sentinel.c:3949-3962)\" },\n \"rx.votes\": { kind: \"rx\", note: \"a majority of the Sentinels and quorum votes for this one (sentinel.c:4744-4745)\" },\n \"timer.election\": { kind: \"timer\" },\n \"local.selected\": { kind: \"local\", note: \"+selected-slave: the best replica (sentinel.c:5047-5087)\" },\n \"local.no-replica\": { kind: \"local\" },\n \"tx.replicaof-noone\": { kind: \"tx\", note: \"MULTI, REPLICAOF NO ONE, CONFIG REWRITE, CLIENT KILL, EXEC (sentinel.c:4868-4936)\" },\n \"rx.info-master\": { kind: \"rx\", note: \"INFO of the promoted replica says role:master (sentinel.c:2610-2630)\" },\n \"timer.promotion\": { kind: \"timer\" },\n \"rx.info-reconfigured\": { kind: \"rx\", note: \"INFO of each other replica says that it follows the new primary, with its link up (sentinel.c:2664-2683)\" },\n \"timer.reconf\": { kind: \"timer\" },\n \"rx.hello-newer\": { kind: \"rx\", note: \"a hello with a newer configuration epoch (sentinel.c:2848-2862)\" },\n \"local.switch\": { kind: \"local\", note: \"+switch-master (sentinel.c:5324-5332, :2857)\" },\n \"tx.info\": { kind: \"tx\" },\n \"rx.info\": { kind: \"rx\" },\n \"tx.hello\": { kind: \"tx\", note: \"PUBLISH to __sentinel__:hello of each instance (sentinel.c:2917-2958)\" },\n \"timer.convert\": { kind: \"timer\" },\n \"tx.convert\": { kind: \"tx\", note: \"+convert-to-slave: REPLICAOF and CLIENT KILL to an old primary that came back (sentinel.c:2631-2643)\" },\n \"timer.retry\": { kind: \"timer\" },\n \"timer.low-activity\": { kind: \"timer\" },\n },\n knobs: {\n down_after: { key: \"sentinel down-after-milliseconds\", scope: \"group\", unit: \"ms\", default: 30000, note: \"sentinel.c:90\" },\n failover_timeout: { key: \"sentinel failover-timeout\", scope: \"group\", unit: \"ms\", default: 180000, note: \"sentinel.c:98\" },\n parallel_syncs: { key: \"sentinel parallel-syncs\", scope: \"group\", unit: \"count\", default: 1, note: \"sentinel.c:102\" },\n quorum: { key: \"sentinel monitor <quorum>\", scope: \"group\", unit: \"count\", default: null },\n config_hz: {\n key: \"CONFIG_DEFAULT_HZ\",\n scope: \"build\",\n unit: \"Hz\",\n default: 10,\n note: \"server.h:139. Sentinel sets hz to 10 + rand() % 10 after each tick (sentinel.c:5478), so a tick is 52 to 100 ms\",\n },\n ping_period: { key: \"SENTINEL DEBUG ping-period\", scope: \"process\", unit: \"ms\", default: 1000, note: \"sentinel.c:84, :87\" },\n info_period: { key: \"SENTINEL DEBUG info-period\", scope: \"process\", unit: \"ms\", default: 10000, note: \"sentinel.c:86\" },\n info_period_failover: {\n key: \"the INFO period of a replica of a primary in ODOWN or in a failover\",\n scope: \"build\",\n unit: \"ms\",\n default: 1000,\n note: \"sentinel.c:3037-3039\",\n },\n ask_period: { key: \"SENTINEL DEBUG ask-period\", scope: \"process\", unit: \"ms\", default: 1000, note: \"sentinel.c:88\" },\n publish_period: { key: \"SENTINEL DEBUG publish-period\", scope: \"process\", unit: \"ms\", default: 2000, note: \"sentinel.c:89\" },\n tilt_trigger: { key: \"SENTINEL DEBUG tilt-trigger\", scope: \"process\", unit: \"ms\", default: 2000, note: \"sentinel.c:91\" },\n tilt_period: { key: \"SENTINEL DEBUG tilt-period\", scope: \"process\", unit: \"ms\", default: 30000, note: \"sentinel.c:92\" },\n replica_reconf_timeout: { key: \"SENTINEL DEBUG slave-reconf-timeout\", scope: \"process\", unit: \"ms\", default: 10000, note: \"sentinel.c:93\" },\n min_link_reconnect_period: {\n key: \"SENTINEL DEBUG min-link-reconnect-period\",\n scope: \"process\",\n unit: \"ms\",\n default: 15000,\n note: \"sentinel.c:94\",\n },\n election_timeout: { key: \"SENTINEL DEBUG election-timeout\", scope: \"process\", unit: \"ms\", default: 10000, note: \"sentinel.c:95\" },\n max_desync: { key: \"SENTINEL_MAX_DESYNC\", scope: \"build\", unit: \"ms\", default: 1000, note: \"sentinel.c:105\" },\n },\n timers: {\n tick: {\n // serverCron returns 1000 / server.hz (server.c:1724), and Sentinel draws hz from 10 to 19 (sentinel.c:5478)\n duration: { expr: \"1000 / config_hz\", unit: \"ms\" },\n early: { expr: \"1000 / config_hz - floor(1000 / (2 * config_hz - 1))\", unit: \"ms\" },\n arms: [\"timer.tick\"],\n fires: \"timer.tick\",\n note: \"the period of sentinelTimer: each check below occurs at a tick, so its lateness is one tick\",\n },\n ping: {\n // ping_period = min(down_after, ping period), sent when the last PONG is older (sentinel.c:3047-3060)\n duration: { expr: \"min(down_after, ping_period)\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"rx.pong\"],\n fires: \"tx.ping\",\n },\n down_after: {\n // elapsed = now - act_ping_time > down_after_period, in whole ms (sentinel.c:4446-4447, :4482)\n duration: { knob: \"down_after\", unit: \"ms\" },\n lateness: { expr: \"1 + 1000 / config_hz\", unit: \"ms\" },\n arms: [\"tx.ping\"],\n cancels: [\"rx.pong\"],\n fires: \"timer.down-after\",\n note: \"it counts from the first PING without a PONG (act_ping_time). A link that closes keeps that time, and its next connect sends a PING at once (sentinel.c:2386-2387)\",\n },\n ask: {\n // asked again when the last reply is ask_period old, and a reply 5 × ask_period old is stale (sentinel.c:4598, :4610)\n duration: { knob: \"ask_period\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"rx.down-reply\"],\n fires: \"tx.ask\",\n },\n info: {\n duration: { knob: \"info_period\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"rx.info\"],\n fires: \"tx.info\",\n note: \"INFO to each primary and replica when the last reply is older (sentinel.c:3049-3053)\",\n },\n info_failover: {\n duration: { knob: \"info_period_failover\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"rx.info\"],\n fires: \"tx.info\",\n note: \"the INFO period of a replica while its primary is ODOWN or in a failover: the promotion is seen at the next INFO\",\n },\n hello: {\n duration: { knob: \"publish_period\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"tx.hello\"],\n fires: \"tx.hello\",\n note: \"a promotion forces the next hello at the next tick (sentinel.c:2630, :2980-2987)\",\n },\n election: {\n // the election timeout is min(SENTINEL_ELECTION_TIMEOUT, failover-timeout) (sentinel.c:5102-5110)\n duration: { expr: \"min(election_timeout, failover_timeout)\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"local.start\"],\n cancels: [\"rx.votes\", \"app.failover\"],\n fires: \"timer.election\",\n note: \"-failover-abort-not-elected. A forced failover (SENTINEL FAILOVER) does not wait for votes\",\n },\n desync: {\n // failover_start_time = now + rand() % SENTINEL_MAX_DESYNC (sentinel.c:4946, :4654)\n duration: { const: 0, unit: \"ms\" },\n lateness: { expr: \"max_desync - 1\", unit: \"ms\" },\n arms: [\"local.start\"],\n fires: \"timer.election\",\n note: \"a random delay of the start time: it moves the abort of an election and the next attempt, not the election itself\",\n },\n retry: {\n duration: { expr: \"failover_timeout * 2\", unit: \"ms\" },\n arms: [\"local.start\"],\n fires: \"timer.retry\",\n note: \"no new failover of the same primary sooner (sentinel.c:4969). A switch resets it (sentinel.c:1545)\",\n },\n promotion: {\n duration: { knob: \"failover_timeout\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"tx.replicaof-noone\"],\n cancels: [\"rx.info-master\"],\n fires: \"timer.promotion\",\n note: \"-failover-abort-slave-timeout (sentinel.c:5198-5205)\",\n },\n reconf: {\n duration: { knob: \"replica_reconf_timeout\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"rx.info-master\"],\n cancels: [\"rx.info-reconfigured\"],\n fires: \"timer.reconf\",\n note: \"a replica that does not follow in time counts as done (sentinel.c:5294-5300)\",\n },\n convert: {\n // a replica that reports master waits publish_period × 4 after the change of its role (sentinel.c:2635-2640)\n duration: { expr: \"publish_period * 4\", unit: \"ms\" },\n arms: [\"rx.info-master\"],\n fires: \"timer.convert\",\n note: \"the check runs at each INFO reply, so the conversion comes at the first INFO after this wait\",\n },\n low_activity: {\n // a command link with a PING pending for down_after / 2, open for min_link_reconnect_period, closes (sentinel.c:4456-4464)\n duration: { expr: \"max(min_link_reconnect_period, down_after / 2)\", unit: \"ms\" },\n lateness: { expr: \"1000 / config_hz\", unit: \"ms\" },\n arms: [\"tx.ping\"],\n cancels: [\"rx.pong\"],\n fires: \"timer.low-activity\",\n },\n },\n transitions: [\n { id: \"sdown\", from: \"up\", to: \"sdown\", on: \"timer.down-after\", timer: \"down_after\", emits: [\"+sdown\"], source: \"sentinel.c:4482-4491\" },\n { id: \"sdown-clear\", from: \"sdown\", to: \"up\", on: \"rx.pong\", emits: [\"-sdown\"], source: \"sentinel.c:4493-4498\" },\n {\n id: \"odown\",\n from: \"sdown\",\n to: \"odown\",\n on: \"local.quorum\",\n emits: [\"+odown\"],\n guard: \"the reply of another Sentinel that is down too, then this Sentinel's next tick\",\n source: \"sentinel.c:4508-4535\",\n },\n { id: \"odown-clear\", from: \"odown\", to: \"up\", on: \"rx.pong\", emits: [\"-odown\", \"-sdown\"] },\n { id: \"start\", from: \"odown\", to: \"wait-start\", on: \"local.start\", emits: [\"+new-epoch\", \"+try-failover\"], source: \"sentinel.c:4938-4948\" },\n {\n id: \"planned\",\n from: \"up\",\n to: \"wait-start\",\n on: \"app.failover\",\n emits: [\"+new-epoch\", \"+try-failover\"],\n guard: \"SRI_FORCE_FAILOVER: no election. COORDINATED holds an election as an ODOWN does\",\n source: \"sentinel.c:3949-3962\",\n },\n {\n id: \"elected\",\n from: \"wait-start\",\n to: \"select-replica\",\n on: [\"rx.votes\", \"app.failover\"],\n emits: [\"+elected-leader\", \"+failover-state-select-slave\"],\n guard: \"at the next tick after the votes\",\n source: \"sentinel.c:5090-5119\",\n },\n { id: \"not-elected\", from: \"wait-start\", to: \"odown\", on: \"timer.election\", timer: \"election\", emits: [\"-failover-abort-not-elected\"] },\n {\n id: \"selected\",\n from: \"select-replica\",\n to: \"send-replicaof-noone\",\n on: \"local.selected\",\n emits: [\"+selected-slave\", \"+failover-state-send-slaveof-noone\"],\n guard: \"at the next tick\",\n source: \"sentinel.c:5121-5137\",\n },\n { id: \"no-replica\", from: \"select-replica\", to: \"odown\", on: \"local.no-replica\", emits: [\"-failover-abort-no-good-slave\"] },\n {\n id: \"replicaof-noone\",\n from: \"send-replicaof-noone\",\n to: \"wait-promotion\",\n on: \"tx.replicaof-noone\",\n emits: [\"+failover-state-wait-promotion\"],\n guard: \"at the next tick\",\n source: \"sentinel.c:5171-5196\",\n },\n {\n id: \"promoted\",\n from: \"wait-promotion\",\n to: \"reconf-replicas\",\n on: \"rx.info-master\",\n emits: [\"+promoted-slave\", \"+failover-state-reconf-slaves\"],\n note: \"get-master-addr-by-name gives the new primary from here (sentinel.c:1658-1670)\",\n source: \"sentinel.c:2610-2630\",\n },\n { id: \"promotion-timeout\", from: \"wait-promotion\", to: \"odown\", on: \"timer.promotion\", timer: \"promotion\", emits: [\"-failover-abort-slave-timeout\"] },\n {\n id: \"reconfigured\",\n from: \"reconf-replicas\",\n to: \"update-config\",\n on: [\"rx.info-reconfigured\", \"timer.reconf\"],\n emits: [\"+failover-end\"],\n source: \"sentinel.c:5207-5246\",\n },\n { id: \"switch\", from: \"update-config\", to: \"up\", on: \"local.switch\", emits: [\"+switch-master\"], source: \"sentinel.c:5324-5332\" },\n {\n id: \"switch-from-hello\",\n from: [\"up\", \"sdown\", \"odown\"],\n to: \"up\",\n on: \"rx.hello-newer\",\n emits: [\"+config-update-from\", \"+switch-master\"],\n note: \"the other Sentinels switch on the hello of the leader, before the leader's own +failover-end\",\n source: \"sentinel.c:2848-2862\",\n },\n ],\n});\n","// @mark1russell7/machines: the machine documents of the systems program, in one place. Each\n// document is a `mark1russell7.machine/1` document of @mark1russell7/algebra. It describes one\n// system at one version from its source, and each fact names its file and line. The schema of the\n// algebra examines each document at load. A document changes only for a reason from its source\n// (a citation) or from a measurement (a run).\n\nimport type { Machine } from \"@mark1russell7/algebra\";\nimport { GO_TRANSPORT } from \"./http/go-transport.ts\";\nimport { NODE_HTTP_AGENT } from \"./http/node-agent.ts\";\nimport { NODE_HTTP_SERVER } from \"./http/node-server.ts\";\nimport { UNDICI_CLIENT } from \"./http/undici.ts\";\nimport { IOREDIS_SENTINEL } from \"./ioredis-sentinel.ts\";\nimport { IOREDIS_STATUS, LINUX_TCP, NF_CONNTRACK_TCP, REDIS_CLIENT } from \"./json.ts\";\nimport { MONGOD_REPL } from \"./mongo/mongod-replication.ts\";\nimport { MONGOD_SESSION } from \"./mongo/mongod-session.ts\";\nimport { MONGODB_NODE } from \"./mongo/mongodb-node.ts\";\nimport { HIKARICP_PGJDBC } from \"./pg/hikaricp-pgjdbc.ts\";\nimport { NODE_POSTGRES } from \"./pg/node-postgres.ts\";\nimport { PGBOUNCER_CLIENT } from \"./pg/pgbouncer.ts\";\nimport { PGBOUNCER_SERVER } from \"./pg/pgbouncer-server.ts\";\nimport { PGPOOL_SESSION } from \"./pg/pgpool.ts\";\nimport { POSTGRES_SESSION } from \"./pg/postgres-session.ts\";\nimport { SUPAVISOR_CLIENT } from \"./pg/supavisor-client.ts\";\nimport { SUPAVISOR_SERVER } from \"./pg/supavisor-server.ts\";\nimport { PROCEDURES_WS_CLIENT, PROCEDURES_WS_SERVER } from \"./procedures-ws.ts\";\nimport { SENTINEL } from \"./sentinel.ts\";\n\nexport {\n GO_TRANSPORT,\n HIKARICP_PGJDBC,\n IOREDIS_SENTINEL,\n IOREDIS_STATUS,\n LINUX_TCP,\n MONGOD_REPL,\n MONGOD_SESSION,\n MONGODB_NODE,\n NF_CONNTRACK_TCP,\n NODE_HTTP_AGENT,\n NODE_HTTP_SERVER,\n NODE_POSTGRES,\n PGBOUNCER_CLIENT,\n PGBOUNCER_SERVER,\n PGPOOL_SESSION,\n POSTGRES_SESSION,\n PROCEDURES_WS_CLIENT,\n PROCEDURES_WS_SERVER,\n REDIS_CLIENT,\n SENTINEL,\n SUPAVISOR_CLIENT,\n SUPAVISOR_SERVER,\n UNDICI_CLIENT,\n};\nexport { MANIFESTATIONS } from \"./json.ts\";\nexport {\n NODE_TIMER_EARLY,\n UNDICI_TICK_MS,\n goLateSeconds,\n goTimerLateness,\n nodeEarlySeconds,\n nodeLateSeconds,\n nodeTimerLateness,\n undiciFastEarly,\n undiciFastLateness,\n} from \"./http/timers.ts\";\n\n/** This function gives each document by its identifier. Two documents with one identifier stop the import. */\nconst byId = (documents: readonly Machine[]): Readonly<Record<string, Machine>> => {\n const out: Record<string, Machine> = {};\n for (const document of documents) {\n if (out[document.id] !== undefined) throw new Error(`two machine documents have the identifier ${document.id}`);\n out[document.id] = document;\n }\n return Object.freeze(out);\n};\n\n/**\n * This map holds each document of the package by its identifier, for example `linux-tcp`. A\n * document on another machine names that machine in `over.machine` as `systems.machine.<id>`.\n */\nexport const MACHINES: Readonly<Record<string, Machine>> = byId([\n LINUX_TCP,\n NF_CONNTRACK_TCP,\n REDIS_CLIENT,\n IOREDIS_STATUS,\n IOREDIS_SENTINEL,\n SENTINEL,\n NODE_HTTP_SERVER,\n NODE_HTTP_AGENT,\n UNDICI_CLIENT,\n GO_TRANSPORT,\n PROCEDURES_WS_CLIENT,\n PROCEDURES_WS_SERVER,\n MONGODB_NODE,\n MONGOD_REPL,\n MONGOD_SESSION,\n NODE_POSTGRES,\n POSTGRES_SESSION,\n HIKARICP_PGJDBC,\n PGBOUNCER_CLIENT,\n PGBOUNCER_SERVER,\n PGPOOL_SESSION,\n SUPAVISOR_CLIENT,\n SUPAVISOR_SERVER,\n]);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,MAAM,WAAW,OAAuB,YAAY,GAAG;;;;;AAMvD,MAAM,YAAY;;;;;;AAOlB,MAAa,qBAAqB,QAAsB;CAAE,MAAM,GAAG,QAAQ,EAAE,EAAE,SAAS;CAAa,MAAM;AAAK;;;;;AAMhH,MAAa,mBAAyB;CAAE,MAAM,OAAO;CAAa,MAAM;AAAK;;AAG7E,MAAa,mBAAmB,OAAqB;CACnD,MAAM,YAAY,EAAE;CACpB,MAAM;AACR;;AAGA,MAAM,iBAAiB,OAAwB,KAAK,IAAI,KAAK,MAAM,KAAK,GAAI,GAAG,CAAC,IAAI,MAAQ,KAAK;;AAGjG,MAAa,mBAAmB,SAAiB,QAC9C,KAAK,IAAI,KAAK,IAAI,SAAS,GAAI,GAAG,GAAG,IAAI,KAAK,MAAO,cAAc,EAAE;;AAGxE,MAAa,oBAAoB,OAAuB,OAAQ,cAAc,EAAE;;AAGhF,MAAa,iBAAiB,YAA4B,KAAK,IAAI,KAAK,IAAI,UAAU,KAAM,IAAO,GAAG,EAAG,IAAI;;;;;AAM7G,MAAa,iBAAiB;;;;;;;;;;;;AAa9B,MAAa,mBAAmB,QAAsB;CACpD,MAAM,IAAI,GAAG,aAAa,GAAG,4BAAwD;CACrF,MAAM;AACR;;;;;;AAOA,MAAa,sBAAsB,QAAsB;CACvD,MACE,SAAS,GAAG,oBAAgD,GAAG,YACnD,GAAG,cAA4B,QAAQ,OAAA,GAAqB,CAAC,EAAE,SAAS,UAAU;CAChG,MAAM;AACR;;;;;;;;;;;;;AClGA,MAAa,eAAwB,cAAc,MAAM;CACvD,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EAAE,IAAI;EAAU,IAAI;EAAS,UAAU;CAAuB;CAC1E,SAAS;EACP;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;CACF;CACA,QAAQ;EACN,QAAQ;GAAE,SAAS;GAAM,QAAQ;EAAK;EACtC,SAAS,CAAC;EACV,QAAQ,EAAE,MAAM,gCAAgC;EAChD,MAAM,EAAE,MAAM,kCAAkC;EAChD,QAAQ,EAAE,OAAO,KAAK;CACxB;CACA,QAAQ;EACN,gBAAgB;GAAE,MAAM;GAAO,MAAM;EAA0D;EAC/F,oBAAoB,EAAE,MAAM,QAAQ;EACpC,aAAa;GAAE,MAAM;GAAS,MAAM;EAAwE;EAC5G,UAAU;GAAE,MAAM;GAAQ,MAAM;EAA6B;EAC7D,cAAc;GAAE,MAAM;GAAS,MAAM;EAAoD;EACzF,UAAU,EAAE,MAAM,OAAO;EACzB,gBAAgB;GAAE,MAAM;GAAM,MAAM;EAAqC;EACzE,mBAAmB,EAAE,MAAM,QAAQ;EACnC,cAAc,EAAE,MAAM,QAAQ;EAC9B,gBAAgB,EAAE,MAAM,QAAQ;EAChC,yBAAyB,EAAE,MAAM,QAAQ;EACzC,cAAc;GAAE,MAAM;GAAM,MAAM;EAAmC;EACrE,cAAc,EAAE,MAAM,KAAK;CAC7B;CACA,OAAO;EACL,iBAAiB;GAAE,KAAK;GAAqC,OAAO;GAAU,MAAM;GAAK,SAAS;EAAG;EACrG,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,cAAc;GAAE,KAAK;GAAkC,OAAO;GAAU,MAAM;GAAS,SAAS;EAAI;EACpG,aAAa;GAAE,KAAK;GAAyB,OAAO;GAAU,MAAM;GAAK,SAAS;EAAG;EACrF,WAAW;GACT,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,mBAAmB;GACjB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,SAAS;GACP,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,uBAAuB;GACrB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,WAAW;GACT,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAI;GAC/C,UAAU,gBAAgB,iBAAiB;GAC3C,MAAM,CAAC,aAAa,YAAY;GAChC,SAAS,CAAC,cAAc;GACxB,OAAO;GACP,MAAM;EACR;EACA,MAAM;GACJ,UAAU;IAAE,MAAM;IAAe,MAAM;GAAI;GAC3C,UAAU,gBAAgB,aAAa;GACvC,MAAM,CAAC,eAAe;GACtB,SAAS,CAAC,kBAAkB;GAC5B,OAAO;EACT;EACA,QAAQ;GACN,UAAU;IAAE,MAAM;IAAW,MAAM;GAAI;GACvC,UAAU,gBAAgB,SAAS;GACnC,MAAM,CAAC,gBAAgB,cAAc;GACrC,SAAS,CAAC,WAAW;GACrB,OAAO;EACT;EACA,iBAAiB;GACf,UAAU;IAAE,MAAM;IAAyB,MAAM;GAAI;GACrD,UAAU,gBAAgB,uBAAuB;GACjD,MAAM,CAAC,cAAc,cAAc;GACnC,SAAS,CAAC,YAAY;GACtB,OAAO;EACT;CACF;CACA,UAAU;EACR,sCAAsC,EAAE,OAAO,YAAY;EAC3D,mCAAmC,EAAE,OAAO,OAAO;EACnD,qCAAqC,EAAE,OAAO,SAAS;CACzD;CACA,aAAa;EACX;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,QAAQ;EACV;EACA;GAAE,IAAI;GAAgB,MAAM;GAAW,IAAI;GAAU,IAAI;EAAmB;EAC5E;GAAE,IAAI;GAAmB,MAAM;GAAW,IAAI;GAAU,IAAI;GAAc,OAAO;GAAQ,OAAO;EAAU;EAC1G;GAAE,IAAI;GAAmB,MAAM;GAAW,IAAI;GAAU,IAAI;GAAU,OAAO;EAAe;EAC5F;GAAE,IAAI;GAAuB,MAAM;GAAW,IAAI;GAAU,IAAI;GAAgB,OAAO;EAAe;EACtG;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,QAAQ;GAChB,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI,CAAC,UAAU,YAAY;GAC3B,OAAO,CAAC,QAAQ;GAChB,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI,CAAC,UAAU,YAAY;GAC3B,OAAO;GACP,OAAO,CAAC,WAAW;GACnB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI,CAAC,UAAU,YAAY;GAC3B,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;CACF;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GAAE,SAAS;GAAY,QAAQ;GAAe,MAAM;EAAc;EAC1E,MAAM;GACJ,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAI;GAC/C,WAAW;IAAE,MAAM;IAA2B,MAAM;GAAI;GACxD,SAAS;IAAE,MAAM;IAAkB,MAAM;GAAQ;EACnD;EACA,MAAM;EACN,MAAM;CACR;AACF,CAAmB;;;;;;;;;;;;;;;;;ACzNnB,MAAa,kBAA2B,cAAc,MAAM;CAC1D,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EAAE,MAAM;EAAW,OAAO;EAAU,OAAO;CAAiD;CACxG,SAAS;EACP;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;CACF;CACA,QAAQ;EACN,QAAQ;GAAE,SAAS;GAAM,QAAQ;EAAK;EACtC,YAAY,CAAC;EACb,MAAM,EAAE,MAAM,4BAA4B;EAC1C,MAAM,EAAE,MAAM,uCAAuC;EACrD,QAAQ,EAAE,OAAO,KAAK;CACxB;CACA,QAAQ;EACN,gBAAgB;GAAE,MAAM;GAAO,MAAM;EAAmB;EACxD,kBAAkB,EAAE,MAAM,QAAQ;EAClC,YAAY;GACV,MAAM;GACN,MAAM;EACR;EACA,UAAU,EAAE,MAAM,OAAO;EACzB,UAAU,EAAE,MAAM,OAAO;EACzB,WAAW;GAAE,MAAM;GAAQ,MAAM;EAA+B;EAChE,qBAAqB,EAAE,MAAM,QAAQ;EACrC,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAgE;CACzG;CACA,OAAO;EACL,WAAW;GACT,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,SAAS;GACP,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,gBAAgB;GAAE,KAAK;GAAkC,OAAO;GAAU,MAAM;GAAM,SAAS;EAAK;EACpG,6BAA6B;GAC3B,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;EACX;EACA,gBAAgB;GAAE,KAAK;GAAkC,OAAO;GAAU,MAAM;GAAS,SAAS;EAAI;EACtG,MAAM;GACJ,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,IAAI;GACF,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ,EACN,aAAa;EACX,UAAU;GAAE,MAAM;GAA2D,MAAM;EAAK;EACxF,UAAU,kBAAkB,yDAAyD;EACrF,OAAO;EACP,MAAM,CAAC,YAAY,YAAY;EAC/B,SAAS,CAAC,cAAc;EACxB,OAAO;EACP,MAAM;CACR,EACF;CACA,UAAU,EACR,sCAAsC,EAAE,OAAO,cAAc,EAC/D;CACA,aAAa;EACX;GAAE,IAAI;GAAc,MAAM;GAAU,IAAI;GAAc,IAAI;GAAgB,OAAO;EAAiB;EAClG;GAAE,IAAI;GAAgB,MAAM;GAAc,IAAI;GAAQ,IAAI;EAAiB;EAC3E;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,QAAQ;GAChB,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,QAAQ;GAChB,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAAU;IAAU;IAAW;GAAc;GAClD,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI,CAAC,UAAU,cAAc;GAC7B,OAAO;GACP,MAAM;GACN,QAAQ;EACV;CACF;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GAAE,YAAY;GAAY,MAAM;GAAe,MAAM;EAAc;EAC3E,MAAM;GACJ,UAAU;IAAE,MAAM;IAAgC,MAAM;GAAI;GAC5D,WAAW;IAAE,OAAO;IAAG,MAAM;GAAI;GACjC,SAAS;IAAE,OAAO;IAAI,MAAM;GAAQ;EACtC;EACA,MAAM;EACN,MAAM;CACR;AACF,CAAmB;;;;;;;;;;;;;ACpMnB,MAAa,mBAA4B,cAAc,MAAM;CAC3D,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EAAE,MAAM;EAAW,OAAO;EAAU,QAAQ;CAAY;CACpE,SAAS;EACP;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;CACF;CACA,QAAQ;EACN,QAAQ;GAAE,SAAS;GAAM,QAAQ;EAAK;EACtC,SAAS,EAAE,MAAM,qFAAqF;EACtG,SAAS,EAAE,MAAM,qEAAqE;EACtF,UAAU,EAAE,MAAM,qFAAqF;EACvG,MAAM,EAAE,MAAM,wDAAwD;EACtE,QAAQ,EAAE,OAAO,KAAK;CACxB;CACA,QAAQ;EACN,QAAQ,EAAE,MAAM,QAAQ;EACxB,oBAAoB;GAAE,MAAM;GAAM,MAAM;EAAwD;EAChG,cAAc;GAAE,MAAM;GAAM,MAAM;EAA0D;EAC5F,uBAAuB;GAAE,MAAM;GAAM,MAAM;EAA0C;EACrF,WAAW;GAAE,MAAM;GAAM,MAAM;EAAqE;EACpG,cAAc;GAAE,MAAM;GAAS,MAAM;EAAiD;EACtF,UAAU;GAAE,MAAM;GAAQ,MAAM;EAAqF;EACrH,UAAU,EAAE,MAAM,OAAO;EACzB,oBAAoB,EAAE,MAAM,QAAQ;EACpC,iBAAiB,EAAE,MAAM,QAAQ;EACjC,iBAAiB,EAAE,MAAM,QAAQ;EACjC,gBAAgB,EAAE,MAAM,QAAQ;EAChC,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAA+D;CACxG;CACA,OAAO;EACL,kBAAkB;GAChB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GAAM,KAAK;GACpB,MAAM;EACR;EACA,wBAAwB;GACtB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,gBAAgB;GAAE,KAAK;GAAmC,OAAO;GAAU,MAAM;GAAM,SAAS;EAAM;EACtG,gBAAgB;GAAE,KAAK;GAAmC,OAAO;GAAU,MAAM;GAAM,SAAS;EAAO;EACvG,6BAA6B;GAC3B,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;EACX;EACA,SAAS;GACP,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GAAG,KAAK;GACjB,MAAM;EACR;EACA,sBAAsB;GACpB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,IAAI;GACF,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,YAAY;GACV,UAAU;IAAE,MAAM;IAA6C,MAAM;GAAK;GAC1E,UAAU,kBAAkB,2CAA2C;GACvE,OAAO;GACP,MAAM;IAAC;IAAc;IAAW;GAAY;GAC5C,SAAS,CAAC,YAAY;GACtB,OAAO;GACP,MAAM;EACR;EACA,SAAS;GACP,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,UAAU;IACR,MAAM;IACN,MAAM;GACR;GACA,MAAM;IAAC;IAAU;IAAoB;IAAiB;GAAe;GACrE,SAAS,CAAC,YAAY;GACtB,OAAO;GACP,MAAM;EACR;EACA,SAAS;GACP,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,UAAU;IACR,MAAM;IACN,MAAM;GACR;GACA,MAAM;IAAC;IAAU;IAAoB;GAAe;GACpD,SAAS,CAAC,qBAAqB;GAC/B,OAAO;EACT;EACA,QAAQ;GACN,UAAU;IAAE,MAAM;IAAW,MAAM;GAAK;GACxC,UAAU,kBAAkB,SAAS;GACrC,OAAO;GACP,MAAM,CAAC,cAAc,gBAAgB;GACrC,SAAS,CAAC,YAAY;GACtB,OAAO;GACP,MAAM;EACR;CACF;CACA,UAAU,EACR,uCAAuC,EAAE,OAAO,aAAa,EAC/D;CACA,aAAa;EACX;GAAE,IAAI;GAAa,MAAM;GAAU,IAAI;GAAW,IAAI;EAAS;EAC/D;GACE,IAAI;GACJ,MAAM,CAAC,WAAW,MAAM;GACxB,IAAI;GACJ,IAAI;GACJ,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI,CAAC,cAAc,qBAAqB;GACxC,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,QAAQ;GAChB,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,QAAQ;GAChB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM,CAAC,WAAW,SAAS;GAC3B,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,UAAU,QAAQ;GAC1B,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,UAAU,QAAQ;GAC1B,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;IAAC;IAAW;IAAW;IAAY;GAAM;GAC/C,IAAI;GACJ,IAAI;GACJ,OAAO,CAAC,QAAQ;GAChB,QAAQ;EACV;EACA;GAAE,IAAI;GAAY,MAAM;IAAC;IAAW;IAAW;IAAY;GAAM;GAAG,IAAI;GAAU,IAAI,CAAC,UAAU,cAAc;EAAE;CACnH;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GAAE,SAAS;GAAe,SAAS;GAAe,UAAU;GAAe,MAAM;EAAc;EACvG,MAAM,CAAC;EACP,MAAM;EACN,MAAM;CACR;AACF,CAAmB;;;;;;;;;;;;;;;;;ACpOnB,MAAa,gBAAyB,cAAc,MAAM;CACxD,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EAAE,QAAQ;EAAU,MAAM;EAAW,YAAY;CAAI;CACjE,SAAS;EACP;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;CACF;CACA,QAAQ;EACN,QAAQ;GAAE,SAAS;GAAM,QAAQ;EAAK;EACtC,YAAY,CAAC;EACb,MAAM,EAAE,MAAM,qDAAqD;EACnE,MAAM,EAAE,MAAM,wDAAwD;EACtE,QAAQ,EAAE,OAAO,KAAK;CACxB;CACA,QAAQ;EACN,gBAAgB,EAAE,MAAM,MAAM;EAC9B,kBAAkB,EAAE,MAAM,QAAQ;EAClC,cAAc;GAAE,MAAM;GAAM,MAAM;EAA2C;EAC7E,cAAc,EAAE,MAAM,KAAK;EAC3B,WAAW;GAAE,MAAM;GAAM,MAAM;EAAmD;EAClF,iBAAiB;GACf,MAAM;GACN,MAAM;EACR;EACA,UAAU,EAAE,MAAM,OAAO;EACzB,UAAU,EAAE,MAAM,OAAO;EACzB,oBAAoB,EAAE,MAAM,QAAQ;EACpC,iBAAiB,EAAE,MAAM,QAAQ;EACjC,cAAc,EAAE,MAAM,QAAQ;EAC9B,iBAAiB,EAAE,MAAM,QAAQ;EACjC,gBAAgB,EAAE,MAAM,QAAQ;CAClC;CACA,OAAO;EACL,kBAAkB;GAAE,KAAK;GAAkC,OAAO;GAAU,MAAM;GAAM,SAAS;EAAK;EACtG,qBAAqB;GAAE,KAAK;GAAqC,OAAO;GAAU,MAAM;GAAM,SAAS;EAAO;EAC9G,2BAA2B;GACzB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;EACX;EACA,gBAAgB;GAAE,KAAK;GAAgC,OAAO;GAAU,MAAM;GAAM,SAAS;EAAO;EACpG,aAAa;GAAE,KAAK;GAA6B,OAAO;GAAU,MAAM;GAAM,SAAS;EAAO;EAC9F,gBAAgB;GAAE,KAAK;GAAiC,OAAO;GAAU,MAAM;GAAM,SAAS;EAAM;EACpG,uBAAuB;GACrB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;EACX;EACA,MAAM;GACJ,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,IAAI;GACF,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,YAAY;GACV,UAAU;IAAE,MAAM;IAAqE,MAAM;GAAK;GAClG,UAAU,kBAAkB,mEAAmE;GAC/F,OAAO;GACP,MAAM,CAAC,iBAAiB,YAAY;GACpC,SAAS,CAAC,cAAc;GACxB,OAAO;GACP,MAAM;EACR;EACA,SAAS;GACP,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,UAAU,mBAAmB,gBAAgB;GAC7C,OAAO,gBAAgB,gBAAgB;GACvC,MAAM,CAAC,cAAc,YAAY;GACjC,SAAS,CAAC,YAAY;GACtB,OAAO;EACT;EACA,MAAM;GACJ,UAAU;IAAE,MAAM;IAAe,MAAM;GAAK;GAC5C,UAAU,mBAAmB,aAAa;GAC1C,OAAO,gBAAgB,aAAa;GACpC,MAAM,CAAC,cAAc,SAAS;GAC9B,SAAS,CAAC,eAAe;GACzB,OAAO;EACT;EACA,SAAS;GACP,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,MAAM,CAAC,kBAAkB;GACzB,SAAS,CAAC,gBAAgB;GAC1B,OAAO;EACT;CACF;CACA,UAAU;EACR,sCAAsC,EAAE,OAAO,aAAa;EAC5D,qCAAqC,EAAE,OAAO,UAAU;EACxD,mCAAmC,EAAE,OAAO,UAAU;CACxD;CACA,aAAa;EACX;GAAE,IAAI;GAAc,MAAM;GAAU,IAAI;GAAc,IAAI;EAAe;EACzE;GAAE,IAAI;GAAgB,MAAM;GAAc,IAAI;GAAQ,IAAI;EAAiB;EAC3E;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,QAAQ;GAChB,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,QAAQ;GAChB,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAAU;IAAU;GAAc;GACvC,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI,CAAC,UAAU,cAAc;GAC7B,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;CACF;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GAAE,YAAY;GAAY,MAAM;GAAe,MAAM;EAAc;EAC3E,MAAM;GACJ,UAAU;IAAE,MAAM;IAAuC,MAAM;GAAI;GACnE,WAAW;IAAE,OAAO;IAAG,MAAM;GAAI;GACjC,SAAS;IAAE,OAAO;IAAI,MAAM;GAAQ;EACtC;EACA,MAAM;EACN,MAAM;CACR;AACF,CAAmB;;;ACpPnB,MAAMA,OAAK;;;;;;;;AASX,MAAa,mBAA4B,cAAc,MAAM;CAC3D,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EAAE,SAAS;EAAS,MAAM;EAAY,MAAM;CAAU;CAClE,SAAS;EACP;GAAE,KAAK,GAAGA,KAAG;GAA4G,MAAM;EAAc;EAC7I;GAAE,KAAK,GAAGA,KAAG;GAAkH,MAAM;EAAc;EACnJ;GAAE,KAAK,GAAGA,KAAG;GAA4H,MAAM;EAAc;EAC7J;GAAE,KAAK,GAAGA,KAAG;GAAmF,MAAM;EAAc;EACpH;GAAE,KAAK,GAAGA,KAAG;GAAsG,MAAM;EAAc;EACvI;GAAE,KAAK,GAAGA,KAAG;GAA6C,MAAM;EAAc;EAC9E;GAAE,KAAK,GAAGA,KAAG;GAA4G,MAAM;EAAc;EAC7I;GAAE,KAAK,GAAGA,KAAG;GAAwG,MAAM;EAAc;EACzI;GAAE,KAAK,GAAGA,KAAG;GAAsG,MAAM;EAAc;EACvI;GAAE,KAAK,GAAGA,KAAG;GAA0G,MAAM;EAAc;CAC7I;CACA,QAAQ;EACN,WAAW;GAAE,SAAS;GAAM,QAAQ;EAAK;EACzC,WAAW,EAAE,MAAM,qGAAqG;EACxH,YAAY,EAAE,MAAM,yDAAyD;EAC7E,SAAS,EAAE,MAAM,sGAAsG;EACvH,OAAO,EAAE,MAAM,2BAA2B;EAC1C,OAAO,EAAE,MAAM,iEAAiE;EAChF,cAAc,EAAE,MAAM,oDAAoD;EAC1E,KAAK,EAAE,OAAO,KAAK;CACrB;CACA,QAAQ;EACN,eAAe,EAAE,MAAM,MAAM;EAC7B,mBAAmB;GAAE,MAAM;GAAS,MAAM;EAA6B;EACvE,iBAAiB;GAAE,MAAM;GAAS,MAAM;EAAiF;EACzH,kBAAkB,EAAE,MAAM,QAAQ;EAClC,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAA2E;EAClH,mBAAmB;GAAE,MAAM;GAAS,MAAM;EAA8D;EACxG,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAAqG;EAC9I,eAAe,EAAE,MAAM,QAAQ;EAC/B,wBAAwB,EAAE,MAAM,QAAQ;EACxC,yBAAyB,EAAE,MAAM,QAAQ;EACzC,eAAe;GAAE,MAAM;GAAS,MAAM;EAA+E;EACrH,oBAAoB;GAAE,MAAM;GAAM,MAAM;EAAsF;CAChI;CACA,OAAO;EACL,gBAAgB;GAAE,KAAK;GAA0B,OAAO;GAAU,MAAM;GAAM,SAAS;GAAO,MAAM;EAAoB;EACxH,mBAAmB;GAAE,KAAK;GAA6B,OAAO;GAAU,MAAM;GAAM,SAAS;GAAM,MAAM;EAAqB;EAC9H,WAAW;GAAE,KAAK;GAAqB,OAAO;GAAU,MAAM;GAAM,SAAS;GAAO,MAAM;EAAgE;EAC1J,sBAAsB;GACpB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,qBAAqB;GAAE,KAAK;GAAiC,OAAO;GAAU,MAAM;GAAM,SAAS;GAAI,MAAM;EAAkD;EAC/J,oBAAoB;GAAE,KAAK;GAAiC,OAAO;GAAU,MAAM;GAAM,SAAS;EAAK;EACvG,mBAAmB;GAAE,KAAK;GAAqC,OAAO;GAAU,MAAM;GAAM,SAAS;GAAO,MAAM;EAAuD;EACzK,kBAAkB;GAAE,KAAK;GAA4B,OAAO;GAAU,MAAM;GAAM,SAAS;GAAG,MAAM;EAA0B;EAC9H,gBAAgB;GAAE,KAAK;GAA0B,OAAO;GAAU,MAAM;GAAM,SAAS;GAAM,MAAM;EAAwD;EAC3J,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,KAAK;GAAE,KAAK;GAA8C,OAAO;GAAQ,MAAM;GAAM,SAAS;EAAK;EACnG,OAAO;GACL,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,aAAa;GAEX,UAAU;IAAE,OAAO;IAAsB,OAAO,CAAC,OAAO;IAAG,MAAM;GAAI;GACrE,UAAU;IAAE,MAAM;IAAe,MAAM;GAAK;GAC5C,MAAM,CAAC,cAAc;GACrB,OAAO;GACP,SAAS,EAAE,QAAQ,CAAC,iBAAiB,EAAE;GACvC,MAAM;EACR;EACA,SAAS;GAEP,UAAU;IAAE,MAAM;IAA6B,MAAM;GAAK;GAC1D,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,aAAa;GACpB,OAAO;EACT;EACA,SAAS;GACP,UAAU;IAAE,MAAM;IAA6B,MAAM;GAAK;GAC1D,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,aAAa;GACpB,OAAO;EACT;EACA,iBAAiB;GACf,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,MAAM,CAAC,kBAAkB;GACzB,SAAS,CAAC,gBAAgB;GAC1B,OAAO;GACP,MAAM;EACR;EACA,gBAAgB;GACd,UAAU;IAAE,MAAM;IAA8D,MAAM;GAAK;GAC3F,MAAM,CAAC,eAAe;GACtB,OAAO;GACP,SAAS,EAAE,QAAQ,CAAC,iBAAiB,EAAE;GACvC,MAAM;EACR;CACF;CACA,aAAa;EACX;GAAE,IAAI;GAAW,MAAM,CAAC,WAAW,KAAK;GAAG,IAAI;GAAa,IAAI;EAAc;EAC9E;GAAE,IAAI;GAAY,MAAM;GAAa,IAAI;GAAc,IAAI;GAAmB,MAAM;EAA0F;EAC9K;GAAE,IAAI;GAAe,MAAM;GAAa,IAAI;GAAa,IAAI;GAAwB,OAAO;EAAiB;EAC7G;GAAE,IAAI;GAAa,MAAM;GAAc,IAAI;GAAW,IAAI;EAAiB;EAC3E;GAAE,IAAI;GAAkB,MAAM,CAAC,cAAc,SAAS;GAAG,IAAI;GAAS,IAAI,CAAC,gBAAgB,uBAAuB;EAAE;EACpH;GAAE,IAAI;GAAS,MAAM;GAAW,IAAI;GAAS,IAAI;EAAkB;EACnE;GAAE,IAAI;GAAc,MAAM;GAAW,IAAI;GAAS,IAAI;EAAiB;EACvE;GAAE,IAAI;GAAQ,MAAM;GAAS,IAAI;GAAS,IAAI;GAAgB,MAAM;EAAwE;EAC5I;GAAE,IAAI;GAAY,MAAM;GAAS,IAAI;GAAS,IAAI;GAAoB,MAAM;EAA6B;EACzG;GAAE,IAAI;GAAS,MAAM;GAAS,IAAI;GAAgB,IAAI;GAAe,MAAM;EAAsF;EACjK;GAAE,IAAI;GAAQ,MAAM;GAAS,IAAI;GAAgB,IAAI;EAAe;EACpE;GAAE,IAAI;GAAa,MAAM;GAAgB,IAAI;GAAa,IAAI;GAAe,OAAO;EAAc;CACpG;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GAAE,YAAY;GAAY,SAAS;GAAe,OAAO;EAAc;EAC/E,MAAM,EAAE,UAAU;GAAE,MAAM;GAA2B,MAAM;EAAI,EAAE;EACjE,MAAM;EACN,MAAM;CACR;AACF,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AM9ID,MAAa,YAAqB,cAAc,MAAMC,iBAAQ;;AAG9D,MAAa,mBAA4B,cAAc,MAAMC,wBAAc;;AAG3E,MAAa,eAAwB,cAAc,MAAMC,oBAAW;;AAGpE,MAAa,iBAA0B,cAAc,MAAMC,sBAAa;;;;;;AAOxE,MAAa,iBAA8D,EACxE,OAAO,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CACvC,MAAMC,sBAAc;;;AC1BvB,MAAMC,OAAK;;;;;;;;;;;;;;;;;;AAmBX,MAAa,cAAuB,cAAc,MAAM;CACtD,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EAAE,SAAS;EAAS,UAAU;EAAkC,SAAS;CAAmD;CACxI,SAAS;EACP;GAAE,KAAK,GAAGA,KAAG;GAA0L,MAAM;EAAc;EAC3N;GAAE,KAAK,GAAGA,KAAG;GAAkF,MAAM;EAAc;EACnH;GAAE,KAAK,GAAGA,KAAG;GAAoJ,MAAM;EAAc;EACrL;GAAE,KAAK,GAAGA,KAAG;GAAoD,MAAM;EAAc;EACrF;GAAE,KAAK,GAAGA,KAAG;GAAqL,MAAM;EAAc;EACtN;GAAE,KAAK,GAAGA,KAAG;GAA4G,MAAM;EAAc;EAC7I;GAAE,KAAK,GAAGA,KAAG;GAA4F,MAAM;EAAc;EAC7H;GAAE,KAAK,GAAGA,KAAG;GAAyH,MAAM;EAAc;EAC1J;GAAE,KAAK,GAAGA,KAAG;GAA8I,MAAM;EAAc;EAC/K;GAAE,KAAK,GAAGA,KAAG;GAA0I,MAAM;EAAc;EAC3K;GAAE,KAAK,GAAGA,KAAG;GAAuI,MAAM;EAAc;EACxK;GAAE,KAAK,GAAGA,KAAG;GAAyK,MAAM;EAAc;EAC1M;GAAE,KAAK,GAAGA,KAAG;GAAoN,MAAM;EAAc;EACrP;GAAE,KAAK,GAAGA,KAAG;GAA8H,MAAM;EAAc;EAC/J;GAAE,KAAK,GAAGA,KAAG;GAAiK,MAAM;EAAc;EAClM;GAAE,KAAK,GAAGA,KAAG;GAAiJ,MAAM;EAAc;EAClL;GAAE,KAAK,GAAGA,KAAG;GAAmF,MAAM;EAAc;EACpH;GAAE,KAAK,GAAGA,KAAG;GAAiK,MAAM;EAAc;EAClM;GAAE,KAAK,GAAGA,KAAG;GAA4H,MAAM;EAAc;EAC7J;GAAE,KAAK,GAAGA,KAAG;GAAsK,MAAM;EAAc;EACvM;GAAE,KAAK,GAAGA,KAAG;GAAsL,MAAM;EAAc;EACvN;GAAE,KAAK,GAAGA,KAAG;GAAyK,MAAM;EAAc;EAC1M;GAAE,KAAK,GAAGA,KAAG;GAAsK,MAAM;EAAc;EACvM;GAAE,KAAK;GAAkN,MAAM;EAAc;EAC7O;GAAE,KAAK,GAAGA,KAAG;GAAgL,MAAM;EAAc;EACjN;GAAE,KAAK,GAAGA,KAAG;GAAsH,MAAM;EAAc;EACvJ;GAAE,KAAK,GAAGA,KAAG;GAAuM,MAAM;EAAc;EACxO;GAAE,KAAK,GAAGA,KAAG;GAAyJ,MAAM;EAAc;EAC1L;GAAE,KAAK;GAA0J,MAAM;EAAc;CACvL;CACA,QAAQ;EACN,SAAS;GAAE,SAAS;GAAM,QAAQ;EAAK;EACvC,WAAW,EAAE,MAAM,+EAA+E;EAClG,WAAW,EAAE,MAAM,qGAAqG;EACxH,WAAW,EAAE,MAAM,8FAA8F;EACjH,SAAS,EAAE,MAAM,wGAAwG;EACzH,OAAO,EAAE,MAAM,gIAAgI;EAC/I,SAAS,EAAE,MAAM,0CAA0C;EAC3D,iBAAiB,EAAE,MAAM,iHAAiH;CAC5I;CACA,QAAQ;EACN,gBAAgB;GAAE,MAAM;GAAM,MAAM;EAA8D;EAClG,gBAAgB;GAAE,MAAM;GAAM,MAAM;EAAuB;EAC3D,wBAAwB;GAAE,MAAM;GAAM,MAAM;EAA4D;EACxG,oBAAoB;GAAE,MAAM;GAAM,MAAM;EAAgD;EACxF,aAAa;GAAE,MAAM;GAAM,MAAM;EAA2F;EAC5H,mBAAmB,EAAE,MAAM,QAAQ;EACnC,0BAA0B;GAAE,MAAM;GAAS,MAAM;EAAqE;EACtH,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAAoC;EAC7E,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAAoE;EAC7G,YAAY;GAAE,MAAM;GAAM,MAAM;EAA0B;EAC1D,eAAe;GAAE,MAAM;GAAM,MAAM;EAAoC;EACvE,mBAAmB;GAAE,MAAM;GAAS,MAAM;EAAqB;EAC/D,iBAAiB,EAAE,MAAM,QAAQ;EACjC,iBAAiB;GAAE,MAAM;GAAS,MAAM;EAA4C;EACpF,kBAAkB,EAAE,MAAM,KAAK;EAC/B,iBAAiB;GAAE,MAAM;GAAO,MAAM;EAAkB;EACxD,wBAAwB,EAAE,MAAM,QAAQ;EACxC,6BAA6B,EAAE,MAAM,QAAQ;EAC7C,eAAe;GAAE,MAAM;GAAO,MAAM;EAAwD;EAC5F,0BAA0B,EAAE,MAAM,QAAQ;EAC1C,wBAAwB,EAAE,MAAM,QAAQ;EACxC,kBAAkB;GAAE,MAAM;GAAM,MAAM;EAAmD;EACzF,oBAAoB;GAAE,MAAM;GAAS,MAAM;EAA+E;EAC1H,uBAAuB;GAAE,MAAM;GAAS,MAAM;EAAyD;EACvG,sBAAsB;GAAE,MAAM;GAAS,MAAM;EAAsD;EACnG,sBAAsB;GAAE,MAAM;GAAM,MAAM;EAA6C;EACvF,sBAAsB;GAAE,MAAM;GAAM,MAAM;EAAuC;EACjF,yBAAyB;GAAE,MAAM;GAAS,MAAM;EAAqD;CACvG;CACA,OAAO;EACL,yBAAyB;GAAE,KAAK;GAAoC,OAAO;GAAe,MAAM;GAAM,SAAS;GAAM,MAAM;EAA4B;EACvJ,sBAAsB;GAAE,KAAK;GAAiC,OAAO;GAAe,MAAM;GAAK,SAAS;GAAI,MAAM;EAA4B;EAC9I,uBAAuB;GAAE,KAAK;GAAkC,OAAO;GAAe,MAAM;GAAM,SAAS;GAAO,MAAM;EAA4B;EACpJ,iBAAiB;GACf,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,sBAAsB;GACpB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,4BAA4B;GAAE,KAAK;GAAuC,OAAO;GAAe,MAAM;GAAM,SAAS;GAAO,MAAM;EAA8B;EAChK,4BAA4B;GAAE,KAAK;GAA8C,OAAO;GAAW,MAAM;GAAK,SAAS;GAAI,MAAM;EAAgC;EACjK,cAAc;GAAE,KAAK;GAAgC,OAAO;GAAW,MAAM;GAAK,SAAS;GAAI,MAAM;EAAgC;EACrI,mBAAmB;GAAE,KAAK;GAAwB,OAAO;GAAS,MAAM;GAAS,SAAS;GAAG,MAAM;EAA4B;EAC/H,kBAAkB;GAAE,KAAK;GAA+B,OAAO;GAAS,MAAM;GAAM,SAAS;GAAO,MAAM;EAAwB;EAClI,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,eAAe;GACb,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,KAAK;GAAE,KAAK;GAAkC,OAAO;GAAQ,MAAM;GAAM,SAAS;EAAK;EACvF,2BAA2B;GAAE,KAAK;GAA6B,OAAO;GAAS,MAAM;GAAM,SAAS;GAAO,MAAM;EAAwB;EACzI,kCAAkC;GAAE,KAAK;GAAoC,OAAO;GAAW,MAAM;GAAK,SAAS;GAAG,MAAM;EAAqC;EACjK,4BAA4B;GAAE,KAAK;GAA8B,OAAO;GAAW,MAAM;GAAK,SAAS;GAAG,MAAM;EAAqC;EACrJ,2CAA2C;GACzC,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,sCAAsC;GAAE,KAAK;GAAwC,OAAO;GAAS,MAAM;GAAK,SAAS;GAAI,MAAM;EAAiC;EACpK,4BAA4B;GAAE,KAAK;GAA8B,OAAO;GAAS,MAAM;GAAM,SAAS;GAAO,MAAM;EAA8B;EACjJ,IAAI;GACF,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,WAAW;GAET,UAAU;IAAE,MAAM;IAA2B,MAAM;GAAK;GACxD,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,MAAM,CAAC,gBAAgB,wBAAwB;GAC/C,OAAO;EACT;EACA,gBAAgB;GAEd,UAAU;IAAE,MAAM;IAA+D,MAAM;GAAK;GAC5F,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,MAAM,CAAC,gBAAgB,wBAAwB;GAC/C,OAAO;GACP,MAAM;EACR;EACA,kBAAkB;GAEhB,UAAU;IAAE,MAAM;IAA+B,MAAM;GAAK;GAC5D,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,MAAM,CAAC,cAAc;GACrB,SAAS,CAAC,cAAc;GACxB,OAAO;GACP,MAAM;EACR;EACA,UAAU;GAER,UAAU;IAAE,MAAM;IAAyB,MAAM;GAAK;GACtD,UAAU;IAAE,MAAM;IAA4D,MAAM;GAAK;GACzF,MAAM;IAAC;IAAmB;IAAwB;GAAkB;GACpE,OAAO;GACP,MAAM;EACR;EACA,UAAU;GAER,UAAU;IAAE,MAAM;IAAyB,MAAM;GAAK;GACtD,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,MAAM,CAAC,iBAAiB,WAAW;GACnC,OAAO;GACP,MAAM;EACR;EACA,cAAc;GACZ,UAAU;IAAE,MAAM;IAAgD,MAAM;GAAK;GAC7E,MAAM,CAAC,iBAAiB,iBAAiB;GACzC,SAAS,CAAC,UAAU;GACpB,OAAO;GACP,MAAM;EACR;EACA,SAAS;GACP,UAAU;IAAE,MAAM;IAAwB,MAAM;GAAK;GACrD,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,MAAM,CAAC,eAAe;GACtB,SAAS,CAAC,iBAAiB;GAC3B,OAAO;GACP,MAAM;EACR;EACA,kBAAkB;GAChB,UAAU;IAAE,MAAM;IAA8B,MAAM;GAAK;GAC3D,MAAM,CAAC,cAAc;GACrB,SAAS,CAAC,iBAAiB;GAC3B,OAAO;GACP,MAAM;EACR;EACA,gBAAgB;GACd,UAAU;IAAE,MAAM;IAA8B,MAAM;GAAI;GAC1D,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,MAAM,CAAC,eAAe;GACtB,SAAS,CAAC,2BAA2B;GACrC,OAAO;GACP,MAAM;EACR;EACA,gBAAgB;GACd,UAAU;IAAE,MAAM;IAAgB,MAAM;GAAI;GAC5C,MAAM,CAAC,eAAe;GACtB,OAAO;GACP,MAAM;EACR;EACA,YAAY;GAEV,UAAU;IAAE,MAAM;IAAuG,MAAM;GAAK;GACpI,OAAO;IAAE,OAAO;IAAe,OAAO,CAAC,IAAI;IAAG,MAAM;GAAI;GACxD,UAAU;IAAE,OAAO;IAAe,OAAO,CAAC,sBAAsB,IAAI;IAAG,MAAM;GAAI;GACjF,MAAM,CAAC,gBAAgB;GACvB,OAAO;GACP,MAAM;EACR;EACA,eAAe;GACb,UAAU;IAAE,OAAO;IAAG,MAAM;GAAK;GACjC,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,MAAM,CAAC,kBAAkB;GACzB,OAAO;GACP,MAAM;EACR;EACA,cAAc;GAEZ,UAAU;IAAE,MAAM;IAA0E,MAAM;GAAK;GACvG,UAAU;IAAE,OAAO;IAAe,OAAO,CAAC,sBAAsB,IAAI;IAAG,MAAM;GAAI;GACjF,MAAM,CAAC,qBAAqB;GAC5B,SAAS,CAAC,gBAAgB;GAC1B,OAAO;GACP,MAAM;EACR;EACA,oBAAoB;GAClB,UAAU;IAAE,MAAM;IAA8D,MAAM;GAAK;GAC3F,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,MAAM,CAAC,oBAAoB;GAC3B,SAAS,CAAC,gBAAgB;GAC1B,OAAO;GACP,MAAM;EACR;EACA,iBAAiB;GACf,UAAU;IAAE,MAAM;IAAwC,MAAM;GAAI;GACpE,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,MAAM,CAAC,oBAAoB;GAC3B,SAAS,CAAC,oBAAoB;GAC9B,OAAO;GACP,MAAM;EACR;CACF;CACA,UAAU;EAER,8CAA8C;GAC5C,UAAU;IAAE,MAAM;IAAyD,MAAM;GAAK;GACtF,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,OAAO;IAAE,MAAM;IAA2B,MAAM;GAAK;GACrD,MAAM;EACR;EACA,sCAAsC,EAAE,OAAO,WAAW;EAE1D,sCAAsC,EAAE,OAAO,WAAW;CAC5D;CACA,aAAa;EACX;GAAE,IAAI;GAAgB,MAAM;GAAW,IAAI;GAAa,IAAI;EAAe;EAC3E;GAAE,IAAI;GAAe,MAAM;GAAa,IAAI;GAAW,IAAI;GAAkB,OAAO;GAAY,OAAO,CAAC,SAAS;GAAG,QAAQ;EAAuD;EACnL;GAAE,IAAI;GAAc,MAAM;GAAa,IAAI;GAAa,IAAI;GAAe,MAAM;GAAgC,QAAQ;EAAoD;EAC7K;GAAE,IAAI;GAAkB,MAAM;GAAW,IAAI;GAAa,IAAI;GAAY,QAAQ;EAAoD;EACtI;GAAE,IAAI;GAAmB,MAAM;GAAW,IAAI;GAAa,IAAI;GAAe,OAAO;GAAgB,OAAO,CAAC,OAAO;GAAG,QAAQ;EAAoD;EACnL;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO,CAAC,SAAS,OAAO;GACxB,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAW,MAAM;GAAa,IAAI;GAAa,IAAI;GAAe,OAAO;GAAgB,OAAO,CAAC,OAAO;EAAE;EAChH;GAAE,IAAI;GAAgB,MAAM;GAAW,IAAI;GAAS,IAAI,CAAC,mBAAmB,eAAe;GAAG,OAAO,CAAC,OAAO;GAAG,QAAQ;EAAkD;EAC1K;GAAE,IAAI;GAAe,MAAM;GAAS,IAAI;GAAW,IAAI;GAAiB,OAAO,CAAC,OAAO;GAAG,QAAQ;EAA6C;EAC/I;GAAE,IAAI;GAAkB,MAAM;IAAC;IAAW;IAAW;GAAO;GAAG,IAAI;GAAa,IAAI;GAAkB,OAAO;GAAY,OAAO,CAAC,OAAO;GAAG,QAAQ;EAAqC;EACxL;GAAE,IAAI;GAAkB,MAAM;IAAC;IAAW;IAAW;GAAO;GAAG,IAAI;GAAa,IAAI;GAAkB,OAAO,CAAC,OAAO;GAAG,QAAQ;EAAqD;EACrL;GAAE,IAAI;GAAgB,MAAM;GAAW,IAAI;GAAiB,IAAI;GAAiB,MAAM;GAAgD,QAAQ;EAAqE;EACpN;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO,CAAC,UAAU,OAAO;GACzB,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAuB,MAAM;GAAiB,IAAI;GAAW,IAAI;GAAwB,OAAO;GAAkB,OAAO;EAAoB;CACrJ;CACA,SAAS,EACP,cAAc;EACZ,UAAU;EACV,MAAM;EACN,QAAQ;GAAE,WAAW;GAAa,SAAS;EAAU;CACvD,EACF;AACF,CAAC;;;AC5UD,MAAMC,OAAK;;;;;;;;;;;;;;AAeX,MAAa,iBAA0B,cAAc,MAAM;CACzD,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EAAE,SAAS;EAAS,IAAI;EAAS,OAAO;CAA6B;CACjF,SAAS;EACP;GAAE,KAAK,GAAGA,KAAG;GAA8J,MAAM;EAAc;EAC/L;GAAE,KAAK,GAAGA,KAAG;GAA+H,MAAM;EAAc;EAChK;GAAE,KAAK,GAAGA,KAAG;GAA8K,MAAM;EAAc;EAC/M;GAAE,KAAK,GAAGA,KAAG;GAAiH,MAAM;EAAc;EAClJ;GAAE,KAAK,GAAGA,KAAG;GAA6G,MAAM;EAAc;EAC9I;GAAE,KAAK,GAAGA,KAAG;GAA8I,MAAM;EAAc;CACjL;CACA,QAAQ;EACN,QAAQ;GAAE,SAAS;GAAM,QAAQ;EAAK;EACtC,WAAW,EAAE,MAAM,oDAAoD;EACvE,MAAM,EAAE,OAAO,KAAK;CACtB;CACA,QAAQ;EACN,QAAQ,EAAE,MAAM,QAAQ;EACxB,YAAY;GAAE,MAAM;GAAQ,MAAM;EAA0C;EAC5E,YAAY,EAAE,MAAM,OAAO;EAC3B,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAwG;EAC/I,YAAY;GAAE,MAAM;GAAM,MAAM;EAAgE;EAChG,kBAAkB;GAAE,MAAM;GAAM,MAAM;EAAgE;CACxG;CACA,OAAO;EACL,oBAAoB;GAAE,KAAK;GAA+B,OAAO;GAAS,MAAM;GAAK,SAAS;GAAM,MAAM;EAAkE;EAC5K,qBAAqB;GAAE,KAAK;GAAgC,OAAO;GAAS,MAAM;GAAK,SAAS;GAAI,MAAM;EAAmE;EAC7K,sBAAsB;GAAE,KAAK;GAAiC,OAAO;GAAS,MAAM;GAAS,SAAS;GAAG,MAAM;EAA4B;EAC3I,eAAe;GAAE,KAAK;GAAoB,OAAO;GAAS,MAAM;GAAK,SAAS;GAAK,MAAM;EAAoB;EAC7G,gBAAgB;GAAE,KAAK;GAAqB,OAAO;GAAS,MAAM;GAAK,SAAS;GAAG,MAAM;EAAoB;EAC7G,IAAI;GAAE,KAAK;GAAa,OAAO;GAAU,MAAM;GAAM,SAAS;GAAM,MAAM;EAA4E;EACtJ,gBAAgB;GAAE,KAAK;GAAwB,OAAO;GAAW,MAAM;GAAM,SAAS;GAAM,MAAM;EAA0G;EAC5M,YAAY;GACV,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ,EACN,aAAa;EACX,UAAU;GAAE,MAAM;GAAkB,MAAM;EAAK;EAC/C,UAAU;GAAE,MAAM;GAAc,MAAM;EAAK;EAC3C,MAAM,CAAC,YAAY,gBAAgB;EACnC,OAAO;EACP,MAAM;CACR,EACF;CACA,UAAU;EACR,2CAA2C;GACzC,UAAU;IAAE,MAAM;IAA0C,MAAM;GAAI;GACtE,UAAU;IAAE,OAAO;IAAe,OAAO,CAAC,iBAAiB,IAAI;IAAG,MAAM;GAAI;GAC5E,OAAO;IAAE,OAAO;IAAe,OAAO,CAAC,IAAI;IAAG,MAAM;GAAI;GACxD,MAAM;EACR;EACA,gDAAgD,EAAE,OAAO,YAAY;CACvE;CACA,aAAa,CACX;EAAE,IAAI;EAAa,MAAM;EAAU,IAAI;EAAa,IAAI;EAAU,QAAQ;CAAgC,GAC1G;EAAE,IAAI;EAAW,MAAM;EAAa,IAAI;EAAQ,IAAI;GAAC;GAAY;GAAY;EAAc;CAAE,CAC/F;CACA,MAAM;EACJ,SAAS;EACT,QAAQ,EAAE,WAAW,cAAc;EACnC,MAAM;GACJ,UAAU;IAAE,MAAM;IAA0C,MAAM;GAAI;GACtE,WAAW;IAAE,MAAM;IAA4C,MAAM;GAAI;GACzE,SAAS;IAAE,MAAM;IAAwB,MAAM;GAAQ;EACzD;EACA,MAAM;EACN,MAAM;CACR;AACF,CAAC;;;AC3FD,MAAMC,OAAK;;;;;;;;;;;;;AAcX,MAAa,eAAwB,cAAc,MAAM;CACvD,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EACV,SAAS;EACT,MAAM;EACN,UAAU;EACV,UAAU;CACZ;CACA,SAAS;EACP;GAAE,KAAK,GAAGA,KAAG;GAAkI,MAAM;EAAc;EACnK;GAAE,KAAK,GAAGA,KAAG;GAAgI,MAAM;EAAc;EACjK;GAAE,KAAK,GAAGA,KAAG;GAA8M,MAAM;EAAc;EAC/O;GAAE,KAAK,GAAGA,KAAG;GAA6M,MAAM;EAAc;EAC9O;GAAE,KAAK,GAAGA,KAAG;GAAuF,MAAM;EAAc;EACxH;GAAE,KAAK,GAAGA,KAAG;GAA4K,MAAM;EAAc;EAC7M;GAAE,KAAK,GAAGA,KAAG;GAAsG,MAAM;EAAc;EACvI;GAAE,KAAK,GAAGA,KAAG;GAA6L,MAAM;EAAc;EAC9N;GAAE,KAAK,GAAGA,KAAG;GAAoH,MAAM;EAAc;EACrJ;GAAE,KAAK,GAAGA,KAAG;GAA6J,MAAM;EAAc;EAC9L;GAAE,KAAK,GAAGA,KAAG;GAA6K,MAAM;EAAc;EAC9M;GAAE,KAAK,GAAGA,KAAG;GAA0L,MAAM;EAAc;EAC3N;GAAE,KAAK,GAAGA,KAAG;GAAwH,MAAM;EAAc;EACzJ;GAAE,KAAK,GAAGA,KAAG;GAAoL,MAAM;EAAc;EACrN;GAAE,KAAK,GAAGA,KAAG;GAA0G,MAAM;EAAc;EAC3I;GAAE,KAAK,GAAGA,KAAG;GAAoJ,MAAM;EAAc;EACrL;GAAE,KAAK,GAAGA,KAAG;GAAuH,MAAM;EAAc;EACxJ;GAAE,KAAK,GAAGA,KAAG;GAA0H,MAAM;EAAc;EAC3J;GAAE,KAAK;GAAmK,MAAM;EAAc;CAChM;CACA,QAAQ;EACN,UAAU;GAAE,SAAS;GAAM,QAAQ;GAAM,MAAM;EAAqD;EACpG,YAAY,EAAE,MAAM,yGAAyG;EAC7H,WAAW,EAAE,MAAM,2GAA2G;EAC9H,WAAW,EAAE,MAAM,uFAAuF;EAC1G,SAAS,EAAE,MAAM,2HAA2H;EAC5I,QAAQ,EAAE,MAAM,2CAA2C;EAC3D,UAAU,EAAE,MAAM,yHAAyH;EAC3I,WAAW,EAAE,MAAM,+FAA+F;EAClH,UAAU,EAAE,MAAM,oGAAoG;EACtH,QAAQ;GAAE,OAAO;GAAM,MAAM;EAAiE;CAChG;CACA,QAAQ;EACN,iBAAiB;GAAE,MAAM;GAAO,MAAM;EAA4D;EAClG,kBAAkB,EAAE,MAAM,QAAQ;EAClC,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAyF;EAChI,YAAY;GAAE,MAAM;GAAM,MAAM;EAA+B;EAC/D,YAAY;GAAE,MAAM;GAAM,MAAM;EAA6B;EAC7D,yBAAyB,EAAE,MAAM,QAAQ;EACzC,2BAA2B,EAAE,MAAM,QAAQ;EAC3C,wBAAwB;GAAE,MAAM;GAAS,MAAM;EAAsG;EACrJ,wBAAwB,EAAE,MAAM,QAAQ;EACxC,eAAe;GAAE,MAAM;GAAS,MAAM;EAAgC;EACtE,2BAA2B;GAAE,MAAM;GAAS,MAAM;EAA4B;EAC9E,0BAA0B;GAAE,MAAM;GAAS,MAAM;EAAwB;EACzE,mBAAmB;GAAE,MAAM;GAAS,MAAM;EAAwE;EAClH,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAAkE;EAC3G,uBAAuB;GAAE,MAAM;GAAS,MAAM;EAAsD;CACtG;CACA,OAAO;EACL,kBAAkB;GAAE,KAAK;GAA4B,OAAO;GAAU,MAAM;GAAM,SAAS;GAAO,KAAK;GAAG,MAAM;EAA8F;EAC9M,sBAAsB;GAAE,KAAK;GAAgC,OAAO;GAAU,MAAM;GAAM,SAAS;GAAO,MAAM;EAA+F;EAC/M,yBAAyB;GAAE,KAAK;GAAmC,OAAO;GAAU,MAAM;GAAM,SAAS;GAAK,MAAM;EAA+B;EACnJ,0BAA0B;GAAE,KAAK;GAAoC,OAAO;GAAU,MAAM;GAAM,SAAS;GAAO,MAAM;EAAiC;EACzJ,iBAAiB;GAAE,KAAK;GAA2B,OAAO;GAAU,MAAM;GAAM,SAAS;GAAG,KAAK;GAAG,MAAM;EAAkD;EAC5J,oBAAoB;GAAE,KAAK;GAA8B,OAAO;GAAU,MAAM;GAAM,SAAS;GAAG,KAAK;GAAG,MAAM;EAAyE;EACzL,eAAe;GAAE,KAAK;GAAyB,OAAO;GAAU,MAAM;GAAM,SAAS;GAAG,MAAM;EAAyE;EACvK,aAAa;GAAE,KAAK;GAAuB,OAAO;GAAU,MAAM;GAAS,SAAS;GAAK,MAAM;EAA+B;EAC9H,aAAa;GAAE,KAAK;GAAuB,OAAO;GAAU,MAAM;GAAS,SAAS;GAAG,MAAM;EAA+B;EAC5H,eAAe;GAAE,KAAK;GAAyB,OAAO;GAAU,MAAM;GAAS,SAAS;GAAG,MAAM;EAA+B;EAChI,uBAAuB;GAAE,KAAK;GAAiC,OAAO;GAAU,MAAM;GAAM,SAAS;GAAQ,MAAM;EAAoE;EACvL,yBAAyB;GAAE,KAAK;GAAyC,OAAO;GAAU,MAAM;GAAK,SAAS;GAAG,MAAM;EAAwF;EAC/M,sBAAsB;GAAE,KAAK;GAAsC,OAAO;GAAU,MAAM;GAAS,SAAS;GAAI,MAAM;EAAoF;EAC1M,aAAa;GAAE,KAAK;GAAuB,OAAO;GAAU,MAAM;GAAM,SAAS;GAAG,MAAM;EAAqC;EAC/H,YAAY;GAAE,KAAK;GAAsB,OAAO;GAAU,MAAM;GAAM,SAAS;GAAG,MAAM;EAAqC;EAC7H,UAAU;GAAE,KAAK;GAAyC,OAAO;GAAU,MAAM;GAAS,SAAS;GAAG,MAAM;EAAyE;EACrL,OAAO;GACL,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,KAAK;GAAE,KAAK;GAAgC,OAAO;GAAQ,MAAM;GAAM,SAAS;EAAK;EACrF,IAAI;GACF,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,gBAAgB;GAGd,UAAU;IAAE,MAAM;IAA2C,MAAM;GAAK;GACxE,OAAO;IAAE,OAAO;IAAG,MAAM;GAAK;GAC9B,UAAU;IAAE,MAAM;IAAa,MAAM;GAAK;GAC1C,MAAM,CAAC,mBAAmB,UAAU;GACpC,SAAS,CAAC,cAAc;GACxB,OAAO;GACP,MAAM;EACR;EACA,iBAAiB;GACf,UAAU;IAAE,MAAM;IAAoB,MAAM;GAAK;GACjD,UAAU;IAAE,MAAM;IAAa,MAAM;GAAK;GAC1C,MAAM,CAAC,kBAAkB;GACzB,SAAS,CAAC,kBAAkB,cAAc;GAC1C,OAAO;GACP,MAAM;EACR;EACA,mBAAmB;GACjB,UAAU;IAAE,MAAM;IAAoB,MAAM;GAAK;GACjD,UAAU;IAAE,MAAM;IAAa,MAAM;GAAK;GAC1C,MAAM,CAAC,iBAAiB;GACxB,SAAS,CAAC,YAAY,cAAc;GACpC,OAAO;GACP,MAAM;EACR;EACA,gBAAgB;GACd,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAK;GAChD,UAAU;IAAE,MAAM;IAAa,MAAM;GAAK;GAC1C,MAAM,CAAC,cAAc;GACrB,SAAS;IAAC;IAAY;IAAgB;GAAiB;GACvD,OAAO;GACP,MAAM;EACR;EACA,cAAc;GACZ,UAAU;IAAE,MAAM;IAAwB,MAAM;GAAK;GACrD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,eAAe;GACtB,OAAO;GACP,MAAM;EACR;EACA,mBAAmB;GACjB,UAAU;IAAE,MAAM;IAA4B,MAAM;GAAK;GACzD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,mBAAmB,gBAAgB;GAC1C,SAAS,CAAC,gBAAgB;GAC1B,OAAO;GACP,MAAM;EACR;EACA,kBAAkB;GAChB,UAAU;IAAE,MAAM;IAAsB,MAAM;GAAK;GACnD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,eAAe;GACtB,SAAS,CAAC,gBAAgB;GAC1B,OAAO;GACP,MAAM;EACR;EACA,WAAW;GACT,UAAU;IAAE,OAAO;IAAG,MAAM;GAAK;GACjC,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM;IAAC;IAAwB;IAAyB;GAAyB;GACjF,OAAO;GACP,MAAM;EACR;CACF;CACA,UAAU;EACR,mCAAmC,EAAE,OAAO,kBAAkB;EAC9D,0CAA0C,EAAE,OAAO,iBAAiB;EACpE,wCAAwC,EAAE,OAAO,eAAe;EAEhE,yCAAyC,EAAE,OAAO,oBAAoB;EACtE,2CAA2C;GACzC,UAAU;IAAE,MAAM;IAAuC,MAAM;GAAI;GACnE,UAAU;IAAE,OAAO;IAAe,OAAO,CAAC,yBAAyB,IAAI;IAAG,MAAM;GAAI;GACpF,OAAO;IAAE,OAAO;IAAe,OAAO,CAAC,IAAI;IAAG,MAAM;GAAI;GACxD,MAAM;EACR;CACF;CACA,aAAa;EACX;GAAE,IAAI;GAAQ,MAAM;GAAU,IAAI;GAAc,IAAI;GAAiB,QAAQ;EAAqB;EAClG;GAAE,IAAI;GAAa,MAAM;GAAc,IAAI;GAAa,IAAI;GAAkB,QAAQ;EAAqB;EAC3G;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,iBAAiB;GACzB,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAkB,MAAM,CAAC,cAAc,WAAW;GAAG,IAAI;GAAW,IAAI;GAAgB,OAAO;GAAqB,QAAQ;EAAqB;EACvJ;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,iBAAiB;GACzB,QAAQ;EACV;EACA;GAAE,IAAI;GAAc,MAAM;GAAa,IAAI;GAAa,IAAI;GAAY,MAAM;GAAsE,QAAQ;EAAqB;EACjL;GAAE,IAAI;GAAW,MAAM;GAAa,IAAI;GAAU,IAAI;EAAW;EACjE;GAAE,IAAI;GAAS,MAAM;GAAa,IAAI;GAAa,IAAI;GAAY,MAAM;GAA4C,QAAQ;EAAqB;EAClJ;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,iBAAiB;GACzB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAS,MAAM;GAAW,IAAI;GAAc,IAAI;GAAe,OAAO;EAAe;EAC3F;GAAE,IAAI;GAAY,MAAM;GAAU,IAAI;GAAU,IAAI;EAAgB;EACpE;GAAE,IAAI;GAAW,MAAM;GAAU,IAAI;GAAU,IAAI;EAAW;EAC9D;GAAE,IAAI;GAAoB,MAAM;GAAU,IAAI;GAAU,IAAI;GAAwB,OAAO;GAAkB,OAAO;EAA2B;EAC/I;GAAE,IAAI;GAAe,MAAM;GAAU,IAAI;GAAY,IAAI;GAAmB,OAAO;GAA6B,MAAM;GAAmD,QAAQ;EAAmD;EACpO;GAAE,IAAI;GAAmB,MAAM;GAAU,IAAI;GAAY,IAAI;GAAgB,OAAO;GAAqB,MAAM;GAAkE,QAAQ;EAAoB;EAC7M;GAAE,IAAI;GAAY,MAAM,CAAC,aAAa,UAAU;GAAG,IAAI;GAAU,IAAI;EAAiB;EACtF;GAAE,IAAI;GAAa,MAAM,CAAC,aAAa,UAAU;GAAG,IAAI;GAAU,IAAI;GAA2B,OAAO;GAAqB,OAAO;GAA6B,QAAQ;EAAsB;CACjM;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GAAE,YAAY;GAAY,WAAW;GAAe,WAAW;GAAe,QAAQ;GAAe,UAAU;EAAc;EACrI,MAAM;GACJ,UAAU;IAAE,MAAM;IAAuC,MAAM;GAAI;GACnE,WAAW;IAAE,MAAM;IAA2B,MAAM;GAAI;GACxD,SAAS;IAAE,MAAM;IAAwB,MAAM;GAAQ;EACzD;EACA,MAAM;EACN,MAAM;CACR;AACF,CAAC;;;ACxQD,MAAM,KAAK;AACX,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BX,MAAa,kBAA2B,cAAc,MAAM;CAC1D,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EACV,UAAU;EACV,QAAQ;EACR,QAAQ;EACR,WAAW;CACb;CACA,SAAS;EACP;GAAE,KAAK,GAAG,GAAG;GAAkL,MAAM;EAAc;EACnN;GAAE,KAAK,GAAG,GAAG;GAA+G,MAAM;EAAc;EAChJ;GAAE,KAAK,GAAG,GAAG;GAAwH,MAAM;EAAc;EACzJ;GAAE,KAAK,GAAG,GAAG;GAAmP,MAAM;EAAc;EACpR;GAAE,KAAK,GAAG,GAAG;GAAiH,MAAM;EAAa;EACjJ;GAAE,KAAK,GAAG,GAAG;GAA4H,MAAM;EAAc;EAC7J;GAAE,KAAK,GAAG,GAAG;GAAwK,MAAM;EAAc;EACzM;GAAE,KAAK,GAAG,GAAG;GAAyI,MAAM;EAAc;EAC1K;GAAE,KAAK,GAAG,GAAG;GAA4J,MAAM;EAAc;EAC7L;GAAE,KAAK,GAAG,GAAG;GAA8K,MAAM;EAAc;EAC/M;GAAE,KAAK,GAAG,GAAG;GAAmI,MAAM;EAAc;EACpK;GAAE,KAAK,GAAG,GAAG;GAA6J,MAAM;EAAc;EAC9L;GAAE,KAAK,GAAG,GAAG;GAAoO,MAAM;EAAc;EACrQ;GAAE,KAAK,GAAG,GAAG;GAAyM,MAAM;EAAc;EAC1O;GAAE,KAAK,GAAG,GAAG;GAA4H,MAAM;EAAc;EAC7J;GAAE,KAAK,GAAG,GAAG;GAAwO,MAAM;EAAc;EACzQ;GAAE,KAAK,GAAG,GAAG;GAAwD,MAAM;EAAc;EACzF;GAAE,KAAK,GAAG,GAAG;GAA8E,MAAM;EAAc;EAC/G;GAAE,KAAK,GAAG,GAAG;GAA+L,MAAM;EAAc;EAChO;GAAE,KAAK,GAAG,GAAG;GAAyK,MAAM;EAAc;EAC1M;GAAE,KAAK,GAAG,GAAG;GAAsF,MAAM;EAAc;EACvH;GAAE,KAAK,GAAG,GAAG;GAAoJ,MAAM;EAAc;EACrL;GAAE,KAAK,GAAG,GAAG;GAA+H,MAAM;EAAc;EAChK;GAAE,KAAK,GAAG,GAAG;GAAsM,MAAM;EAAc;EACvO;GAAE,KAAK,GAAG,GAAG;GAAgG,MAAM;EAAc;EACjI;GAAE,KAAK,GAAG,GAAG;GAAyE,MAAM;EAAc;EAC1G;GAAE,KAAK,GAAG,GAAG;GAAoP,MAAM;EAAc;EACrR;GAAE,KAAK,GAAG,GAAG;GAAwI,MAAM;EAAU;EACrK;GAAE,KAAK,GAAG,GAAG;GAA0J,MAAM;EAAc;EAC3L;GAAE,KAAK,GAAG,GAAG;GAAkI,MAAM;EAAc;EACnK;GAAE,KAAK,GAAG,GAAG;GAA+G,MAAM;EAAc;EAChJ;GAAE,KAAK,GAAG,GAAG;GAA+J,MAAM;EAAc;EAChM;GAAE,KAAK,GAAG,GAAG;GAAwO,MAAM;EAAc;EACzQ;GAAE,KAAK,GAAG,GAAG;GAA2H,MAAM;EAAc;EAC5J;GAAE,KAAK,GAAG,GAAG;GAAkO,MAAM;EAAc;EACnQ;GAAE,KAAK,GAAG,GAAG;GAA4H,MAAM;EAAc;EAC7J;GAAE,KAAK,GAAG,GAAG;GAAsK,MAAM;EAAc;EACvM;GAAE,KAAK,GAAG,GAAG;GAAmG,MAAM;EAAc;EACpI;GAAE,KAAK,GAAG,GAAG;GAAiL,MAAM;EAAc;EAClN;GAAE,KAAK,GAAG,GAAG;GAA6K,MAAM;EAAc;EAC9M;GAAE,KAAK,GAAG,GAAG;GAA2G,MAAM;EAAc;EAC5I;GAAE,KAAK;GAAkH,MAAM;EAAU;EACzI;GAAE,KAAK;GAA8L,MAAM;EAAc;EACzN;GAAE,KAAK;GAAuL,MAAM;EAAc;CACpN;CACA,QAAQ;EACN,UAAU;GAAE,SAAS;GAAM,QAAQ;GAAM,MAAM;EAAsE;EACrH,SAAS,EAAE,MAAM,mHAAmH;EACpI,YAAY,EAAE,MAAM,iHAAiH;EACrI,eAAe,EACb,MAAM,4KACR;EACA,aAAa,EAAE,MAAM,kIAAkI;EACvJ,SAAS,EACP,MAAM,kKACR;EACA,OAAO,EAAE,MAAM,iHAAiH;EAChI,QAAQ,EAAE,MAAM,+EAA+E;EAC/F,UAAU,EAAE,MAAM,8HAA8H;EAChJ,SAAS,EAAE,MAAM,2HAA2H;EAC5I,MAAM,EAAE,MAAM,iGAAiG;EAC/G,UAAU,EAAE,MAAM,kGAAkG;EACpH,YAAY,EAAE,MAAM,8JAA8J;EAClL,OAAO;GACL,OAAO;GACP,MAAM;EACR;CACF;CACA,QAAQ;EACN,cAAc;GAAE,MAAM;GAAO,MAAM;EAAsC;EACzE,iBAAiB;GAAE,MAAM;GAAO,MAAM;EAAqD;EAC3F,aAAa;GAAE,MAAM;GAAO,MAAM;EAAkE;EACpG,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAA+H;EACtK,iBAAiB;GAAE,MAAM;GAAS,MAAM;EAAoF;EAC5H,kBAAkB,EAAE,MAAM,QAAQ;EAClC,kBAAkB;GAAE,MAAM;GAAM,MAAM;EAAuE;EAC7G,mBAAmB;GAAE,MAAM;GAAS,MAAM;EAAiF;EAC3H,iBAAiB;GAAE,MAAM;GAAS,MAAM;EAAmE;EAC3G,YAAY;GAAE,MAAM;GAAM,MAAM;EAA0D;EAC1F,sBAAsB;GAAE,MAAM;GAAM,MAAM;EAA0C;EACpF,qBAAqB;GAAE,MAAM;GAAM,MAAM;EAAkF;EAC3H,YAAY;GAAE,MAAM;GAAQ,MAAM;EAAqF;EACvH,YAAY;GAAE,MAAM;GAAQ,MAAM;EAAqD;EACvF,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAyF;EAChI,kBAAkB;GAAE,MAAM;GAAM,MAAM;EAAmC;EACzE,kBAAkB;GAAE,MAAM;GAAM,MAAM;EAAoC;EAC1E,aAAa;GAAE,MAAM;GAAM,MAAM;EAAyF;EAC1H,gBAAgB;GAAE,MAAM;GAAM,MAAM;EAA4F;EAChI,yBAAyB;GAAE,MAAM;GAAS,MAAM;EAA+C;EAC/F,8BAA8B;GAAE,MAAM;GAAS,MAAM;EAAyE;EAC9H,wBAAwB;GAAE,MAAM;GAAS,MAAM;EAAgF;EAC/H,4BAA4B;GAAE,MAAM;GAAS,MAAM;EAA4F;EAC/I,uBAAuB;GAAE,MAAM;GAAS,MAAM;EAAmE;EACjH,4BAA4B;GAAE,MAAM;GAAS,MAAM;EAA2E;EAC9H,mBAAmB;GAAE,MAAM;GAAS,MAAM;EAAuC;EACjF,sBAAsB;GAAE,MAAM;GAAS,MAAM;EAAsC;EACnF,cAAc;GAAE,MAAM;GAAS,MAAM;EAA+E;EACpH,qBAAqB;GAAE,MAAM;GAAS,MAAM;EAA2C;CACzF;CACA,OAAO;EACL,mBAAmB;GACjB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,mBAAmB;GACjB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,aAAa;GACX,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,aAAa;GACX,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,eAAe;GACb,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,eAAe;GACb,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,iBAAiB;GAAE,KAAK;GAA4B,OAAO;GAAU,MAAM;GAAS,SAAS;GAAI,MAAM;EAAuB;EAC9H,2BAA2B;GACzB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,aAAa;GACX,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,wBAAwB;GACtB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,sBAAsB;GACpB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,eAAe;GACb,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,OAAO;GACL,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,IAAI;GACF,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,iBAAiB;GACf,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAI;GAC9C,UAAU;IAAE,MAAM;IAAoC,MAAM;GAAK;GACjE,MAAM,CAAC,kBAAkB;GACzB,SAAS;IAAC;IAAkB;IAAgB;GAAU;GACtD,OAAO;GACP,MAAM;EACR;EACA,sBAAsB;GACpB,UAAU;IAAE,MAAM;IAAkD,MAAM;GAAK;GAC/E,UAAU;IAAE,MAAM;IAA8E,MAAM;GAAK;GAC3G,MAAM,CAAC,mBAAmB;GAC1B,SAAS;IAAC;IAAkB;IAAgB;IAAY;GAAU;GAClE,OAAO;GACP,MAAM;EACR;EACA,gBAAgB;GACd,UAAU;IAAE,MAAM;IAAiB,MAAM;GAAI;GAC7C,UAAU;IAAE,MAAM;IAAmC,MAAM;GAAK;GAChE,MAAM,CAAC,iBAAiB,gBAAgB;GACxC,SAAS;IAAC;IAAmB;IAAsB;IAAqB;IAAgB;IAAY;GAAU;GAC9G,OAAO;GACP,MAAM;EACR;EACA,oBAAoB;GAClB,UAAU;IAAE,MAAM;IAAqB,MAAM;GAAK;GAClD,UAAU;IAAE,MAAM;IAAiD,MAAM;GAAK;GAC9E,MAAM;IAAC;IAAe;IAAkB;GAAe;GACvD,SAAS;IAAC;IAAiB;IAAY;IAAgB;IAAY;GAAU;GAC7E,OAAO;GACP,MAAM;EACR;EACA,eAAe;GACb,UAAU;IAAE,MAAM;IAAgB,MAAM;GAAI;GAC5C,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,gBAAgB;GACvB,SAAS;IAAC;IAAsB;IAAqB;IAAgB;IAAY;GAAU;GAC3F,OAAO;GACP,MAAM;EACR;EACA,oBAAoB;GAClB,UAAU;IAAE,MAAM;IAAqB,MAAM;GAAK;GAClD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,eAAe;GACtB,SAAS,CAAC,eAAe;GACzB,OAAO;GACP,MAAM;EACR;EACA,WAAW;GACT,UAAU;IAAE,MAAM;IAAiB,MAAM;GAAK;GAC9C,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,OAAO;IAAE,MAAM;IAAqB,MAAM;GAAK;GAC/C,MAAM;IAAC;IAAiB;IAAY;GAAiB;GACrD,OAAO;GACP,MAAM;EACR;EACA,cAAc;GACZ,UAAU;IAAE,MAAM;IAAe,MAAM;GAAK;GAC5C,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,OAAO;IAAE,MAAM;IAAwC,MAAM;GAAK;GAClE,MAAM,CAAC,eAAe;GACtB,OAAO;GACP,MAAM;EACR;EACA,aAAa;GACX,UAAU;IAAE,OAAO;IAAM,MAAM;GAAK;GACpC,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,mBAAmB;GAC1B,OAAO;GACP,MAAM;EACR;EACA,cAAc;GACZ,UAAU;IAAE,MAAM;IAAiB,MAAM;GAAK;GAC9C,UAAU;IAAE,MAAM;IAAwB,MAAM;GAAK;GACrD,MAAM,CAAC,cAAc;GACrB,SAAS;IAAC;IAAc;IAAmB;GAAoB;GAC/D,OAAO;GACP,MAAM;EACR;CACF;CACA,UAAU;EACR,mCAAmC,EAAE,OAAO,kBAAkB;EAC9D,sCAAsC,EAAE,OAAO,eAAe;EAC9D,qCAAqC,EAAE,OAAO,iBAAiB;EAC/D,wCAAwC,EAAE,OAAO,eAAe;EAChE,2CAA2C;GACzC,UAAU;IAAE,MAAM;IAAiB,MAAM;GAAK;GAC9C,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,OAAO;IAAE,MAAM;IAAqB,MAAM;GAAK;GAC/C,MAAM;EACR;CACF;CACA,aAAa;EACX;GAAE,IAAI;GAAa,MAAM;GAAU,IAAI;GAAc,IAAI;GAAgB,OAAO;GAAmB,QAAQ;EAAiD;EAC5J;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAc,MAAM;GAAW,IAAI;GAAQ,IAAI;GAAiB,OAAO;GAAgE,QAAQ;EAA0B;EAC/K;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,gBAAgB;GACxB,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAAY;IAAgB;GAAuB;GACxD,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAY,MAAM;GAAe,IAAI;GAAW,IAAI;GAAkB,OAAO;GAAkB,QAAQ;EAA+C;EAC5J;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAAgB;IAAY;GAAU;GAC3C,OAAO;GACP,QAAQ;EACV;EACA;GAAE,IAAI;GAAc,MAAM;GAAW,IAAI;GAAS,IAAI;GAAmB,OAAO;GAAsB,QAAQ;EAA8D;EAC5K;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAAgB;IAAY;IAAY;IAAqB;GAAsB;GACxF,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAc,MAAM;GAAS,IAAI;GAAU,IAAI;GAAiB,OAAO;GAAa,QAAQ;EAAiD;EACnJ;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAA4B;IAAgB;IAAY;GAAU;GACvE,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,gBAAgB;GACxB,QAAQ;EACV;EACA;GAAE,IAAI;GAAc,MAAM;GAAY,IAAI;GAAQ,IAAI;GAAY,QAAQ;EAAuD;EACjI;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAA4B;IAAgB;IAAY;GAAU;GACvE,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,gBAAgB;GACxB,QAAQ;EACV;EACA;GAAE,IAAI;GAAY,MAAM;GAAW,IAAI;GAAU,IAAI;GAAY,OAAO;GAAa,QAAQ;EAA0B;EACvH;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAA4B;IAAgB;IAAY;GAAU;GACvE,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,QAAQ;EACV;EACA;GAAE,IAAI;GAAc,MAAM;GAAY,IAAI;GAAQ,IAAI;GAAsB,QAAQ;EAAmC;EACvH;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAAgB;IAAY;IAAY;GAAsB;GACnE,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,WAAW;GACnB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI,CAAC,qBAAqB,oBAAoB;GAC9C,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAAgB;IAAY;IAAY;GAAsB;GACnE,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,cAAc;GACtB,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,cAAc;GACtB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,cAAc;GACtB,MAAM;GACN,QAAQ;EACV;CACF;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GACN,YAAY;GACZ,aAAa;GACb,SAAS;GACT,OAAO;GACP,QAAQ;GACR,UAAU;GACV,SAAS;GACT,MAAM;GACN,UAAU;GACV,YAAY;EACd;EACA,MAAM,EACJ,UAAU;GAAE,MAAM;GAAkB,MAAM;EAAI,EAChD;EACA,MAAM;EACN,MAAM;CACR;AACF,CAAC;;;AC9rBD,MAAMC,OAAK;AACX,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;AAuBb,MAAa,gBAAyB,cAAc,MAAM;CACxD,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EACV,IAAI;EACJ,WAAW;EACX,eAAe;EACf,MAAM;EACN,QAAQ;EACR,WAAW;CACb;CACA,SAAS;EACP;GAAE,KAAK,GAAG,KAAK;GAAqJ,MAAM;EAAc;EACxL;GAAE,KAAK,GAAGA,KAAG;GAA6H,MAAM;EAAc;EAC9J;GAAE,KAAK,GAAGA,KAAG;GAAqI,MAAM;EAAc;EACtK;GAAE,KAAK,GAAGA,KAAG;GAAyI,MAAM;EAAa;EACzK;GAAE,KAAK,GAAGA,KAAG;GAAoK,MAAM;EAAc;EACrM;GAAE,KAAK,GAAGA,KAAG;GAA4J,MAAM;EAAc;EAC7L;GAAE,KAAK,GAAGA,KAAG;GAAwG,MAAM;EAAc;EACzI;GAAE,KAAK,GAAGA,KAAG;GAAyM,MAAM;EAAc;EAC1O;GAAE,KAAK,GAAGA,KAAG;GAA0J,MAAM;EAAc;EAC3L;GAAE,KAAK,GAAGA,KAAG;GAA2L,MAAM;EAAc;EAC5N;GAAE,KAAK,GAAGA,KAAG;GAAiM,MAAM;EAAc;EAClO;GAAE,KAAK,GAAGA,KAAG;GAAyH,MAAM;EAAc;EAC1J;GAAE,KAAK,GAAGA,KAAG;GAA+J,MAAM;EAAc;EAChM;GAAE,KAAK,GAAGA,KAAG;GAA4G,MAAM;EAAc;EAC7I;GAAE,KAAK,GAAGA,KAAG;GAAgH,MAAM;EAAc;EACjJ;GAAE,KAAK,GAAGA,KAAG;GAAiJ,MAAM;EAAc;EAClL;GAAE,KAAK,GAAGA,KAAG;GAAsI,MAAM;EAAc;EACvK;GAAE,KAAK,GAAGA,KAAG;GAA+I,MAAM;EAAc;EAChL;GAAE,KAAK,GAAGA,KAAG;GAAqJ,MAAM;EAAc;EACtL;GAAE,KAAK,GAAG,KAAK;GAAuK,MAAM;EAAc;EAC1M;GAAE,KAAK,GAAG,KAAK;GAAkL,MAAM;EAAc;EACrN;GAAE,KAAK,GAAG,KAAK;GAA2I,MAAM;EAAc;EAC9K;GAAE,KAAK,GAAG,KAAK;GAAsK,MAAM;EAAc;EACzM;GAAE,KAAK,GAAG,KAAK;GAA4G,MAAM;EAAc;EAC/I;GAAE,KAAK,GAAG,KAAK;GAA4J,MAAM;EAAc;EAC/L;GAAE,KAAK,GAAG,KAAK;GAA2K,MAAM;EAAc;EAC9M;GAAE,KAAK,GAAG,KAAK;GAAqG,MAAM;EAAa;EACvI;GAAE,KAAK;GAA2M,MAAM;EAAU;EAClO;GAAE,KAAK;GAAiR,MAAM;EAAc;EAC5S;GAAE,KAAK;GAA6J,MAAM;EAAc;EACxL;GAAE,KAAK;GAAsN,MAAM;EAAc;EACjP;GAAE,KAAK;GAA8E,MAAM;EAAc;EACzG;GAAE,KAAK;GAAwH,MAAM;EAAc;CACrJ;CACA,QAAQ;EACN,UAAU;GAAE,SAAS;GAAM,QAAQ;GAAM,MAAM;EAAkE;EACjH,SAAS,EACP,MAAM,0IACR;EACA,YAAY,EAAE,MAAM,2GAA2G;EAC/H,SAAS,EAAE,MAAM,0GAA0G;EAC3H,MAAM,EACJ,MAAM,+IACR;EACA,UAAU,EAAE,MAAM,0GAA0G;EAC5H,UAAU,EACR,MAAM,+LACR;EACA,QAAQ,EAAE,MAAM,yFAAyF;EACzG,OAAO;GACL,OAAO;GACP,MAAM;EACR;CACF;CACA,QAAQ;EACN,gBAAgB;GAAE,MAAM;GAAO,MAAM;EAAqE;EAC1G,aAAa;GAAE,MAAM;GAAO,MAAM;EAAoE;EACtG,eAAe;GAAE,MAAM;GAAO,MAAM;EAAwG;EAC5I,qBAAqB;GAAE,MAAM;GAAO,MAAM;EAA4H;EACtK,iBAAiB;GAAE,MAAM;GAAS,MAAM;EAA4F;EACpI,cAAc;GAAE,MAAM;GAAS,MAAM;EAA4G;EACjJ,kBAAkB,EAAE,MAAM,QAAQ;EAClC,mBAAmB;GAAE,MAAM;GAAS,MAAM;EAAwG;EAClJ,sBAAsB;GAAE,MAAM;GAAM,MAAM;EAAsC;EAChF,qBAAqB;GAAE,MAAM;GAAM,MAAM;EAAgG;EACzI,YAAY;GAAE,MAAM;GAAQ,MAAM;EAAoH;EACtJ,YAAY;GAAE,MAAM;GAAQ,MAAM;EAA8D;EAChG,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAuF;EAC9H,gBAAgB;GAAE,MAAM;GAAM,MAAM;EAA0F;EAC9H,yBAAyB;GAAE,MAAM;GAAS,MAAM;EAAkF;EAClI,0BAA0B;GAAE,MAAM;GAAS,MAAM;EAAgE;EACjH,cAAc;GAAE,MAAM;GAAS,MAAM;EAAmC;EACxE,uBAAuB;GAAE,MAAM;GAAS,MAAM;EAA2D;EACzG,sBAAsB;GAAE,MAAM;GAAS,MAAM;EAAoC;CACnF;CACA,OAAO;EACL,yBAAyB;GACvB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,mBAAmB;GACjB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,eAAe;GACb,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,KAAK;GAAE,KAAK;GAAe,OAAO;GAAU,MAAM;GAAS,SAAS;GAAI,MAAM;EAAsB;EACpG,KAAK;GACH,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,SAAS;GAAE,KAAK;GAAmB,OAAO;GAAU,MAAM;GAAS,SAAS;GAAM,MAAM;EAA+D;EACvJ,iBAAiB;GACf,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,WAAW;GACT,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,6BAA6B;GAC3B,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,yBAAyB;GACvB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,sBAAsB;GACpB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,mBAAmB;GACjB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,qCAAqC;GACnC,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,OAAO;GACL,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,IAAI;GACF,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,iBAAiB;GACf,UAAU;IAAE,MAAM;IAA2B,MAAM;GAAK;GACxD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GAGtC,MAAM,CAAC,oBAAoB,eAAe;GAC1C,SAAS;IAAC;IAAmB;IAAgB;IAAY;IAAY;GAAmB;GACxF,OAAO;GAGP,MAAM;EACR;EACA,kBAAkB;GAChB,UAAU;IAAE,MAAM;IAA2B,MAAM;GAAK;GACxD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,eAAe;GACtB,SAAS,CAAC,iBAAiB,iBAAiB;GAC5C,OAAO;GACP,MAAM;EACR;EACA,cAAc;GACZ,UAAU;IAAE,MAAM;IAAqB,MAAM;GAAK;GAClD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,cAAc;GACrB,SAAS;IAAC;IAAgB;IAAgB;IAAY;IAAY;IAAqB;GAAoB;GAC3G,OAAO;GACP,MAAM;EACR;EACA,eAAe;GACb,UAAU;IAAE,MAAM;IAAiB,MAAM;GAAK;GAC9C,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,aAAa,gBAAgB;GACpC,SAAS;IAAC;IAAsB;IAAqB;IAAgB;IAAY;GAAU;GAC3F,OAAO;GACP,MAAM;EACR;EACA,cAAc;GACZ,UAAU;IAAE,MAAM;IAAsB,MAAM;GAAI;GAClD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,iBAAiB;GACxB,SAAS;IAAC;IAAgB;IAAY;GAAU;GAChD,OAAO;GACP,MAAM;EACR;CACF;CACA,UAAU;EACR,mCAAmC,EAAE,OAAO,kBAAkB;EAC9D,sCAAsC,EAAE,OAAO,eAAe;EAC9D,qCAAqC,EAAE,OAAO,gBAAgB;EAC9D,2CAA2C;GACzC,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAI;GAC9C,UAAU;IAAE,OAAO;IAAe,OAAO,CAAC,kBAAkB,IAAI;IAAG,MAAM;GAAI;GAC7E,OAAO;IAAE,OAAO;IAAe,OAAO,CAAC,IAAI;IAAG,MAAM;GAAI;GACxD,MAAM;EACR;CACF;CACA,aAAa;EACX;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAc,MAAM;GAAW,IAAI;GAAQ,IAAI;GAAiB,QAAQ;EAAqC;EACnH;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM,CAAC,cAAc,SAAS;GAC9B,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM,CAAC,cAAc,SAAS;GAC9B,IAAI;GACJ,IAAI;IAAC;IAAgB;IAAY;IAAY;GAAmB;GAChE,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI,CAAC,sBAAsB,mBAAmB;GAC9C,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAAgB;IAAY;GAAU;GAC3C,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI,CAAC,gBAAgB,UAAU;GAC/B,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAAgB;IAAY;IAAY;GAAmB;GAChE,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,cAAc;GACtB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,cAAc;GACtB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI,CAAC,gBAAgB,UAAU;GAC/B,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;CACF;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GACN,YAAY;GACZ,SAAS;GACT,MAAM;GACN,UAAU;GACV,UAAU;GACV,QAAQ;EACV;EACA,MAAM;GACJ,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAI;GAC9C,WAAW;IAAE,MAAM;IAA2B,MAAM;GAAI;GACxD,SAAS;IAAE,MAAM;IAAwB,MAAM;GAAQ;EACzD;EACA,MAAM;EACN,MAAM;CACR;AACF,CAAC;;;ACnjBD,MAAa,KAAK;;AAGlB,MAAa,YAAgC;CAC3C;EAAE,KAAK,GAAG,GAAG;EAA0Y,MAAM;CAAc;CAC3a;EAAE,KAAK,GAAG,GAAG;EAA+L,MAAM;CAAc;CAChO;EAAE,KAAK,GAAG,GAAG;EAA8H,MAAM;CAAc;CAC/J;EAAE,KAAK,GAAG,GAAG;EAAuJ,MAAM;CAAc;CACxL;EAAE,KAAK,GAAG,GAAG;EAAwH,MAAM;CAAc;CACzJ;EAAE,KAAK,GAAG,GAAG;EAAkL,MAAM;CAAc;CACnN;EAAE,KAAK,GAAG,GAAG;EAAoO,MAAM;CAAc;CACrQ;EAAE,KAAK,GAAG,GAAG;EAAwG,MAAM;CAAc;CACzI;EAAE,KAAK,GAAG,GAAG;EAAyM,MAAM;CAAc;AAC5O;;;;;;;;;;;;;;;AAgBA,MAAa,mBAA4B,cAAc,MAAM;CAC3D,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EACV,WAAW;EACX,WAAW;EACX,QAAQ;EACR,QAAQ;CACV;CACA,SAAS;EACP,GAAG;EACH;GAAE,KAAK,GAAG,GAAG;GAA4I,MAAM;EAAc;EAC7K;GAAE,KAAK,GAAG,GAAG;GAA4G,MAAM;EAAc;EAC7I;GAAE,KAAK,GAAG,GAAG;GAA2I,MAAM;EAAc;EAC5K;GAAE,KAAK,GAAG,GAAG;GAAoN,MAAM;EAAc;EACrP;GAAE,KAAK,GAAG,GAAG;GAAoJ,MAAM;EAAc;EACrL;GAAE,KAAK,GAAG,GAAG;GAA0G,MAAM;EAAc;EAC3I;GAAE,KAAK,GAAG,GAAG;GAAsG,MAAM;EAAc;EACvI;GAAE,KAAK,GAAG,GAAG;GAAwG,MAAM;EAAc;EACzI;GAAE,KAAK,GAAG,GAAG;GAA4H,MAAM;EAAc;EAC7J;GAAE,KAAK,GAAG,GAAG;GAAgM,MAAM;EAAc;EACjO;GAAE,KAAK,GAAG,GAAG;GAAiH,MAAM;EAAc;EAClJ;GAAE,KAAK,GAAG,GAAG;GAA8M,MAAM;EAAc;EAC/O;GAAE,KAAK,GAAG,GAAG;GAAuK,MAAM;EAAc;EACxM;GAAE,KAAK,GAAG,GAAG;GAAgI,MAAM;EAAc;EACjK;GAAE,KAAK,GAAG,GAAG;GAA0O,MAAM;EAAc;EAC3Q;GAAE,KAAK,GAAG,GAAG;GAAyJ,MAAM;EAAc;EAC1L;GAAE,KAAK,GAAG,GAAG;GAAsL,MAAM;EAAc;EACvN;GAAE,KAAK,GAAG,GAAG;GAAsI,MAAM;EAAc;EACvK;GAAE,KAAK,GAAG,GAAG;GAA+G,MAAM;EAAc;EAChJ;GAAE,KAAK,GAAG,GAAG;GAA6K,MAAM;EAAc;CAChN;CACA,QAAQ;EACN,UAAU;GAAE,SAAS;GAAM,QAAQ;GAAM,MAAM;EAA0C;EACzF,OAAO,EAAE,MAAM,kFAAkF;EACjG,SAAS,EACP,MAAM,kLACR;EACA,MAAM,EAAE,MAAM,kHAAkH;EAChI,SAAS,EAAE,MAAM,kHAAkH;EACnI,QAAQ,EAAE,MAAM,wGAAwG;EACxH,OAAO;GAAE,OAAO;GAAM,MAAM;EAA2F;CACzH;CACA,QAAQ;EACN,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAuC;EAC9E,mBAAmB;GAAE,MAAM;GAAS,MAAM;EAAwC;EAClF,iBAAiB;GAAE,MAAM;GAAS,MAAM;EAAyE;EACjH,YAAY;GAAE,MAAM;GAAM,MAAM;EAA4C;EAC5E,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAA6C;EACtF,2BAA2B;GAAE,MAAM;GAAM,MAAM;EAAqF;EACpI,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAAyH;EAClK,kBAAkB;GAAE,MAAM;GAAQ,MAAM;EAAqF;EAC7H,sBAAsB;GAAE,MAAM;GAAQ,MAAM;EAAuD;EACnG,YAAY;GAAE,MAAM;GAAQ,MAAM;EAAsE;EACxG,YAAY;GAAE,MAAM;GAAQ,MAAM;EAA0C;EAC5E,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAoD;EAC3F,gBAAgB;GAAE,MAAM;GAAM,MAAM;EAAsC;EAC1E,cAAc;GAAE,MAAM;GAAO,MAAM;EAAkE;EACrG,YAAY;GAAE,MAAM;GAAM,MAAM;EAAwF;EACxH,eAAe;GAAE,MAAM;GAAS,MAAM;EAAwE;EAC9G,oBAAoB;GAAE,MAAM;GAAS,MAAM;EAAqE;EAChH,cAAc;GAAE,MAAM;GAAS,MAAM;EAA6E;EAClH,eAAe;GAAE,MAAM;GAAS,MAAM;EAAiE;EACvG,0BAA0B;GAAE,MAAM;GAAS,MAAM;EAA0G;EAC3J,qBAAqB;GAAE,MAAM;GAAS,MAAM;EAA6E;CAC3H;CACA,OAAO;EACL,sBAAsB;GAAE,KAAK;GAAkC,OAAO;GAAS,MAAM;GAAK,SAAS;GAAI,KAAK;GAAG,MAAM;EAAiB;EACtI,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,qBAAqB;GAAE,KAAK;GAAiC,OAAO;GAAS,MAAM;GAAK,SAAS;GAAG,KAAK;GAAG,MAAM;EAAiB;EACnI,eAAe;GAAE,KAAK;GAA2B,OAAO;GAAS,MAAM;GAAK,SAAS;GAAG,KAAK;GAAG,MAAM;EAAiB;EACvH,0BAA0B;GAAE,KAAK;GAAsC,OAAO;GAAS,MAAM;GAAK,SAAS;GAAG,KAAK;GAAG,MAAM;EAAiB;EAC7I,qBAAqB;GAAE,KAAK;GAAiC,OAAO;GAAS,MAAM;GAAK,SAAS;GAAG,KAAK;GAAG,MAAM;EAAiB;EACnI,SAAS;GACP,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,OAAO;GACL,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,sBAAsB;GACpB,UAAU;IAAE,MAAM;IAAwB,MAAM;GAAI;GACpD,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAK;GAChD,MAAM,CAAC,eAAe,eAAe;GACrC,SAAS,CAAC,mBAAmB,eAAe;GAC5C,OAAO;GACP,MAAM;EACR;EACA,oBAAoB;GAClB,UAAU;IAAE,MAAM;IAAsB,MAAM;GAAI;GAClD,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAK;GAChD,MAAM,CAAC,eAAe;GACtB,SAAS,CAAC,gBAAgB;GAC1B,OAAO;GACP,MAAM;EACR;EACA,qBAAqB;GACnB,UAAU;IAAE,MAAM;IAAuB,MAAM;GAAI;GACnD,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAK;GAChD,MAAM,CAAC,YAAY;GACnB,SAAS,CAAC,UAAU;GACpB,OAAO;GACP,MAAM;EACR;EACA,eAAe;GACb,UAAU;IAAE,MAAM;IAAiB,MAAM;GAAI;GAC7C,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAK;GAChD,MAAM,CAAC,iBAAiB,cAAc;GACtC,SAAS,CAAC,kBAAkB,yBAAyB;GACrD,OAAO;GACP,MAAM;EACR;EACA,0BAA0B;GACxB,UAAU;IAAE,MAAM;IAA4B,MAAM;GAAI;GACxD,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAK;GAChD,MAAM,CAAC,yBAAyB;GAChC,SAAS,CAAC,YAAY,gBAAgB;GACtC,OAAO;GACP,MAAM;EACR;EACA,qBAAqB;GACnB,UAAU;IAAE,MAAM;IAAuB,MAAM;GAAI;GACnD,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAK;GAChD,MAAM,CAAC,cAAc;GACrB,SAAS,CAAC,gBAAgB;GAC1B,OAAO;GACP,MAAM;EACR;CACF;CACA,UAAU;EACR,uCAAuC,EAAE,OAAO,sBAAsB;EACtE,qCAAqC,EAAE,OAAO,gBAAgB;CAChE;CACA,aAAa;EACX;GAAE,IAAI;GAAc,MAAM;GAAU,IAAI;GAAS,IAAI;GAAgB,OAAO;GAAwB,QAAQ;EAAqB;EACjI;GAAE,IAAI;GAAiB,MAAM;GAAS,IAAI;GAAQ,IAAI;GAAmB,OAAO;GAA2E,QAAQ;EAA0B;EAC7L;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAe,MAAM;GAAW,IAAI;GAAQ,IAAI;GAAiB,QAAQ;EAA0B;EACzG;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAgB,MAAM;GAAU,IAAI;GAAQ,IAAI;GAAkB,OAAO;GAAuB,QAAQ;EAAgD;EAC9J;GAAE,IAAI;GAAsB,MAAM;GAAU,IAAI;GAAU,IAAI;GAA2B,OAAO;GAA4B,QAAQ;EAAuB;EAC3J;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;IAAC;IAAS;IAAQ;GAAQ;GAChC,IAAI;GACJ,IAAI;IAAC;IAAY;IAAY;IAAgB;GAAc;GAC3D,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;IAAC;IAAS;IAAW;IAAQ;IAAW;GAAQ;GACtD,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;CACF;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GAAE,OAAO;GAAe,SAAS;GAAe,MAAM;GAAe,SAAS;GAAe,QAAQ;EAAc;EAC3H,MAAM,CAAC;EACP,MAAM;EACN,MAAM;CACR;AACF,CAAC;;;;;;;;;;;;;;;;;;;;AClWD,MAAa,mBAA4B,cAAc,MAAM;CAC3D,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EACV,WAAW;EACX,WAAW;EACX,QAAQ;CACV;CACA,SAAS;EACP,GAAG;EACH;GAAE,KAAK,GAAG,GAAG;GAAwL,MAAM;EAAc;EACzN;GAAE,KAAK,GAAG,GAAG;GAAmJ,MAAM;EAAc;EACpL;GAAE,KAAK,GAAG,GAAG;GAA8G,MAAM;EAAc;EAC/I;GAAE,KAAK,GAAG,GAAG;GAAyO,MAAM;EAAc;EAC1Q;GAAE,KAAK,GAAG,GAAG;GAA+I,MAAM;EAAc;EAChL;GACE,KAAK;GACL,MAAM;EACR;EACA;GAAE,KAAK,GAAG,GAAG;GAA+I,MAAM;EAAc;EAChL;GAAE,KAAK,GAAG,GAAG;GAAqI,MAAM;EAAc;EACtK;GAAE,KAAK,GAAG,GAAG;GAAoG,MAAM;EAAc;EACrI;GAAE,KAAK,GAAG,GAAG;GAA+H,MAAM;EAAc;EAChK;GAAE,KAAK,GAAG,GAAG;GAAiN,MAAM;EAAc;EAClP;GAAE,KAAK,GAAG,GAAG;GAAyQ,MAAM;EAAc;EAC1S;GAAE,KAAK,GAAG,GAAG;GAA2E,MAAM;EAAc;EAC5G;GAAE,KAAK,GAAG,GAAG;GAA2I,MAAM;EAAc;EAC5K;GAAE,KAAK,GAAG,GAAG;GAAwI,MAAM;EAAc;EACzK;GAAE,KAAK,GAAG,GAAG;GAAgJ,MAAM;EAAc;EACjL;GAAE,KAAK,GAAG,GAAG;GAA+E,MAAM;EAAc;EAChH;GAAE,KAAK,GAAG,GAAG;GAA0M,MAAM;EAAc;CAC7O;CACA,QAAQ;EACN,UAAU;GAAE,SAAS;GAAM,QAAQ;GAAM,MAAM;EAAgF;EAC/H,YAAY,EAAE,MAAM,wDAAwD;EAC5E,OAAO,EAAE,MAAM,+GAA+G;EAC9H,MAAM,EAAE,MAAM,wGAAwG;EACtH,MAAM,EAAE,MAAM,+FAA+F;EAC7G,QAAQ,EAAE,MAAM,+EAA+E;EAC/F,QAAQ,EAAE,MAAM,8DAA8D;EAC9E,SAAS,EAAE,MAAM,0GAA0G;EAC3H,OAAO;GAAE,OAAO;GAAM,MAAM;EAA2G;CACzI;CACA,QAAQ;EACN,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAA6C;EACpF,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAAuB;EAChE,qBAAqB;GAAE,MAAM;GAAM,MAAM;EAA8C;EACvF,sBAAsB;GAAE,MAAM;GAAM,MAAM;EAAgC;EAC1E,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAA2B;EACpE,eAAe;GAAE,MAAM;GAAS,MAAM;EAAgD;EACtF,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAAwF;EACjI,eAAe;GAAE,MAAM;GAAQ,MAAM;EAAoC;EACzE,oBAAoB;GAAE,MAAM;GAAS,MAAM;EAAsF;EACjI,YAAY;GAAE,MAAM;GAAQ,MAAM;EAAsE;EACxG,YAAY;GAAE,MAAM;GAAQ,MAAM;EAA0C;EAC5E,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAoD;EAC3F,eAAe;GAAE,MAAM;GAAO,MAAM;EAAmC;EACvE,mBAAmB;GAAE,MAAM;GAAO,MAAM;EAAqE;EAC7G,YAAY;GAAE,MAAM;GAAM,MAAM;EAAmD;EACnF,gBAAgB;GAAE,MAAM;GAAM,MAAM;EAAsD;EAC1F,yBAAyB;GAAE,MAAM;GAAS,MAAM;EAAiD;EACjG,uBAAuB;GAAE,MAAM;GAAS,MAAM;EAA0E;EACxH,qBAAqB;GAAE,MAAM;GAAS,MAAM;EAA0E;EACtH,cAAc;GAAE,MAAM;GAAS,MAAM;EAAkF;EACvH,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAAoE;EAC7G,qBAAqB;GAAE,MAAM;GAAS,MAAM;EAAiF;CAC/H;CACA,OAAO;EACL,wBAAwB;GACtB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,oBAAoB;GAAE,KAAK;GAAgC,OAAO;GAAS,MAAM;GAAK,SAAS;GAAI,MAAM;EAAiB;EAC1H,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,iBAAiB;GAAE,KAAK;GAA6B,OAAO;GAAS,MAAM;GAAK,SAAS;GAAM,MAAM;EAA2E;EAChL,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,SAAS;GAAE,KAAK;GAA0C,OAAO;GAAW,MAAM;GAAM,SAAS;GAAS,MAAM;EAAiE;EACjL,OAAO;GACL,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,iBAAiB;GACf,UAAU;IAAE,MAAM;IAA0B,MAAM;GAAI;GACtD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,OAAO;IAAE,MAAM;IAAS,MAAM;GAAK;GACnC,MAAM,CAAC,kBAAkB;GACzB,SAAS;IAAC;IAAkB;IAAgB;GAAU;GACtD,OAAO;GACP,MAAM;EACR;EACA,eAAe;GACb,UAAU;IAAE,MAAM;IAA0B,MAAM;GAAI;GACtD,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAK;GAChD,MAAM,CAAC,aAAa;GACpB,SAAS;IAAC;IAAsB;IAAqB;IAAgB;IAAY;GAAU;GAC3F,OAAO;GACP,MAAM;EACR;EACA,aAAa;GACX,UAAU;IAAE,MAAM;IAAsB,MAAM;GAAI;GAClD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,eAAe;GACtB,OAAO;GACP,MAAM;EACR;EACA,qBAAqB;GACnB,UAAU;IAAE,MAAM;IAAuB,MAAM;GAAI;GACnD,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAK;GAChD,MAAM,CAAC,YAAY;GACnB,SAAS,CAAC,gBAAgB;GAC1B,OAAO;GACP,MAAM;EACR;EACA,iBAAiB;GACf,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAI;GAC/C,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAK;GAChD,MAAM,CAAC,cAAc;GACrB,OAAO;GACP,MAAM;EACR;EACA,aAAa;GACX,UAAU;IAAE,MAAM;IAAsB,MAAM;GAAI;GAClD,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAK;GAChD,MAAM,CAAC,YAAY;GACnB,SAAS,CAAC,gBAAgB;GAC1B,OAAO;GACP,MAAM;EACR;CACF;CACA,UAAU;EACR,mCAAmC,EAAE,OAAO,kBAAkB;EAC9D,sCAAsC,EAAE,OAAO,sBAAsB;EACrE,wCAAwC,EAAE,OAAO,kBAAkB;CACrE;CACA,aAAa;EACX;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GAAE,IAAI;GAAiB,MAAM;GAAc,IAAI;GAAS,IAAI;GAAkB,OAAO;GAAiB,QAAQ;EAA6C;EAC3J;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAAgB;IAAY;GAAuB;GACxD,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAAqB;IAAY;IAAY;GAAc;GAChE,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAa,MAAM;GAAW,IAAI;GAAc,IAAI;GAAqB,OAAO;GAA+B,OAAO;GAAmB,QAAQ;EAAiD;EACxM;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAc,MAAM;GAAQ,IAAI;GAAU,IAAI;GAAkB,QAAQ;EAAwB;EACtG;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,cAAc;GACtB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;IAAC;IAAS;IAAQ;IAAQ;IAAU;GAAQ;GAClD,IAAI;GACJ,IAAI;IAAC;IAAY;IAAY;GAAc;GAC3C,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAsB,MAAM;IAAC;IAAQ;IAAQ;GAAQ;GAAG,IAAI;GAAS,IAAI;GAAc,OAAO,CAAC,cAAc;GAAG,MAAM;GAAyB,QAAQ;EAAwB;EACrL;GAAE,IAAI;GAAqB,MAAM;IAAC;IAAQ;IAAQ;GAAQ;GAAG,IAAI;GAAS,IAAI;GAAkB,OAAO,CAAC,cAAc;GAAG,MAAM;GAA0B,QAAQ;EAAwB;EACzL;GAAE,IAAI;GAAiB,MAAM;GAAQ,IAAI;GAAQ,IAAI;GAAqB,OAAO;GAAsF,QAAQ;EAA4C;EAC3N;GAAE,IAAI;GAAa,MAAM;GAAQ,IAAI;GAAU,IAAI;GAAe,OAAO,CAAC,UAAU;GAAG,QAAQ;EAAsB;EACrH;GAAE,IAAI;GAAe,MAAM;GAAU,IAAI;GAAQ,IAAI;GAAsB,OAAO;GAAuB,QAAQ;EAAuB;EACxI;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,cAAc;GACtB,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAyB,MAAM;GAAU,IAAI;GAAQ,IAAI;GAAe,OAAO;GAAwB,OAAO;GAAuB,QAAQ;EAA0B;EAC7K;GAAE,IAAI;GAAwB,MAAM;GAAU,IAAI;GAAS,IAAI;GAAoB,OAAO,CAAC,cAAc;GAAG,MAAM;GAAiD,QAAQ;EAAwB;EACnM;GAAE,IAAI;GAAc,MAAM,CAAC,QAAQ,MAAM;GAAG,IAAI;GAAS,IAAI;GAAe,OAAO,CAAC,cAAc;GAAG,MAAM;GAAyD,QAAQ;EAAwB;EACpM;GACE,IAAI;GACJ,MAAM,CAAC,QAAQ,MAAM;GACrB,IAAI;GACJ,IAAI;GACJ,OAAO,CAAC,cAAc;GACtB,MAAM;GACN,QAAQ;EACV;CACF;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GAAE,YAAY;GAAY,OAAO;GAAe,MAAM;GAAe,MAAM;GAAe,QAAQ;GAAe,QAAQ;EAAc;EAC/I,MAAM,CAAC;EACP,MAAM;EACN,MAAM;CACR;AACF,CAAC;;;AC7RD,MAAa,KAAK;;;;;;;;;;;;;;;;;;;AAoBlB,MAAa,iBAA0B,cAAc,MAAM;CACzD,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EACV,QAAQ;EACR,yBAAyB;EACzB,QAAQ;EACR,SAAS;CACX;CACA,SAAS;EACP;GACE,KAAK,GAAG,GAAG;GACX,MAAM;EACR;EACA;GAAE,KAAK,GAAG,GAAG;GAAwN,MAAM;EAAc;EACzP;GAAE,KAAK,GAAG,GAAG;GAAkL,MAAM;EAAc;EACnN;GAAE,KAAK,GAAG,GAAG;GAAmJ,MAAM;EAAc;EACpL;GAAE,KAAK,GAAG,GAAG;GAA2P,MAAM;EAAc;EAC5R;GAAE,KAAK,GAAG,GAAG;GAAgJ,MAAM;EAAc;EACjL;GAAE,KAAK,GAAG,GAAG;GAA+J,MAAM;EAAc;EAChM;GAAE,KAAK,GAAG,GAAG;GAA2L,MAAM;EAAc;EAC5N;GAAE,KAAK,GAAG,GAAG;GAAoO,MAAM;EAAc;EACrQ;GAAE,KAAK,GAAG,GAAG;GAAoI,MAAM;EAAc;EACrK;GAAE,KAAK,GAAG,GAAG;GAAqQ,MAAM;EAAc;EACtS;GAAE,KAAK,GAAG,GAAG;GAAuG,MAAM;EAAc;EACxI;GAAE,KAAK,GAAG,GAAG;GAA6I,MAAM;EAAc;EAC9K;GAAE,KAAK,GAAG,GAAG;GAA0I,MAAM;EAAc;EAC3K;GAAE,KAAK,GAAG,GAAG;GAAsK,MAAM;EAAc;CACzM;CACA,QAAQ;EACN,UAAU;GAAE,SAAS;GAAM,QAAQ;GAAM,MAAM;EAA0C;EACzF,OAAO,EAAE,MAAM,2EAA2E;EAC1F,YAAY,EAAE,MAAM,2LAA2L;EAC/M,MAAM,EAAE,MAAM,kHAAkH;EAChI,SAAS,EAAE,MAAM,wGAAwG;EACzH,OAAO;GAAE,OAAO;GAAM,MAAM;EAAuF;CACrH;CACA,QAAQ;EACN,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAuC;EAC9E,cAAc;GAAE,MAAM;GAAM,MAAM;EAAmC;EACrE,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAmF;EAC1H,mBAAmB;GAAE,MAAM;GAAS,MAAM;EAAsC;EAChF,YAAY;GAAE,MAAM;GAAM,MAAM;EAA4C;EAC5E,sBAAsB;GAAE,MAAM;GAAM,MAAM;EAAwD;EAClG,eAAe;GAAE,MAAM;GAAQ,MAAM;EAA8C;EACnF,iBAAiB;GAAE,MAAM;GAAQ,MAAM;EAAgF;EACvH,gBAAgB;GAAE,MAAM;GAAQ,MAAM;EAA2D;EACjG,cAAc;GAAE,MAAM;GAAS,MAAM;EAAsC;EAC3E,iBAAiB;GAAE,MAAM;GAAS,MAAM;EAAuD;EAC/F,cAAc;GAAE,MAAM;GAAS,MAAM;EAAkF;EACvH,eAAe;GAAE,MAAM;GAAS,MAAM;EAA+D;EACrG,YAAY;GAAE,MAAM;GAAM,MAAM;EAAsF;EACtH,YAAY;GAAE,MAAM;GAAM,MAAM;EAAiF;EACjH,eAAe;GAAE,MAAM;GAAS,MAAM;EAA4D;CACpG;CACA,OAAO;EACL,wBAAwB;GAAE,KAAK;GAAiC,OAAO;GAAS,MAAM;GAAK,SAAS;GAAI,KAAK;GAAG,MAAM;EAA+C;EACrK,iBAAiB;GAAE,KAAK;GAA0B,OAAO;GAAS,MAAM;GAAM,SAAS;GAAO,KAAK;GAAG,MAAM;EAAqF;EACjM,mBAAmB;GAAE,KAAK;GAA4B,OAAO;GAAS,MAAM;GAAK,SAAS;GAAG,KAAK;GAAG,MAAM;EAA+C;EAC1J,MAAM;GACJ,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,OAAO;GACL,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,OAAO;GACL,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,wBAAwB;GACtB,UAAU;IAAE,MAAM;IAA0B,MAAM;GAAI;GACtD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,aAAa;GACpB,SAAS,CAAC,YAAY;GACtB,OAAO;GACP,MAAM;EACR;EACA,iBAAiB;GACf,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAK;GAChD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,kBAAkB;GACzB,SAAS,CAAC,mBAAmB,eAAe;GAC5C,OAAO;GACP,MAAM;EACR;EACA,mBAAmB;GACjB,UAAU;IAAE,MAAM;IAA4B,MAAM;GAAI;GACxD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,YAAY;GACnB,SAAS,CAAC,UAAU;GACpB,OAAO;GACP,MAAM;EACR;EACA,OAAO;GACL,UAAU;IAAE,MAAM;IAAS,MAAM;GAAI;GACrC,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,eAAe;GACtB,SAAS,CAAC,oBAAoB;GAC9B,OAAO;GACP,SAAS,EAAE,QAAQ,CAAC,eAAe,EAAE;GACrC,MAAM;EACR;CACF;CACA,aAAa;EACX;GAAE,IAAI;GAAc,MAAM;GAAU,IAAI;GAAS,IAAI;GAAgB,OAAO;GAA0B,QAAQ;EAA+B;EAC7I;GAAE,IAAI;GAAa,MAAM;GAAS,IAAI;GAAQ,IAAI;GAAgB,OAAO;GAAoH,OAAO;GAAqB,QAAQ;EAAiC;EAClQ;GAAE,IAAI;GAAe,MAAM;GAAS,IAAI;GAAc,IAAI;GAAc,OAAO;GAA0C,OAAO;GAAmB,QAAQ;EAA8E;EACzO;GAAE,IAAI;GAAiB,MAAM;GAAc,IAAI;GAAQ,IAAI;GAAmB,OAAO;GAAqB,QAAQ;EAAgD;EAClK;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI,CAAC,iBAAiB,eAAe;GACrC,OAAO;GACP,OAAO,CAAC,eAAe,UAAU;GACjC,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAa,MAAM;GAAQ,IAAI;GAAW,IAAI;GAAY,OAAO;GAAS,QAAQ;EAAqD;EAC7I;GAAE,IAAI;GAAa,MAAM;GAAW,IAAI;GAAQ,IAAI;GAAsB,OAAO;GAAqB,QAAQ;EAA4C;EAC1J;GAAE,IAAI;GAAa,MAAM;GAAW,IAAI;GAAW,IAAI;GAAe,OAAO;GAAS,OAAO,CAAC,UAAU;GAAG,MAAM;GAAoD,QAAQ;EAA4C;EACzN;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM,CAAC,QAAQ,SAAS;GACxB,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM,CAAC,QAAQ,SAAS;GACxB,IAAI;GACJ,IAAI;GACJ,OAAO,CAAC,aAAa;GACrB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;IAAC;IAAS;IAAQ;GAAS;GACjC,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,QAAQ;EACV;CACF;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GAAE,OAAO;GAAe,YAAY;GAAe,MAAM;GAAe,SAAS;EAAc;EACvG,MAAM,CAAC;EACP,MAAM;EACN,MAAM;CACR;AACF,CAAC;;;ACtND,MAAMC,OAAK;AACX,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;AAsBZ,MAAa,mBAA4B,cAAc,MAAM;CAC3D,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EACV,YAAY;EACZ,IAAI;EACJ,OAAO;EACP,QAAQ;CACV;CACA,SAAS;EACP;GAAE,KAAK;GAAqD,MAAM;EAAc;EAChF;GAAE,KAAK,GAAGA,KAAG;GAAoH,MAAM;EAAc;EACrJ;GAAE,KAAK,GAAGA,KAAG;GAA4P,MAAM;EAAc;EAC7R;GAAE,KAAK,GAAGA,KAAG;GAAsP,MAAM;EAAc;EACvR;GAAE,KAAK,GAAGA,KAAG;GAA0J,MAAM;EAAc;EAC3L;GAAE,KAAK,GAAGA,KAAG;GAA2O,MAAM;EAAc;EAC5Q;GAAE,KAAK,GAAGA,KAAG;GAA+P,MAAM;EAAc;EAChS;GAAE,KAAK,GAAGA,KAAG;GAA4K,MAAM;EAAc;EAC7M;GAAE,KAAK,GAAGA,KAAG;GAA0M,MAAM;EAAc;EAC3O;GAAE,KAAK,GAAGA,KAAG;GAAqI,MAAM;EAAc;EACtK;GAAE,KAAK,GAAGA,KAAG;GAAwQ,MAAM;EAAc;EACzS;GAAE,KAAK,GAAGA,KAAG;GAAwO,MAAM;EAAc;EACzQ;GAAE,KAAK,GAAGA,KAAG;GAAwK,MAAM;EAAc;EACzM;GAAE,KAAK,GAAGA,KAAG;GAAoO,MAAM;EAAc;EACrQ;GAAE,KAAK,GAAGA,KAAG;GAA2J,MAAM;EAAc;EAC5L;GAAE,KAAK,GAAGA,KAAG;GAAiK,MAAM;EAAc;EAClM;GAAE,KAAK,GAAGA,KAAG;GAAgP,MAAM;EAAc;EACjR;GAAE,KAAK,GAAGA,KAAG;GAA8I,MAAM;EAAc;EAC/K;GAAE,KAAK,GAAGA,KAAG;GAAiQ,MAAM;EAAc;EAClS;GAAE,KAAK,GAAGA,KAAG;GAA0Q,MAAM;EAAc;EAC3S;GAAE,KAAK,GAAGA,KAAG;GAAkK,MAAM;EAAc;EACnM;GAAE,KAAK,GAAGA,KAAG;GAAqJ,MAAM;EAAc;EACtL;GAAE,KAAK,GAAGA,KAAG;GAAuP,MAAM;EAAc;EACxR;GAAE,KAAK,GAAGA,KAAG;GAAuI,MAAM;EAAc;EACxK;GAAE,KAAK,GAAGA,KAAG;GAAsH,MAAM;EAAc;EACvJ;GAAE,KAAK,GAAGA,KAAG;GAA6F,MAAM;EAAc;EAC9H;GAAE,KAAK,GAAGA,KAAG;GAA8Q,MAAM;EAAc;EAC/S;GAAE,KAAK,GAAGA,KAAG;GAA0Q,MAAM;EAAc;EAC3S;GAAE,KAAK,GAAGA,KAAG;GAAgO,MAAM;EAAc;EACjQ;GAAE,KAAK,GAAGA,KAAG;GAAkN,MAAM;EAAc;EACnP;GAAE,KAAK,GAAGA,KAAG;GAAyN,MAAM;EAAc;EAC1P;GAAE,KAAK,GAAGA,KAAG;GAA8K,MAAM;EAAc;EAC/M;GAAE,KAAK,GAAGA,KAAG;GAAiQ,MAAM;EAAc;EAClS;GAAE,KAAK,GAAGA,KAAG;GAAiE,MAAM;EAAc;EAClG;GAAE,KAAK,GAAGA,KAAG;GAAsL,MAAM;EAAc;EACvN;GAAE,KAAK,GAAGA,KAAG;GAAsM,MAAM;EAAc;EACvO;GAAE,KAAK,GAAGA,KAAG;GAA6F,MAAM;EAAc;EAC9H;GAAE,KAAK,GAAGA,KAAG;GAAyO,MAAM;EAAc;EAC1Q;GAAE,KAAK,GAAGA,KAAG;GAAoL,MAAM;EAAc;EACrN;GAAE,KAAK,GAAGA,KAAG;GAA+N,MAAM;EAAc;EAChQ;GAAE,KAAK,GAAGA,KAAG;GAAwJ,MAAM;EAAc;EACzL;GAAE,KAAK,GAAG,IAAI;GAA0N,MAAM;EAAa;EAC3P;GAAE,KAAK,GAAG,IAAI;GAAoV,MAAM;EAAa;CACvX;CACA,QAAQ;EACN,QAAQ;GAAE,SAAS;GAAM,QAAQ;EAAK;EACtC,SAAS,EAAE,MAAM,wGAAwG;EACzH,gBAAgB,EAAE,MAAM,kGAAkG;EAC1H,MAAM,EAAE,MAAM,sFAAsF;EACpG,qBAAqB,EAAE,MAAM,iGAAiG;EAC9H,SAAS,EACP,MAAM,2IACR;EACA,SAAS,EACP,MAAM,uSACR;EACA,MAAM;GAAE,OAAO;GAAM,MAAM;EAA+E;CAC5G;CACA,QAAQ;EACN,QAAQ;GAAE,MAAM;GAAS,MAAM;EAAkG;EACjI,cAAc;GAAE,MAAM;GAAM,MAAM;EAAkD;EACpF,uBAAuB;GAAE,MAAM;GAAS,MAAM;EAA4E;EAC1H,cAAc;GAAE,MAAM;GAAM,MAAM;EAAiE;EACnG,gBAAgB;GAAE,MAAM;GAAM,MAAM;EAAmD;EACvF,sBAAsB;GAAE,MAAM;GAAM,MAAM;EAAwD;EAClG,YAAY;GAAE,MAAM;GAAM,MAAM;EAAiF;EACjH,wBAAwB;GAAE,MAAM;GAAS,MAAM;EAAgD;EAC/F,mBAAmB;GAAE,MAAM;GAAS,MAAM;EAAsD;EAChG,sBAAsB,EAAE,MAAM,QAAQ;EACtC,2BAA2B;GAAE,MAAM;GAAS,MAAM;EAAiE;EACnH,yBAAyB;GAAE,MAAM;GAAS,MAAM;EAAkC;EAClF,sBAAsB;GAAE,MAAM;GAAS,MAAM;EAAiD;EAC9F,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAA+B;EACxE,aAAa;GAAE,MAAM;GAAS,MAAM;EAA+C;EACnF,YAAY;GAAE,MAAM;GAAQ,MAAM;EAA0C;EAC5E,YAAY,EAAE,MAAM,OAAO;EAC3B,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAkF;EACzH,wBAAwB,EAAE,MAAM,QAAQ;EACxC,wBAAwB,EAAE,MAAM,QAAQ;EACxC,mBAAmB,EAAE,MAAM,QAAQ;EACnC,cAAc,EAAE,MAAM,QAAQ;EAC9B,qBAAqB,EAAE,MAAM,QAAQ;EACrC,6BAA6B,EAAE,MAAM,QAAQ;EAC7C,sBAAsB,EAAE,MAAM,QAAQ;EACtC,sBAAsB;GAAE,MAAM;GAAS,MAAM;EAA2C;CAC1F;CACA,OAAO;EACL,oBAAoB;GAAE,KAAK;GAA+B,OAAO;GAAS,MAAM;GAAK,SAAS;GAAM,MAAM;EAA8E;EACxL,qBAAqB;GAAE,KAAK;GAAgC,OAAO;GAAS,MAAM;GAAK,SAAS;GAAI,MAAM;EAAkF;EAC5L,sBAAsB;GAAE,KAAK;GAAiC,OAAO;GAAS,MAAM;GAAS,SAAS;GAAG,MAAM;EAA+E;EAC9L,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,yBAAyB;GACvB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,sBAAsB;GACpB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,kBAAkB;GAChB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,mBAAmB;GAAE,KAAK;GAAgC,OAAO;GAAW,MAAM;GAAM,SAAS;GAAG,KAAK;GAAG,MAAM;EAAiE;EACnL,cAAc;GAAE,KAAK;GAA2B,OAAO;GAAW,MAAM;GAAM,SAAS;GAAG,KAAK;GAAG,MAAM;EAAwD;EAChK,qBAAqB;GAAE,KAAK;GAAkC,OAAO;GAAW,MAAM;GAAM,SAAS;GAAG,KAAK;GAAG,MAAM;EAAmE;EACzL,qCAAqC;GACnC,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,sBAAsB;GAAE,KAAK;GAAmC,OAAO;GAAW,MAAM;GAAM,SAAS;GAAG,KAAK;GAAG,MAAM;EAA4D;EACpL,kCAAkC;GAChC,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,wBAAwB;GACtB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,IAAI;GAAE,KAAK;GAAa,OAAO;GAAU,MAAM;GAAM,SAAS;GAAM,MAAM;EAAqF;EAC/J,aAAa;GACX,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,gBAAgB;GACd,UAAU;IAAE,MAAM;IAA0B,MAAM;GAAI;GACtD,UAAU;IAAE,MAAM;IAAe,MAAM;GAAK;GAC5C,MAAM,CAAC,eAAe;GACtB,SAAS,CAAC,YAAY;GACtB,OAAO;GACP,MAAM;EACR;EACA,gBAAgB;GACd,UAAU;IAAE,MAAM;IAA0B,MAAM;GAAI;GACtD,UAAU;IAAE,MAAM;IAAe,MAAM;GAAK;GAC5C,MAAM,CAAC,sBAAsB;GAC7B,SAAS,CAAC,qBAAqB;GAC/B,OAAO;GACP,MAAM;EACR;EACA,mBAAmB;GACjB,UAAU;IAAE,MAAM;IAAqB,MAAM;GAAK;GAClD,UAAU;IAAE,MAAM;IAAe,MAAM;GAAK;GAC5C,MAAM,CAAC,YAAY;GACnB,SAAS,CAAC,wBAAwB,UAAU;GAC5C,OAAO;GACP,MAAM;EACR;EACA,cAAc;GACZ,UAAU;IAAE,MAAM;IAAgB,MAAM;GAAK;GAC7C,UAAU;IAAE,MAAM;IAAe,MAAM;GAAK;GAC5C,MAAM,CAAC,iBAAiB;GACxB,SAAS,CAAC,sBAAsB,UAAU;GAC1C,OAAO;GACP,MAAM;EACR;EACA,qBAAqB;GACnB,UAAU;IAAE,MAAM;IAAuB,MAAM;GAAK;GACpD,UAAU;IAAE,MAAM;IAAe,MAAM;GAAK;GAC5C,MAAM,CAAC,yBAAyB;GAChC,SAAS,CAAC,yBAAyB,UAAU;GAC7C,OAAO;GACP,MAAM;EACR;EACA,qBAAqB;GACnB,UAAU;IAAE,MAAM;IAAuC,MAAM;GAAK;GACpE,UAAU;IAAE,MAAM;IAAe,MAAM;GAAK;GAC5C,MAAM,CAAC,2BAA2B;GAClC,SAAS,CAAC,YAAY;GACtB,OAAO;GACP,MAAM;EACR;EACA,cAAc;GACZ,UAAU;IAAE,MAAM;IAAwB,MAAM;GAAK;GACrD,UAAU;IAAE,MAAM;IAAe,MAAM;GAAK;GAC5C,MAAM,CAAC,YAAY;GACnB,SAAS,CAAC,YAAY;GACtB,OAAO;GACP,MAAM;EACR;EACA,cAAc;GACZ,UAAU;IAAE,MAAM;IAAoC,MAAM;GAAK;GACjE,UAAU;IAAE,MAAM;IAAe,MAAM;GAAK;GAC5C,MAAM,CAAC,cAAc,oBAAoB;GACzC,SAAS,CAAC,UAAU;GACpB,OAAO;GACP,MAAM;EACR;CACF;CACA,UAAU;EACR,2CAA2C;GACzC,UAAU;IAAE,MAAM;IAAsB,MAAM;GAAI;GAClD,UAAU;IAAE,OAAO;IAAe,OAAO,CAAC,sBAAsB,IAAI;IAAG,MAAM;GAAI;GACjF,OAAO;IAAE,OAAO;IAAe,OAAO,CAAC,IAAI;IAAG,MAAM;GAAI;GACxD,MAAM;EACR;EACA,gDAAgD,EAAE,OAAO,YAAY;CACvE;CACA,aAAa;EACX;GAAE,IAAI;GAAa,MAAM;GAAU,IAAI;GAAW,IAAI;GAAU,QAAQ;EAA8C;EACtH;GAAE,IAAI;GAAc,MAAM;GAAW,IAAI;GAAkB,IAAI;GAAc,QAAQ;EAA4B;EACjH;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAAY;IAAY;GAAc;GAC3C,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;IAAC;IAAY;IAAY;GAAc;GAC3C,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM,CAAC,QAAQ,qBAAqB;GACpC,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAY,MAAM;GAAW,IAAI;GAAQ,IAAI;GAAsB,OAAO;GAAwB,QAAQ;EAAuB;EACvI;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM,CAAC,WAAW,qBAAqB;GACvC,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAmB,MAAM;GAAW,IAAI;GAAW,IAAI;GAAsB,QAAQ;EAA0C;EACrI;GAAE,IAAI;GAAmB,MAAM;GAAW,IAAI;GAAW,IAAI;GAAkB,QAAQ;EAAsB;EAC7G;GACE,IAAI;GACJ,MAAM,CAAC,WAAW,SAAS;GAC3B,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM,CAAC,QAAQ,qBAAqB;GACpC,IAAI;GACJ,IAAI;IAAC;IAAY;IAAY;GAAc;GAC3C,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAgB,MAAM,CAAC,QAAQ,qBAAqB;GAAG,IAAI;GAAQ,IAAI;GAAgB,QAAQ;EAAuB;EAC5H;GACE,IAAI;GACJ,MAAM;IAAC;IAAQ;IAAuB;IAAW;GAAS;GAC1D,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;CACF;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GACN,SAAS;GACT,gBAAgB;GAChB,MAAM;GACN,qBAAqB;GACrB,SAAS;GACT,SAAS;EACX;EACA,MAAM;GACJ,UAAU;IAAE,MAAM;IAAsB,MAAM;GAAI;GAClD,WAAW;IAAE,MAAM;IAAuB,MAAM;GAAI;GACpD,SAAS;IAAE,MAAM;IAAwB,MAAM;GAAQ;GACvD,kBAAkB;IAAE,MAAM;IAAoB,MAAM;GAAK;EAC3D;EACA,MAAM;EACN,MAAM;CACR;AACF,CAAC;;;ACjcD,MAAa,KAAK;;;;;;;;;;;;;;;;;;;;AAqBlB,MAAa,mBAA4B,cAAc,MAAM;CAC3D,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EACV,WAAW;EACX,MAAM;EACN,QAAQ;EACR,QAAQ;CACV;CACA,SAAS;EACP;GAAE,KAAK,GAAG,GAAG;GAAyK,MAAM;EAAc;EAC1M;GAAE,KAAK,GAAG,GAAG;GAAyI,MAAM;EAAc;EAC1K;GAAE,KAAK,GAAG,GAAG;GAA0H,MAAM;EAAc;EAC3J;GACE,KAAK,2CAA2C,GAAG;GACnD,MAAM;EACR;EACA;GACE,KAAK,GAAG,GAAG;GACX,MAAM;EACR;EACA;GAAE,KAAK,GAAG,GAAG;GAAiI,MAAM;EAAc;EAClK;GAAE,KAAK,GAAG,GAAG;GAAoH,MAAM;EAAc;EACrJ;GAAE,KAAK,GAAG,GAAG;GAA2N,MAAM;EAAc;EAC5P;GAAE,KAAK,GAAG,GAAG;GAAiN,MAAM;EAAc;EAClP;GAAE,KAAK,GAAG,GAAG;GAA+K,MAAM;EAAc;EAChN;GAAE,KAAK,GAAG,GAAG;GAAqT,MAAM;EAAc;EACtV;GAAE,KAAK,GAAG,GAAG;GAAwN,MAAM;EAAc;EACzP;GAAE,KAAK,GAAG,GAAG;GAA2K,MAAM;EAAc;EAC5M;GAAE,KAAK,GAAG,GAAG;GAAgJ,MAAM;EAAc;EACjL;GAAE,KAAK,GAAG,GAAG;GAAmT,MAAM;EAAc;EACpV;GAAE,KAAK,GAAG,GAAG;GAAgH,MAAM;EAAc;EACjJ;GAAE,KAAK,GAAG,GAAG;GAA2S,MAAM;EAAc;CAC9U;CACA,QAAQ;EACN,UAAU;GAAE,SAAS;GAAM,QAAQ;GAAM,MAAM;EAAsC;EACrF,WAAW,EAAE,MAAM,kDAAkD;EACrE,MAAM,EAAE,MAAM,oGAAoG;EAClH,MAAM,EAAE,MAAM,qEAAqE;EACnF,UAAU,EAAE,MAAM,gHAAgH;EAClI,MAAM,EAAE,MAAM,iHAAiH;EAC/H,OAAO;GAAE,OAAO;GAAM,MAAM;EAAuE;CACrG;CACA,QAAQ;EACN,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAmC;EAC1E,cAAc;GAAE,MAAM;GAAM,MAAM;EAAmC;EACrE,uBAAuB;GAAE,MAAM;GAAS,MAAM;EAAwE;EACtH,YAAY;GAAE,MAAM;GAAM,MAAM;EAAmD;EACnF,qBAAqB;GAAE,MAAM;GAAS,MAAM;EAA8D;EAC1G,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAwE;EAC/G,eAAe;GAAE,MAAM;GAAQ,MAAM;EAAkG;EACvI,eAAe;GAAE,MAAM;GAAQ,MAAM;EAA6E;EAClH,iBAAiB;GAAE,MAAM;GAAS,MAAM;EAA+F;EACvI,mBAAmB;GAAE,MAAM;GAAS,MAAM;EAAqC;EAC/E,cAAc;GAAE,MAAM;GAAS,MAAM;EAA8C;EACnF,mBAAmB;GAAE,MAAM;GAAS,MAAM;EAAyD;EACnG,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAA0H;EACnK,gBAAgB;GAAE,MAAM;GAAM,MAAM;EAAqD;EACzF,YAAY;GAAE,MAAM;GAAM,MAAM;EAA0F;CAC5H;CACA,OAAO;EACL,2BAA2B;GAAE,KAAK;GAAqD,OAAO;GAAS,MAAM;GAAK,SAAS;GAAI,KAAK;GAAG,MAAM;EAAqC;EAClL,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,uBAAuB;GAAE,KAAK;GAA+C,OAAO;GAAS,MAAM;GAAM,SAAS;GAAO,MAAM;EAAmC;EAClK,WAAW;GAAE,KAAK;GAAsC,OAAO;GAAW,MAAM;GAAM,SAAS;GAAM,MAAM;EAA+D;EAC1K,MAAM;GAAE,KAAK;GAA+C,OAAO;GAAW,MAAM;GAAM,SAAS;GAAO,MAAM;EAAgE;EAChL,eAAe;GAAE,KAAK;GAA0C,OAAO;GAAW,MAAM;GAAM,SAAS;GAAO,MAAM;EAA4D;EAChL,OAAO;GACL,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,mBAAmB;GACjB,UAAU;IAAE,MAAM;IAAa,MAAM;GAAK;GAC1C,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,iBAAiB;GACxB,SAAS,CAAC,YAAY;GACtB,OAAO;GACP,MAAM;EACR;EACA,cAAc;GACZ,UAAU;IAAE,MAAM;IAAQ,MAAM;GAAK;GACrC,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,YAAY;GACnB,SAAS,CAAC,qBAAqB;GAC/B,OAAO;GACP,MAAM;EACR;EACA,WAAW;GACT,UAAU;IAAE,MAAM;IAA6B,MAAM;GAAI;GACzD,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,YAAY;GACnB,SAAS,CAAC,UAAU;GACpB,OAAO;GACP,SAAS,EAAE,QAAQ,CAAC,YAAY,EAAE;GAClC,MAAM;EACR;EACA,kBAAkB;GAChB,UAAU;IAAE,MAAM;IAAiB,MAAM;GAAK;GAC9C,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,gBAAgB;GACvB,SAAS,CAAC,mBAAmB;GAC7B,OAAO;GACP,MAAM;EACR;CACF;CACA,aAAa;EACX;GAAE,IAAI;GAAc,MAAM;GAAU,IAAI;GAAa,IAAI;GAAgB,OAAO;GAAqB,QAAQ;EAAyC;EACtJ;GAAE,IAAI;GAAe,MAAM;GAAa,IAAI;GAAQ,IAAI;GAAc,OAAO;GAAgB,QAAQ;EAA0C;EAC/I;GAAE,IAAI;GAA2B,MAAM;GAAa,IAAI;GAAS,IAAI;GAAmB,QAAQ;EAA0C;EAC1I;GAAE,IAAI;GAAsB,MAAM;GAAQ,IAAI;GAAS,IAAI;GAAc,OAAO;GAAS,OAAO,CAAC,UAAU;GAAG,QAAQ;EAA0C;EAChK;GAAE,IAAI;GAAqB,MAAM;GAAQ,IAAI;GAAQ,IAAI;GAAuB,OAAO;GAAa,QAAQ;EAA0C;EACtJ;GAAE,IAAI;GAAiB,MAAM,CAAC,QAAQ,MAAM;GAAG,IAAI;GAAQ,IAAI;GAAmB,OAAO;GAAuC,OAAO;GAAa,OAAO,CAAC,cAAc;GAAG,QAAQ;EAA0C;EAC/N;GAAE,IAAI;GAAa,MAAM;GAAQ,IAAI;GAAY,IAAI;GAAY,OAAO;GAAoB,QAAQ;EAA0C;EAC9I;GAAE,IAAI;GAAmB,MAAM;GAAY,IAAI;GAAQ,IAAI;GAAqB,QAAQ;EAAoD;EAC5I;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAa,MAAM;GAAQ,IAAI;GAAQ,IAAI;GAAgB,OAAO;GAAa,QAAQ;EAA0C;EACvI;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAY,MAAM;IAAC;IAAa;IAAQ;IAAQ;IAAY;GAAM;GAAG,IAAI;GAAS,IAAI;GAAe,QAAQ;EAAsD;EACzK;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;CACF;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GAAE,WAAW;GAAe,MAAM;GAAe,MAAM;GAAe,UAAU;GAAe,MAAM;EAAc;EAC3H,MAAM,CAAC;EACP,MAAM;EACN,MAAM;CACR;AACF,CAAC;;;;;;;;;;;;;;;;ACjLD,MAAa,mBAA4B,cAAc,MAAM;CAC3D,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EACV,WAAW;EACX,MAAM;EACN,QAAQ;CACV;CACA,SAAS;EACP;GAAE,KAAK,GAAG,GAAG;GAAoL,MAAM;EAAc;EACrN;GAAE,KAAK,GAAG,GAAG;GAA4J,MAAM;EAAc;EAC7L;GAAE,KAAK,GAAG,GAAG;GAAgO,MAAM;EAAc;EACjQ;GAAE,KAAK,GAAG,GAAG;GAA0O,MAAM;EAAc;EAC3Q;GAAE,KAAK,GAAG,GAAG;GAA0M,MAAM;EAAc;EAC3O;GAAE,KAAK,GAAG,GAAG;GAA0J,MAAM;EAAc;EAC3L;GAAE,KAAK,GAAG,GAAG;GAA8H,MAAM;EAAc;EAC/J;GAAE,KAAK,GAAG,GAAG;GAAsH,MAAM;EAAc;EACvJ;GAAE,KAAK,GAAG,GAAG;GAAgO,MAAM;EAAc;EACjQ;GAAE,KAAK,GAAG,GAAG;GAA8R,MAAM;EAAc;EAC/T;GACE,KAAK,GAAG,GAAG;GACX,MAAM;EACR;CACF;CACA,QAAQ;EACN,UAAU;GAAE,SAAS;GAAM,QAAQ;GAAM,MAAM;EAA8B;EAC7E,UAAU,EAAE,MAAM,oFAAoF;EACtG,YAAY,EAAE,MAAM,2CAA2C;EAC/D,gBAAgB,EAAE,MAAM,2EAA2E;EACnG,MAAM,EAAE,MAAM,kEAAkE;EAChF,MAAM,EAAE,MAAM,0GAA0G;EACxH,OAAO;GAAE,OAAO;GAAM,MAAM;EAAuD;CACrF;CACA,QAAQ;EACN,eAAe;GAAE,MAAM;GAAS,MAAM;EAAgC;EACtE,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAAuB;EAChE,sBAAsB;GAAE,MAAM;GAAM,MAAM;EAAiF;EAC3H,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAAiD;EAC1F,eAAe;GAAE,MAAM;GAAQ,MAAM;EAA4C;EACjF,YAAY;GAAE,MAAM;GAAQ,MAAM;EAAmC;EACrE,YAAY;GAAE,MAAM;GAAQ,MAAM;EAA0C;EAC5E,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAoD;EAC3F,oBAAoB;GAAE,MAAM;GAAM,MAAM;EAAsE;EAC9G,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAA6D;EACtG,iBAAiB;GAAE,MAAM;GAAS,MAAM;EAAiC;EACzE,cAAc;GAAE,MAAM;GAAS,MAAM;EAA0C;EAC/E,gBAAgB;GAAE,MAAM;GAAM,MAAM;EAAsD;EAC1F,YAAY;GAAE,MAAM;GAAM,MAAM;EAA0F;EAC1H,oBAAoB;GAAE,MAAM;GAAS,MAAM;EAAoG;CACjJ;CACA,OAAO;EACL,UAAU;GAAE,KAAK;GAAmD,OAAO;GAAW,MAAM;GAAM,SAAS;GAAM,MAAM;EAA2D;EAClL,SAAS;GAAE,KAAK;GAAgD,OAAO;GAAW,MAAM;GAAM,SAAS;GAAM,MAAM;EAAoF;EACvM,MAAM;GAAE,KAAK;GAAyD,OAAO;GAAW,MAAM;GAAM,SAAS;GAAO,MAAM;EAA2D;EACrL,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,KAAK;GACL,MAAM;EACR;EACA,OAAO;GACL,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,UAAU;GACR,UAAU;IAAE,MAAM;IAAY,MAAM;GAAK;GACzC,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,gBAAgB;GACvB,OAAO;GACP,MAAM;EACR;EACA,iBAAiB;GACf,UAAU;IAAE,MAAM;IAAW,MAAM;GAAK;GACxC,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,kBAAkB;GACzB,SAAS;IAAC;IAAkB;IAAgB;GAAU;GACtD,OAAO;GACP,MAAM;EACR;EACA,wBAAwB;GACtB,UAAU;IAAE,MAAM;IAAQ,MAAM;GAAK;GACrC,UAAU;IAAE,MAAM;IAAS,MAAM;GAAK;GACtC,MAAM,CAAC,sBAAsB;GAC7B,SAAS;IAAC;IAAsB;IAAY;IAAY;GAAc;GACtE,OAAO;GACP,MAAM;EACR;CACF;CACA,aAAa;EACX;GAAE,IAAI;GAAa,MAAM;GAAU,IAAI;GAAc,IAAI;GAAe,OAAO;GAAmD,OAAO;GAAmB,QAAQ;EAAsC;EAC1M;GAAE,IAAI;GAAkB,MAAM;GAAU,IAAI;GAAY,IAAI;GAAe,OAAO;GAAkD,OAAO;GAAY,QAAQ;EAAsC;EACrM;GAAE,IAAI;GAAqB,MAAM;GAAY,IAAI;GAAc,IAAI;GAAkB,OAAO;GAAmB,QAAQ;EAAsC;EAC7J;GAAE,IAAI;GAAiB,MAAM;GAAc,IAAI;GAAkB,IAAI;GAAkB,OAAO;GAA0B,QAAQ;EAAsC;EACtK;GACE,IAAI;GACJ,MAAM,CAAC,cAAc,gBAAgB;GACrC,IAAI;GACJ,IAAI;IAAC;IAAiB;IAAgB;IAAY;IAAY;GAAY;GAC1E,OAAO;GACP,OAAO,CAAC,UAAU;GAClB,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAqB,MAAM;GAAkB,IAAI;GAAQ,IAAI;GAAsB,QAAQ;EAAsC;EACvI;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO,CAAC,kBAAkB;GAC1B,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAgB,MAAM;GAAQ,IAAI;GAAQ,IAAI;GAAkB,QAAQ;EAAsC;EACpH;GAAE,IAAI;GAAe,MAAM;GAAQ,IAAI;GAAQ,IAAI;GAAsB,QAAQ;EAAsC;EACvH;GACE,IAAI;GACJ,MAAM,CAAC,QAAQ,MAAM;GACrB,IAAI;GACJ,IAAI;IAAC;IAAY;IAAY;GAAc;GAC3C,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAmB,MAAM;GAAQ,IAAI;GAAS,IAAI;GAAe,OAAO,CAAC,cAAc;GAAG,QAAQ;EAAsC;CAChJ;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GAAE,YAAY;GAAY,gBAAgB;GAAe,MAAM;GAAe,MAAM;EAAc;EAC1G,MAAM,EAAE,UAAU;GAAE,MAAM;GAAkB,MAAM;EAAI,EAAE;EACxD,MAAM;EACN,MAAM;CACR;AACF,CAAC;;;;;;;;;;;;;;AC/ID,MAAM,cAAc,aAA2B;CAC7C,IAAI,EAAE,UAAU,aAAa,SAAS,SAAS,MAAM,MAAM,IAAI,MAAM,sBAAsB;CAC3F,OAAO,SAAS;AAClB;;AAGA,MAAM,iBAAiB;;AAGvB,MAAM,QAAQ,OAAuB,WAAW,kBAAkB,EAAE,CAAC;;AAErE,MAAM,QAAQ,WAAW,gBAAgB;;;;;;;;;;;;;;;;;;AAmBzC,MAAa,uBAAgC,cAAc,MAAM;CAC/D,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EAAE,sBAAsB;EAAS,0BAA0B;EAAS,MAAM;EAAW,QAAQ;EAAU,IAAI;EAAU,QAAQ;CAAY;CACrJ,SAAS;EACP;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;CACF;CACA,QAAQ;EACN,cAAc;GAAE,SAAS;GAAM,MAAM;EAAY;EACjD,YAAY,EAAE,MAAM,qCAAqC;EACzD,WAAW,EAAE,MAAM,gCAAgC;EACnD,eAAe,EAAE,MAAM,6EAA6E;EACpG,cAAc,EAAE,MAAM,+BAA+B;EACrD,eAAe,EAAE,MAAM,2DAA2D;CACpF;CACA,QAAQ;EACN,SAAS;GAAE,MAAM;GAAO,MAAM;EAAuB;EACrD,MAAM;GAAE,MAAM;GAAM,MAAM;EAAgD;EAC1E,qBAAqB,EAAE,MAAM,QAAQ;EACrC,YAAY;GAAE,MAAM;GAAS,MAAM;EAAyB;EAC5D,MAAM,EAAE,MAAM,KAAK;EACnB,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAwC;EAC/E,MAAM;GAAE,MAAM;GAAS,MAAM;EAAgG;EAC7H,iBAAiB,EAAE,MAAM,QAAQ;EACjC,WAAW;GAAE,MAAM;GAAS,MAAM;EAAkD;EACpF,cAAc;GAAE,MAAM;GAAM,MAAM;EAA8B;EAChE,YAAY;GAAE,MAAM;GAAM,MAAM;EAAyC;EACzE,mBAAmB,EAAE,MAAM,QAAQ;EACnC,OAAO;GAAE,MAAM;GAAO,MAAM;EAA6B;EACzD,QAAQ,EAAE,MAAM,QAAQ;CAC1B;CACA,OAAO;EACL,oBAAoB;GAAE,KAAK;GAAsB,OAAO;GAAU,MAAM;GAAM,SAAS;EAAM;EAC7F,mBAAmB;GAAE,KAAK;GAAqB,OAAO;GAAU,MAAM;GAAM,SAAS;EAAK;EAC1F,kBAAkB;GAAE,KAAK;GAAoB,OAAO;GAAU,MAAM;GAAS,SAAS;EAAE;EACxF,yBAAyB;GAAE,KAAK;GAA0B,OAAO;GAAU,MAAM;GAAM,SAAS;EAAK;EACrG,8BAA8B;GAAE,KAAK;GAA+B,OAAO;GAAU,MAAM;GAAS,SAAS;EAAI;EACjH,qBAAqB;GAAE,KAAK;GAAsB,OAAO;GAAU,MAAM;GAAM,SAAS;EAAM;EAC9F,wBAAwB;GAAE,KAAK;GAAyB,OAAO;GAAU,MAAM;GAAS,SAAS;GAAM,MAAM;EAA0B;EACvI,kBAAkB;GAChB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,iBAAiB;GAAE,KAAK;GAAkB,OAAO;GAAU,MAAM;GAAM,SAAS;EAAM;EACtF,oBAAoB;GAAE,KAAK;GAAqB,OAAO;GAAU,MAAM;GAAM,SAAS;GAAO,MAAM;EAA2E;EAC9K,iBAAiB;GACf,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,IAAI;GACF,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;CACF;CACA,QAAQ;EACN,MAAM;GACJ,UAAU;IAAE,MAAM;IAAsB,MAAM;GAAK;GACnD,UAAU,kBAAkB,oBAAoB;GAChD,OAAO;GACP,MAAM,CAAC,iBAAiB;GACxB,SAAS,CAAC,QAAQ,OAAO;GACzB,OAAO;GACP,SAAS,EAAE,QAAQ,CAAC,MAAM,EAAE;GAC5B,MAAM;EACR;EACA,MAAM;GACJ,UAAU;IAAE,MAAM;IAAmE,MAAM;GAAK;GAChG,UAAU;IAAE,MAAM,6BAA6B,KAAK,oBAAoB,EAAE,MAAM,KAAK,mBAAmB;IAAK,MAAM;GAAK;GACxH,OAAO;IAAE,MAAM,uBAAuB,MAAM;IAAI,MAAM;GAAK;GAC3D,MAAM,CAAC,qBAAqB;GAC5B,SAAS;IAAC;IAAQ;IAAQ;GAAO;GACjC,OAAO;GACP,MAAM;EACR;EACA,WAAW;GACT,UAAU;IAAE,MAAM;IAAgB,MAAM;GAAK;GAC7C,UAAU,kBAAkB,cAAc;GAC1C,OAAO;IAAE,MAAM,sBAAsB,eAAe,KAAK;IAAS,MAAM;GAAK;GAC7E,MAAM,CAAC,oBAAoB;GAC3B,SAAS,CAAC,OAAO;GACjB,OAAO;GACP,SAAS,EAAE,QAAQ,CAAC,MAAM,EAAE;GAC5B,MAAM;EACR;EACA,WAAW;GACT,UAAU;IAAE,MAAM;IAAsB,MAAM;GAAK;GACnD,UAAU,kBAAkB,oBAAoB;GAChD,OAAO;GACP,MAAM,CAAC,kBAAkB;GACzB,SAAS;IAAC;IAAQ;IAAQ;GAAO;GACjC,OAAO;EACT;EACA,SAAS;GACP,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAK;GAChD,UAAU,kBAAkB,iBAAiB;GAC7C,OAAO;GACP,MAAM,CAAC,YAAY;GACnB,SAAS;IAAC;IAAY;IAAQ;GAAO;GACrC,OAAO;GACP,MAAM;EACR;CACF;CACA,UAAU,EAER,2CAA2C,EAAE,OAAO,OAAO,EAC7D;CACA,aAAa;EACX;GAAE,IAAI;GAAa,MAAM;GAAgB,IAAI;GAAW,IAAI;EAAa;EACzE;GAAE,IAAI;GAAW,MAAM;GAAc,IAAI;GAAQ,IAAI;GAAa,QAAQ;EAAuB;EACjG;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,SAAS;GACjB,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAW,MAAM;GAAiB,IAAI;GAAQ,IAAI;GAAa,QAAQ;EAAuB;EACpG;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,gBAAgB;GACxB,MAAM;GACN,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;IAAC;IAAc;IAAa;GAAe;GACjD,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;IAAC;IAAc;IAAa;GAAe;GACjD,IAAI;GACJ,IAAI;GACJ,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;IAAC;IAAgB;IAAc;IAAa;IAAiB;GAAc;GACjF,IAAI;GACJ,IAAI;EACN;EACA;GAAE,IAAI;GAAa,MAAM;GAAiB,IAAI;GAAU,IAAI;EAAe;CAC7E;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GAAE,YAAY;GAAY,WAAW;GAAe,eAAe;EAAc;EACzF,MAAM;GACJ,UAAU;IAAE,MAAM;IAAmB,MAAM;GAAI;GAC/C,WAAW;IAAE,OAAO;IAAG,MAAM;GAAI;GACjC,SAAS;IAAE,OAAO;IAAI,MAAM;GAAQ;EACtC;EACA,MAAM;EACN,MAAM;CACR;AACF,CAAmB;;;;;;;;;;AAWnB,MAAa,uBAAgC,cAAc,MAAM;CAC/D,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EAAE,sBAAsB;EAAS,IAAI;EAAU,MAAM;EAAW,QAAQ;CAAY;CAChG,SAAS;EACP;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;EACA;GACE,KAAK;GACL,MAAM;EACR;CACF;CACA,QAAQ;EACN,QAAQ;GAAE,SAAS;GAAM,QAAQ;EAAK;EACtC,MAAM,EAAE,MAAM,iCAAiC;EAC/C,SAAS,EAAE,MAAM,8CAA8C;EAC/D,QAAQ,EAAE,OAAO,KAAK;CACxB;CACA,QAAQ;EACN,QAAQ,EAAE,MAAM,QAAQ;EACxB,mBAAmB;GAAE,MAAM;GAAS,MAAM;EAAuC;EACjF,WAAW,EAAE,MAAM,KAAK;EACxB,WAAW;GAAE,MAAM;GAAM,MAAM;EAAwC;EACvE,kBAAkB,EAAE,MAAM,QAAQ;EAClC,OAAO;GAAE,MAAM;GAAQ,MAAM;EAAsC;EACnE,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAA+D;CACxG;CACA,OAAO;EACL,oBAAoB;GAAE,KAAK;GAAsB,OAAO;GAAU,MAAM;GAAM,SAAS;GAAO,MAAM;EAAqC;EACzI,kBAAkB;GAAE,KAAK;GAAoB,OAAO;GAAU,MAAM;GAAS,SAAS;EAAE;EACxF,eAAe;GACb,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,IAAI;GAAE,KAAK;GAAa,OAAO;GAAU,MAAM;GAAM,SAAS;EAAK;CACrE;CACA,QAAQ,EACN,WAAW;EACT,UAAU;GAAE,MAAM;GAAyC,MAAM;EAAK;EACtE,UAAU;GAAE,MAAM,uBAAuB,KAAK,oBAAoB,EAAE;GAAI,MAAM;EAAK;EACnF,OAAO;GAAE,MAAM,uBAAuB,MAAM;GAAI,MAAM;EAAK;EAC3D,MAAM,CAAC,eAAe;EACtB,SAAS,CAAC,SAAS;EACnB,OAAO;EACP,MAAM;CACR,EACF;CACA,aAAa;EACX;GAAE,IAAI;GAAa,MAAM;GAAU,IAAI;GAAU,IAAI;EAAO;EAC5D;GAAE,IAAI;GAAW,MAAM;GAAQ,IAAI;GAAmB,IAAI;EAAU;EACpE;GAAE,IAAI;GAAW,MAAM;GAAW,IAAI;GAAW,IAAI;EAAO;EAC5D;GAAE,IAAI;GAAW,MAAM,CAAC,QAAQ,SAAS;GAAG,IAAI;GAAW,IAAI;GAAQ,OAAO,CAAC,SAAS;GAAG,QAAQ;EAAuB;EAC1H;GAAE,IAAI;GAAgB,MAAM;GAAW,IAAI;GAAkB,IAAI;GAAU,OAAO;GAAa,OAAO,CAAC,QAAQ;GAAG,QAAQ;EAAsB;EAChJ;GAAE,IAAI;GAAY,MAAM,CAAC,QAAQ,SAAS;GAAG,IAAI,CAAC,SAAS,cAAc;GAAG,IAAI;EAAS;CAC3F;CACA,MAAM;EACJ,SAAS;EACT,QAAQ;GAAE,MAAM;GAAe,SAAS;EAAc;EACtD,MAAM,CAAC;EACP,MAAM;CACR;AACF,CAAmB;;;AClYnB,MAAM,KAAK;;;;;;;AAQX,MAAa,WAAoB,cAAc,MAAM;CACnD,QAAQ;CACR,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;EAAE,QAAQ;EAAS,OAAO;CAAgC;CACtE,SAAS;EACP;GAAE,KAAK,GAAG,GAAG;GAAkD,MAAM;EAAc;EACnF;GAAE,KAAK,GAAG,GAAG;GAA8G,MAAM;EAAc;EAC/I;GAAE,KAAK,GAAG,GAAG;GAA8D,MAAM;EAAc;EAC/F;GAAE,KAAK,GAAG,GAAG;GAAmD,MAAM;EAAc;EACpF;GAAE,KAAK,GAAG,GAAG;GAAgD,MAAM;EAAc;EACjF;GAAE,KAAK,GAAG,GAAG;GAAwC,MAAM;EAAc;EACzE;GAAE,KAAK,GAAG,GAAG;GAA2F,MAAM;EAAc;EAC5H;GAAE,KAAK,GAAG,GAAG;GAA8F,MAAM;EAAc;EAC/H;GAAE,KAAK;GAAsG,MAAM;EAAW;CAChI;CACA,QAAQ;EACN,IAAI;GAAE,SAAS;GAAM,MAAM;EAAwC;EACnE,OAAO,EAAE,MAAM,gFAAgF;EAC/F,OAAO,EAAE,MAAM,2EAA2E;EAC1F,cAAc,EAAE,MAAM,0EAA0E;EAChG,kBAAkB,EAAE,MAAM,gEAAgE;EAC1F,wBAAwB,EAAE,MAAM,sEAAsE;EACtG,kBAAkB,EAAE,MAAM,wGAAwG;EAClI,mBAAmB,EAAE,MAAM,4GAA4G;EACvI,iBAAiB,EAAE,MAAM,oHAAoH;CAC/I;CACA,QAAQ;EACN,cAAc;GAAE,MAAM;GAAS,MAAM;EAAiD;EACtF,WAAW;GAAE,MAAM;GAAM,MAAM;EAAuF;EACtH,WAAW;GAAE,MAAM;GAAM,MAAM;EAAyD;EACxF,oBAAoB,EAAE,MAAM,QAAQ;EACpC,UAAU;GAAE,MAAM;GAAM,MAAM;EAAgF;EAC9G,iBAAiB;GAAE,MAAM;GAAM,MAAM;EAAiD;EACtF,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAAiE;EACxG,eAAe;GAAE,MAAM;GAAS,MAAM;EAAqG;EAC3I,gBAAgB;GAAE,MAAM;GAAO,MAAM;EAA8E;EACnH,YAAY;GAAE,MAAM;GAAM,MAAM;EAAmF;EACnH,kBAAkB,EAAE,MAAM,QAAQ;EAClC,kBAAkB;GAAE,MAAM;GAAS,MAAM;EAA2D;EACpG,oBAAoB,EAAE,MAAM,QAAQ;EACpC,sBAAsB;GAAE,MAAM;GAAM,MAAM;EAAoF;EAC9H,kBAAkB;GAAE,MAAM;GAAM,MAAM;EAAuE;EAC7G,mBAAmB,EAAE,MAAM,QAAQ;EACnC,wBAAwB;GAAE,MAAM;GAAM,MAAM;EAA2G;EACvJ,gBAAgB,EAAE,MAAM,QAAQ;EAChC,kBAAkB;GAAE,MAAM;GAAM,MAAM;EAAkE;EACxG,gBAAgB;GAAE,MAAM;GAAS,MAAM;EAA+C;EACtF,WAAW,EAAE,MAAM,KAAK;EACxB,WAAW,EAAE,MAAM,KAAK;EACxB,YAAY;GAAE,MAAM;GAAM,MAAM;EAAwE;EACxG,iBAAiB,EAAE,MAAM,QAAQ;EACjC,cAAc;GAAE,MAAM;GAAM,MAAM;EAAuG;EACzI,eAAe,EAAE,MAAM,QAAQ;EAC/B,sBAAsB,EAAE,MAAM,QAAQ;CACxC;CACA,OAAO;EACL,YAAY;GAAE,KAAK;GAAoC,OAAO;GAAS,MAAM;GAAM,SAAS;GAAO,MAAM;EAAgB;EACzH,kBAAkB;GAAE,KAAK;GAA6B,OAAO;GAAS,MAAM;GAAM,SAAS;GAAQ,MAAM;EAAgB;EACzH,gBAAgB;GAAE,KAAK;GAA2B,OAAO;GAAS,MAAM;GAAS,SAAS;GAAG,MAAM;EAAiB;EACpH,QAAQ;GAAE,KAAK;GAA6B,OAAO;GAAS,MAAM;GAAS,SAAS;EAAK;EACzF,WAAW;GACT,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,aAAa;GAAE,KAAK;GAA8B,OAAO;GAAW,MAAM;GAAM,SAAS;GAAM,MAAM;EAAqB;EAC1H,aAAa;GAAE,KAAK;GAA8B,OAAO;GAAW,MAAM;GAAM,SAAS;GAAO,MAAM;EAAgB;EACtH,sBAAsB;GACpB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,YAAY;GAAE,KAAK;GAA6B,OAAO;GAAW,MAAM;GAAM,SAAS;GAAM,MAAM;EAAgB;EACnH,gBAAgB;GAAE,KAAK;GAAiC,OAAO;GAAW,MAAM;GAAM,SAAS;GAAM,MAAM;EAAgB;EAC3H,cAAc;GAAE,KAAK;GAA+B,OAAO;GAAW,MAAM;GAAM,SAAS;GAAM,MAAM;EAAgB;EACvH,aAAa;GAAE,KAAK;GAA8B,OAAO;GAAW,MAAM;GAAM,SAAS;GAAO,MAAM;EAAgB;EACtH,wBAAwB;GAAE,KAAK;GAAuC,OAAO;GAAW,MAAM;GAAM,SAAS;GAAO,MAAM;EAAgB;EAC1I,2BAA2B;GACzB,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;EACR;EACA,kBAAkB;GAAE,KAAK;GAAmC,OAAO;GAAW,MAAM;GAAM,SAAS;GAAO,MAAM;EAAgB;EAChI,YAAY;GAAE,KAAK;GAAuB,OAAO;GAAS,MAAM;GAAM,SAAS;GAAM,MAAM;EAAiB;CAC9G;CACA,QAAQ;EACN,MAAM;GAEJ,UAAU;IAAE,MAAM;IAAoB,MAAM;GAAK;GACjD,OAAO;IAAE,MAAM;IAAwD,MAAM;GAAK;GAClF,MAAM,CAAC,YAAY;GACnB,OAAO;GACP,MAAM;EACR;EACA,MAAM;GAEJ,UAAU;IAAE,MAAM;IAAgC,MAAM;GAAK;GAC7D,UAAU;IAAE,MAAM;IAAoB,MAAM;GAAK;GACjD,MAAM,CAAC,SAAS;GAChB,OAAO;EACT;EACA,YAAY;GAEV,UAAU;IAAE,MAAM;IAAc,MAAM;GAAK;GAC3C,UAAU;IAAE,MAAM;IAAwB,MAAM;GAAK;GACrD,MAAM,CAAC,SAAS;GAChB,SAAS,CAAC,SAAS;GACnB,OAAO;GACP,MAAM;EACR;EACA,KAAK;GAEH,UAAU;IAAE,MAAM;IAAc,MAAM;GAAK;GAC3C,UAAU;IAAE,MAAM;IAAoB,MAAM;GAAK;GACjD,MAAM,CAAC,eAAe;GACtB,OAAO;EACT;EACA,MAAM;GACJ,UAAU;IAAE,MAAM;IAAe,MAAM;GAAK;GAC5C,UAAU;IAAE,MAAM;IAAoB,MAAM;GAAK;GACjD,MAAM,CAAC,SAAS;GAChB,OAAO;GACP,MAAM;EACR;EACA,eAAe;GACb,UAAU;IAAE,MAAM;IAAwB,MAAM;GAAK;GACrD,UAAU;IAAE,MAAM;IAAoB,MAAM;GAAK;GACjD,MAAM,CAAC,SAAS;GAChB,OAAO;GACP,MAAM;EACR;EACA,OAAO;GACL,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,UAAU;IAAE,MAAM;IAAoB,MAAM;GAAK;GACjD,MAAM,CAAC,UAAU;GACjB,OAAO;GACP,MAAM;EACR;EACA,UAAU;GAER,UAAU;IAAE,MAAM;IAA2C,MAAM;GAAK;GACxE,UAAU;IAAE,MAAM;IAAoB,MAAM;GAAK;GACjD,MAAM,CAAC,aAAa;GACpB,SAAS,CAAC,YAAY,cAAc;GACpC,OAAO;GACP,MAAM;EACR;EACA,QAAQ;GAEN,UAAU;IAAE,OAAO;IAAG,MAAM;GAAK;GACjC,UAAU;IAAE,MAAM;IAAkB,MAAM;GAAK;GAC/C,MAAM,CAAC,aAAa;GACpB,OAAO;GACP,MAAM;EACR;EACA,OAAO;GACL,UAAU;IAAE,MAAM;IAAwB,MAAM;GAAK;GACrD,MAAM,CAAC,aAAa;GACpB,OAAO;GACP,MAAM;EACR;EACA,WAAW;GACT,UAAU;IAAE,MAAM;IAAoB,MAAM;GAAK;GACjD,UAAU;IAAE,MAAM;IAAoB,MAAM;GAAK;GACjD,MAAM,CAAC,oBAAoB;GAC3B,SAAS,CAAC,gBAAgB;GAC1B,OAAO;GACP,MAAM;EACR;EACA,QAAQ;GACN,UAAU;IAAE,MAAM;IAA0B,MAAM;GAAK;GACvD,UAAU;IAAE,MAAM;IAAoB,MAAM;GAAK;GACjD,MAAM,CAAC,gBAAgB;GACvB,SAAS,CAAC,sBAAsB;GAChC,OAAO;GACP,MAAM;EACR;EACA,SAAS;GAEP,UAAU;IAAE,MAAM;IAAsB,MAAM;GAAK;GACnD,MAAM,CAAC,gBAAgB;GACvB,OAAO;GACP,MAAM;EACR;EACA,cAAc;GAEZ,UAAU;IAAE,MAAM;IAAkD,MAAM;GAAK;GAC/E,UAAU;IAAE,MAAM;IAAoB,MAAM;GAAK;GACjD,MAAM,CAAC,SAAS;GAChB,SAAS,CAAC,SAAS;GACnB,OAAO;EACT;CACF;CACA,aAAa;EACX;GAAE,IAAI;GAAS,MAAM;GAAM,IAAI;GAAS,IAAI;GAAoB,OAAO;GAAc,OAAO,CAAC,QAAQ;GAAG,QAAQ;EAAuB;EACvI;GAAE,IAAI;GAAe,MAAM;GAAS,IAAI;GAAM,IAAI;GAAW,OAAO,CAAC,QAAQ;GAAG,QAAQ;EAAuB;EAC/G;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO,CAAC,QAAQ;GAChB,OAAO;GACP,QAAQ;EACV;EACA;GAAE,IAAI;GAAe,MAAM;GAAS,IAAI;GAAM,IAAI;GAAW,OAAO,CAAC,UAAU,QAAQ;EAAE;EACzF;GAAE,IAAI;GAAS,MAAM;GAAS,IAAI;GAAc,IAAI;GAAe,OAAO,CAAC,cAAc,eAAe;GAAG,QAAQ;EAAuB;EAC1I;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO,CAAC,cAAc,eAAe;GACrC,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI,CAAC,YAAY,cAAc;GAC/B,OAAO,CAAC,mBAAmB,8BAA8B;GACzD,OAAO;GACP,QAAQ;EACV;EACA;GAAE,IAAI;GAAe,MAAM;GAAc,IAAI;GAAS,IAAI;GAAkB,OAAO;GAAY,OAAO,CAAC,6BAA6B;EAAE;EACtI;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO,CAAC,mBAAmB,oCAAoC;GAC/D,OAAO;GACP,QAAQ;EACV;EACA;GAAE,IAAI;GAAc,MAAM;GAAkB,IAAI;GAAS,IAAI;GAAoB,OAAO,CAAC,+BAA+B;EAAE;EAC1H;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO,CAAC,gCAAgC;GACxC,OAAO;GACP,QAAQ;EACV;EACA;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,OAAO,CAAC,mBAAmB,+BAA+B;GAC1D,MAAM;GACN,QAAQ;EACV;EACA;GAAE,IAAI;GAAqB,MAAM;GAAkB,IAAI;GAAS,IAAI;GAAmB,OAAO;GAAa,OAAO,CAAC,+BAA+B;EAAE;EACpJ;GACE,IAAI;GACJ,MAAM;GACN,IAAI;GACJ,IAAI,CAAC,wBAAwB,cAAc;GAC3C,OAAO,CAAC,eAAe;GACvB,QAAQ;EACV;EACA;GAAE,IAAI;GAAU,MAAM;GAAiB,IAAI;GAAM,IAAI;GAAgB,OAAO,CAAC,gBAAgB;GAAG,QAAQ;EAAuB;EAC/H;GACE,IAAI;GACJ,MAAM;IAAC;IAAM;IAAS;GAAO;GAC7B,IAAI;GACJ,IAAI;GACJ,OAAO,CAAC,uBAAuB,gBAAgB;GAC/C,MAAM;GACN,QAAQ;EACV;CACF;AACF,CAAC;;;;ACtOD,MAAM,QAAQ,cAAqE;CACjF,MAAM,MAA+B,CAAC;CACtC,KAAK,MAAM,YAAY,WAAW;EAChC,IAAI,IAAI,SAAS,QAAQ,KAAA,GAAW,MAAM,IAAI,MAAM,6CAA6C,SAAS,IAAI;EAC9G,IAAI,SAAS,MAAM;CACrB;CACA,OAAO,OAAO,OAAO,GAAG;AAC1B;;;;;AAMA,MAAa,WAA8C,KAAK;CAC9D;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC"}
|