Skip to content

Commit 496ec6c

Browse files
authored
fix: add read call to derp-map endpoint to avoid ws ping timeout (#8859)
1 parent 75fcc24 commit 496ec6c

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

coderd/workspaceagents.go

+31
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"errors"
99
"flag"
1010
"fmt"
11+
"io"
1112
"net"
1213
"net/http"
1314
"net/netip"
@@ -851,6 +852,36 @@ func (api *API) derpMapUpdates(rw http.ResponseWriter, r *http.Request) {
851852
nconn := websocket.NetConn(ctx, ws, websocket.MessageBinary)
852853
defer nconn.Close()
853854

855+
// Slurp all packets from the connection into io.Discard so pongs get sent
856+
// by the websocket package.
857+
go func() {
858+
_, _ = io.Copy(io.Discard, nconn)
859+
}()
860+
861+
go func(ctx context.Context) {
862+
// TODO(mafredri): Is this too frequent? Use separate ping disconnect timeout?
863+
t := time.NewTicker(api.AgentConnectionUpdateFrequency)
864+
defer t.Stop()
865+
866+
for {
867+
select {
868+
case <-t.C:
869+
case <-ctx.Done():
870+
return
871+
}
872+
873+
// We don't need a context that times out here because the ping will
874+
// eventually go through. If the context times out, then other
875+
// websocket read operations will receive an error, obfuscating the
876+
// actual problem.
877+
err := ws.Ping(ctx)
878+
if err != nil {
879+
_ = ws.Close(websocket.StatusInternalError, err.Error())
880+
return
881+
}
882+
}
883+
}(ctx)
884+
854885
ticker := time.NewTicker(api.Options.DERPMapUpdateFrequency)
855886
defer ticker.Stop()
856887

0 commit comments

Comments
 (0)