@@ -10,6 +10,8 @@ import (
1010 "github.com/andyrewlee/amux/internal/safego"
1111)
1212
13+ const ptyIdleHeartbeatInterval = time .Second
14+
1315// PTYReaderConfig configures the shared PTY read loop.
1416type PTYReaderConfig struct {
1517 Label string // safego goroutine label
@@ -79,8 +81,30 @@ func RunPTYReader(
7981 }
8082 })
8183
82- ticker := time .NewTicker (cfg .FrameInterval )
83- defer ticker .Stop ()
84+ heartbeatTicker := time .NewTicker (ptyIdleHeartbeatInterval )
85+ defer heartbeatTicker .Stop ()
86+ var flushTicker * time.Ticker
87+ var flushTick <- chan time.Time
88+ startFlushTicker := func () {
89+ if flushTicker != nil {
90+ return
91+ }
92+ flushInterval := cfg .FrameInterval
93+ if flushInterval <= 0 {
94+ flushInterval = 40 * time .Millisecond
95+ }
96+ flushTicker = time .NewTicker (flushInterval )
97+ flushTick = flushTicker .C
98+ }
99+ stopFlushTicker := func () {
100+ if flushTicker == nil {
101+ return
102+ }
103+ flushTicker .Stop ()
104+ flushTicker = nil
105+ flushTick = nil
106+ }
107+ defer stopFlushTicker ()
84108
85109 var pending []byte
86110 var stoppedErr error
@@ -110,14 +134,23 @@ func RunPTYReader(
110134 return
111135 }
112136 pending = append (pending , data ... )
137+ startFlushTicker ()
113138 if len (pending ) >= cfg .MaxPendingBytes {
114139 if ! SendPTYMsg (msgCh , cancel , factory .Output (pending )) {
115140 close (msgCh )
116141 return
117142 }
118143 pending = nil
144+ if stoppedErr == nil {
145+ stopFlushTicker ()
146+ }
147+ }
148+ if stoppedErr != nil && len (pending ) == 0 {
149+ SendPTYMsg (msgCh , cancel , factory .Stopped (stoppedErr ))
150+ close (msgCh )
151+ return
119152 }
120- case <- ticker . C :
153+ case <- flushTick :
121154 beat ()
122155 if len (pending ) > 0 {
123156 if ! SendPTYMsg (msgCh , cancel , factory .Output (pending )) {
@@ -126,11 +159,16 @@ func RunPTYReader(
126159 }
127160 pending = nil
128161 }
162+ if len (pending ) == 0 {
163+ stopFlushTicker ()
164+ }
129165 if stoppedErr != nil {
130166 SendPTYMsg (msgCh , cancel , factory .Stopped (stoppedErr ))
131167 close (msgCh )
132168 return
133169 }
170+ case <- heartbeatTicker .C :
171+ beat ()
134172 }
135173 }
136174}
0 commit comments