@@ -4,17 +4,20 @@ import (
4
4
"io"
5
5
"net/http"
6
6
"sync"
7
+ "time"
7
8
)
8
9
9
10
// Client wraps an http connection and converts it to an
10
11
// event stream.
11
12
type Client struct {
12
- flush http.Flusher
13
- write io.Writer
14
- close http.CloseNotifier
15
- events chan * Event
16
- closed bool
17
- waiter sync.WaitGroup
13
+ flush http.Flusher
14
+ write io.Writer
15
+ close http.CloseNotifier
16
+ events chan * Event
17
+ closed bool
18
+ waiter sync.WaitGroup
19
+ lastFlush time.Time
20
+ lastWrite time.Time
18
21
}
19
22
20
23
// NewClient creates a client wrapping a response writer.
@@ -26,7 +29,7 @@ type Client struct {
26
29
// Returns nil on error.
27
30
func NewClient (w http.ResponseWriter , req * http.Request ) * Client {
28
31
c := & Client {
29
- events : make (chan * Event , 1 ),
32
+ events : make (chan * Event , 100 ),
30
33
write : w ,
31
34
}
32
35
@@ -55,6 +58,7 @@ func NewClient(w http.ResponseWriter, req *http.Request) *Client {
55
58
// start the sending thread
56
59
c .waiter .Add (1 )
57
60
go c .run ()
61
+ go c .flusher ()
58
62
return c
59
63
}
60
64
@@ -84,7 +88,6 @@ func (c *Client) Wait() {
84
88
85
89
// Worker thread for the client responsible for writing events
86
90
func (c * Client ) run () {
87
-
88
91
for {
89
92
select {
90
93
case ev , ok := <- c .events :
@@ -97,13 +100,28 @@ func (c *Client) run() {
97
100
98
101
// send the event
99
102
io .Copy (c .write , ev )
100
- c .flush . Flush ()
103
+ c .lastWrite = time . Now ()
101
104
102
- case _ = <- c .close .CloseNotify ():
105
+ case <- c .close .CloseNotify ():
103
106
c .closed = true
104
107
c .waiter .Done ()
105
108
return
106
109
}
107
110
108
111
}
109
112
}
113
+
114
+ // flusher amortizes flushing costs for high activity SSE channels
115
+ func (c * Client ) flusher () {
116
+ ticker := time .NewTicker (100 * time .Millisecond )
117
+
118
+ for ! c .closed {
119
+ <- ticker .C
120
+ if c .lastFlush .Before (c .lastWrite ) {
121
+ c .lastFlush = c .lastWrite
122
+ c .flush .Flush ()
123
+ }
124
+ }
125
+
126
+ ticker .Stop ()
127
+ }
0 commit comments