Tags: TomTonic/fanout
Tags
refactor: harden fan-out concurrency contract and loser cancellation An audit of the parallel fan-out confirmed there are no data races today, but one invariant was implicit and fragile. Document and defend the concurrency contract, and abort losing upstreams sooner: - Document the read-only contract on Client.Request: the same *dns.Msg is shared across all fan-out workers for a query, so implementations must treat it as read-only. Mutating it (e.g. zeroing the ID for DoH/DoQ per RFC 8484 / RFC 9250, or adding EDNS options) would be a data race and would corrupt the requests sent to the other upstreams. - The producer now evaluates Pick() into a variable before the select instead of inside the send case, so a cancellation no longer silently consumes and discards a pick, and guards against a nil Client (defensive: serverCount is clamped to <= len(clients) today). - Cancel the per-query context immediately once a result is selected, so losing upstream attempts are aborted right away instead of lingering until ServeDNS returns. cancel stays idempotent (also runs via defer) and does not override an already-set deadline cause, so the failure reason stays accurate. Tests: shared-request immutability, nil-pick safety, and prompt loser cancellation. go test -race -short and golangci-lint are clean.
PreviousNext