fix(connection): make shutdown() idempotent with sync.Once (#1698)
txtop#287 reports `panic: close of closed channel` in Connection.shutdown at `close(c.connClosedChan)` when running against a local cardano-node in Docker. shutdown is invoked from exactly one goroutine spawned in setupConnection, but setupConnection's own error paths (muxer-error goroutine -> Close -> doneChan trigger during a partially-initialised connection) and tests that close the underlying net.Conn out from under the library have driven the cleanup into shutdown a second time, which panics on the connClosedChan/errorChan closes. Wrap the cleanup in sync.Once so subsequent calls are no-ops. Close() already uses sync.Once for the doneChan close; adding a symmetric guard on the cleanup side keeps the contract simple: Connection cleanup runs exactly once regardless of who triggers it. Signed-off-by: SAY-5 <[email protected]> Co-authored-by: SAY-5 <[email protected]>