@@ -6,22 +6,36 @@ import (
66 "log/slog"
77 "math"
88 "syscall"
9- "time"
109
1110 "code.selman.me/hauntty/internal/config"
1211 "code.selman.me/hauntty/internal/protocol"
1312 "github.com/creack/pty"
1413)
1514
16- const (
17- sessionClientOutBufferSize = 256
18- slowClientGracePeriod = 100 * time .Millisecond
19- )
15+ const sessionClientOutBufferSize = 256
2016
2117func (c * sessionClient ) writeLoop () {
18+ defer func () {
19+ close (c .writeDone )
20+ select {
21+ case c .ready <- struct {}{}:
22+ default :
23+ }
24+ }()
25+
2226 for msg := range c .outCh {
27+ select {
28+ case c .ready <- struct {}{}:
29+ default :
30+ }
2331 if err := c .conn .WriteMessage (msg ); err != nil {
24- break
32+ _ = c .closeConn ()
33+ return
34+ }
35+ }
36+ if c .final != nil {
37+ if err := c .conn .WriteMessage (c .final ); err != nil {
38+ _ = c .closeConn ()
2539 }
2640 }
2741}
@@ -169,32 +183,37 @@ func removeClient(clients []*sessionClient, target *sessionClient) []*sessionCli
169183 return clients
170184}
171185
172- func broadcastOutput (clients []* sessionClient , name string , msg * protocol.Output ) []* sessionClient {
173- i := 0
186+ func queueOutput (clients []* sessionClient , msg * protocol.Output ) []* sessionClient {
187+ var pending [] * sessionClient
174188 for _ , c := range clients {
175189 select {
176- case c .outCh <- msg :
177- clients [i ] = c
178- i ++
190+ case <- c .writeDone :
179191 continue
180192 default :
181193 }
182-
183- timer := time .NewTimer (slowClientGracePeriod )
184194 select {
185195 case c .outCh <- msg :
186- if ! timer .Stop () {
187- <- timer .C
188- }
189- clients [i ] = c
190- i ++
191- case <- timer .C :
192- slog .Debug ("evicting slow client" , "session" , name , "grace" , slowClientGracePeriod )
196+ default :
197+ pending = append (pending , c )
198+ }
199+ }
200+ return pending
201+ }
202+
203+ func pruneFinishedClients (clients , pending []* sessionClient ) ([]* sessionClient , []* sessionClient , bool ) {
204+ kept := clients [:0 ]
205+ changed := false
206+ for _ , c := range clients {
207+ select {
208+ case <- c .writeDone :
209+ pending = removeClient (pending , c )
193210 close (c .outCh )
194- _ = c .closeConn ()
211+ changed = true
212+ default :
213+ kept = append (kept , c )
195214 }
196215 }
197- return clients [: i ]
216+ return kept , pending , changed
198217}
199218
200219func notifyClientsChanged (clients []* sessionClient , sizeFn func () (uint16 , uint16 )) {
0 commit comments