Skip to content

relay: the invite-mint-plus-CLOSE combination is covered by no test at the wire #983

Open

Description

@chappie-daemon

The invite EVENT plus CLOSE mid-mint, over a socket combination is now covered by no test in the repository, and the only record of that is in a job folder that .git/info/exclude keeps out of every tree.

How the gap arose

a_close_during_the_invite_mint_leaves_the_event_but_not_the_read used to exercise that combination at the wire. It synchronised the CLOSE against the invite mint with a fixed 50 ms sleep, which made a correct fix go red under load (#963), and the test-only fix was to move it down to the handler level: it now owns a Connection and calls unsubscribe::handle directly, ordering the abort before the gate release by program order. That closed the flake and cost the wire path.

What carries what now (verified, not assumed)

piece covered by
decode of ["CLOSE","invite"], the connection loop, the AUTH exchange wire tests (wire_parity, transport)
invite EVENT minted before EOSE an_invite_request_mints_one_kind_28935_event_before_eose — no CLOSE
CLOSE aborting a gated read a_close_aborts_an_in_flight_read_without_a_frame — see #982, it passes under the delay it exists to catch
mint + CLOSE mid-mint over a socket nothing

wire_parity's 16 recorded sessions contain invite-mint (no CLOSE) and req-close-abort (CLOSE after the read has ended), and the replay has no gate, so it cannot hold a read open across a CLOSE.

What closing it needs

Shape B from #963's spec: the relay publishes its per-connection registry (relay.rs:291-297), a Server accessor exposes it, and the wire test polls read_in_flight between sending the CLOSE and releasing the gate. That is production source at five Relay::new call sites, one of them nostreamd/src/main.rs:111 — which is why it was not done inside a $1.20 test-only job.

Found while fixing #963 on branch factory/014-close-mint-sync (base rewrite/main @ 2b2287f).

Activity

  1. added
    bugSomething isn't working
    rewritenostream 4.0 Rust/LMDB rewrite
    rustRust implementation work
    factoryBuilt by the software factory
    on Oct 25, 2026
  2. chappie-daemon commented on Oct 25, 2026

    @chappie-daemon
    CollaboratorAuthor

    Why the wire-level test was the wrong instrument, not merely an expensive one (recorded here so the next reader learns it from the issue rather than inferring that the wire path vanished):

    Once #978 made CLOSE a prefix, handlers::begin runs the whole handler on the connection loop before the next frame is read. A wire-level test that waits for wall-clock time is therefore testing a property the code guarantees by construction, and a timer cannot tell you whether the prefix ran — it can only tell you whether 50 ms was long enough. That is why #963's test moved to the handler level rather than getting a better tolerance, and why the remaining gap is a coverage gap, not a timing one.

    What a wire test for this combination would need: the relay publishes its per-connection registry (as it already does internally via read_in_flight), a wire test polls it between the CLOSE and the release of the mint, and the assertion attributes each frame to the subscription whose read produced it. That is production source at five Relay::new sites, which is why it is its own job.

    Until then the handler-level test asserts both halves (the invite EVENT is stored, read_in_flight("invite") is false before the release) and its comment names this issue and the sibling wire test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfactoryBuilt by the software factoryrewritenostream 4.0 Rust/LMDB rewriterustRust implementation work

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions