network: socket options (TCP_NODELAY, keepalive) #120
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Long-lived database connections: a dead peer is noticed only by keepalive. Listed among what
stdis missing for thefirst-party packages.
TCP_NODELAYis already on for every stream (docs/design/NETWORK.mdsection 4); what is missingis a way to switch it and to turn TCP keepalive on, with its timings.
Source
docs/design/NETWORK.mdsection 4: the setter forTCP_NODELAYand the socket options are named there as lateradditions, each when a program needs it.
Design (decided by the loop)
This is an epic of two steps, because the change needs a new native and the seed that builds the compiler compiles
std/network(compiler/src/debugger/adapter.trbimports it): the two-commit rule of CLAUDE.md applies, and the secondcommit cannot bootstrap until the published seed knows the natives.
std/network, onTcpStreamonly. UDP options and listener options stay later additions.fn setNoDelay(enabled: Bool): Result<Void, NetworkError>andfn setKeepAlive(idle: Duration?, interval: Duration? = None, count: Int? = None): Result<Void, NetworkError>:Noneforidleturns keepalive off,Some(idle)turns it on, and the two other parameters set the probe spacingand count where given (whole seconds, at least 1; a smaller
Durationis rounded up, zero is refused). Plus thereads
fn noDelay(): Result<Bool, NetworkError>andfn keepAlive(): Result<Duration?, NetworkError>. Defaults stay:TCP_NODELAYon, keepalive off.networkSetOptionandnetworkOption, with the option as a number.Steps
feat(runtime): ...): #426, landed (PR #427)std/networkAPI onTcpStream, tests, docs (docs/standard-library/network.md, NETWORK.md section 4, thegenerated
skills/) and FIRST-PARTY.md gap 22 marked done. Commitfeat(network): TcpStream.setNoDelay and setKeepAlive: #473 (filed once the published seedc4a8443532aaknew the natives).Acceptance criteria (of the epic)
TcpStream, tested instd/networkagainst a loopbackconnection (set, read back, a closed stream fails with
isClosed()), natively and in the VMDependencies
None known; the steps depend on each other as listed.
Moved from the planning lists of the docs; the design record stays the specification.
[loop:torbscript] intake: in scope (author orion, label loop), source FIRST-PARTY.md gap 22, not a duplicate. No dependencies. next: waiting (refine queued, ready buffer full) until 2026-10-10T04:00:00Z
[loop:torbscript] claim refine by session:loop-torbscript-20261023 until 2026-10-23T14:56Z
[loop:torbscript] decided by the loop: #120 is an epic of two steps, not one PR. Why:
TCP_NODELAYis already on (NETWORK.md section 4) and only needs a setter, but keepalive needs a new native, and the compiler importsstd/network(compiler/src/debugger/adapter.trb), so the seed compiles it: the two-commit rule of CLAUDE.md applies and a PR with the native and thestd/API together cannot bootstrap before the published seed knows the native. Packagestd/network, onTcpStreamonly; methods (setNoDelay,setKeepAlive(idle:, interval:, count:)plus two readers), defaults unchanged; one native pairnetworkSetOption/networkOptionwith the option as a number, so a later option costs no manifest entry; no sandbox change (an option of an open socket is no new capability). Details are in the rewritten body.Refine result: no duplicate in the open issues (keyword search: keepalive, nodelay, socket option). First step filed as #426 (runtime natives, touches the seed: yes, label
loopandready) and linked in the checklist. Step 2 (thestd/networkAPI, tests, docs, gap 22 done) is filed just in time once step 1 has landed and the published seed knows the natives. The seed refresh stays Torben's/the merge gate's. #120 stays withoutready.Refine worker usage: roughly 85k tokens (estimate, sonnet).
next: waiting (epic waits on its steps)
[loop:torbscript] claim refine by session:loop-torbscript-20261025 until 2026-10-24T24:00:00Z
[loop:torbscript] decided by the loop: step 1 (#426, the natives
networkSetOption/networkOption) landed with PR #427, so the first step of the earlier brief (aTCP_NODELAYsetter without a native) is moot: the native pair serves every option, and the setter and keepalive belong in onestd/commit. Step 2 starts next and is filed just in time as #473 (labelloopandready):TcpStream.setNoDelay/noDelay/setKeepAlive/keepAlive, one commitfeat(network): TcpStream.setNoDelay and setKeepAlive. Why one step and not two: both halves are a few lines over the same two natives and the same tests, far below the ~1 h of an issue of its own. Seed: the published seedc4a8443532aa(2026-10-24) was built from a commit after the natives landed, so this is the safe second commit of the two-commit rule andstd/networkcan use them; no further seed change. No duplicate found (keywords: keepalive, nodelay, socket option, TcpStream). Owner-reserved matters: none (no new capability, no public contract with users, no cost). The checklist above links #473.[loop:torbscript] refine: checked #120 against main, NETWORK.md section 4, FIRST-PARTY.md gap 22 and the published seeds. Step 1 (#426) had already landed (PR #427) and the published seed knows its natives, so no first step was filed; step 2 is now filed as #473 with label
loopandready(goal, testable acceptance criteria, design record point, seed impact: none further, size: one commit). The epic checklist is updated; #120 stays withoutready. next: waiting (epic waits on step 2, #473 is ready for implement). Refine worker usage: roughly 70k tokens (estimate, sonnet).[loop:torbscript] close: both steps landed (#426 via PR 427, #473 via PR 477, merge commit
9bc0ec86f3on main), FIRST-PARTY.md gap 22 is marked done on main, main CI green. Epic checklist ticked, closing. next: closed