Add lightweight write deadlines to Conn
- Langage dominant
- Go
- Étoiles
- 5.5k
- Forks
- 376
- Métriques de merge des PR
- Aucune PR mergée en 30 j
Description
### Problem
Long-lived WebSocket servers often need every outbound write to be bounded. With `v1.8.15`, the main API requires creating a deadline context for every message:
```go
package main
import (
"context"
"log"
"net/http"
"time"
"github.com/coder/websocket"
)
func main() {
http.HandleFunc("/", serve)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func serve(w http.ResponseWriter, r *http.Request) {
c, err := websocket.Accept(w, r, nil)
if err != nil {
return
}
defer c.CloseNow()
connCtx := c.CloseRead(r.Context())
ticker := time.NewTicker(10 * time.Millisecond)
defer ticker.Stop()
for {
select {
case <-connCtx.Done():
return
case <-ticker.C:
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
err := c.Write(ctx, websocket.MessageText, []byte(`{"type":"event"}`))
cancel()
if err != nil {
return
}
}
}
}
```
Using `context.Background()` avoids the timeout-related allocations added around each frame, but also removes the bounded-write guarantee.
`websocket.NetConn` exposes `SetWriteDeadline`, but it is a full bidirectional adapter. It creates read and write contexts, timers, and locks, and calls `SetReadLimit(-1)` even when only its write side is needed.
A loopback benchmark with `v1.8.15` on Go 1.27rc2 produced:
| Strategy | Write path | Connection construction |
|---|---:|---:|
| `context.WithTimeout` | 1304 B/op, 12 allocs/op | no extra adapter |
| `NetConn.SetWriteDeadline` | 664 B/op, 5 allocs/op | 848 B, 13 allocs |
The write measurements use the same client reader, so the allocation difference is the relevant result. At high connection counts, the fixed `NetConn` cost is material.
### Request
Could `*websocket.Conn` provide a lightweight write-only deadline mechanism, for example `SetWriteDeadline(time.Time)` or an equivalent API?
Ideally it would:
- reuse connection-owned deadline state instead of allocating a timer context per write;
- bound both write-lock acquisition and the underlying write;
- preserve the current behavior where a timed-out write closes the WebSocket;
- remain safe with concurrent `Ping`, `Close`, and data writes;
- avoid creating read-side state or changing the configured read limit;
- allow zero time to clear the deadline.
Related: #252 discusses the same API direction for read deadlines.
Guide de contribution
Aucun guide de contribution indexé pour ce dépôt
Piste de recherche
Inspectez d’abord le chemin d’écriture sur *websocket.Conn et la gestion des deadlines dans websocket.NetConn, puis lisez l’issue #252 pour la direction concernant le read-deadline. Le travail est considéré comme terminé lorsqu’il existe un mécanisme de deadline réservé à l’écriture qui borne l’acquisition du lock et les écritures, préserve le comportement de fermeture en cas de timeout, reste sûr avec des opérations concurrentes, évite tout état côté lecture et est supprimé avec une durée nulle.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- go
- Domaine
- backend-api-design, networking
- Type d'issue
- Fonctionnalité
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Activité
- Calme
- Clarté
- Plutôt claire
- Accessibilité débutants
- 45/100