@@ -14,6 +14,7 @@ var StreamNotFoundErr = errors.New("stream not found")
14
14
15
15
// TricklePublisher represents a trickle streaming client
16
16
type TricklePublisher struct {
17
+ client * http.Client
17
18
baseURL string
18
19
index int // Current index for segments
19
20
writeLock sync.Mutex // Mutex to manage concurrent access
@@ -47,6 +48,7 @@ func NewTricklePublisher(url string) (*TricklePublisher, error) {
47
48
c := & TricklePublisher {
48
49
baseURL : url ,
49
50
contentType : "video/MP2T" ,
51
+ client : httpClient (),
50
52
}
51
53
p , err := c .preconnect ()
52
54
if err != nil {
@@ -76,13 +78,7 @@ func (c *TricklePublisher) preconnect() (*pendingPost, error) {
76
78
77
79
// Start the POST request in a background goroutine
78
80
go func () {
79
- // Createa new client to prevent connection reuse
80
- client := http.Client {Transport : & http.Transport {
81
- DisableKeepAlives : true ,
82
- // ignore orch certs for now
83
- TLSClientConfig : & tls.Config {InsecureSkipVerify : true },
84
- }}
85
- resp , err := client .Do (req )
81
+ resp , err := c .client .Do (req )
86
82
if err != nil {
87
83
slog .Error ("Failed to complete POST for segment" , "url" , url , "err" , err )
88
84
errCh <- err
@@ -126,11 +122,8 @@ func (c *TricklePublisher) Close() error {
126
122
if err != nil {
127
123
return err
128
124
}
129
- resp , err := (& http.Client {Transport : & http.Transport {
130
- DisableKeepAlives : true ,
131
- // ignore orch certs for now
132
- TLSClientConfig : & tls.Config {InsecureSkipVerify : true },
133
- }}).Do (req )
125
+ // Use a new client for a fresh connection
126
+ resp , err := httpClient ().Do (req )
134
127
if err != nil {
135
128
return err
136
129
}
@@ -174,11 +167,12 @@ func (p *pendingPost) reconnect() (*pendingPost, error) {
174
167
// Set the publisher's sequence sequence to the intended reconnect
175
168
// Call publisher's preconnect (which increments its sequence)
176
169
// then reset publisher's sequence back to the original
177
- //slog.Info("Re-connecting", "url", p.client.baseURL, "seq", p. client.index)
170
+ // Also recreate the client to force a fresh connection
178
171
p .client .writeLock .Lock ()
179
172
defer p .client .writeLock .Unlock ()
180
173
currentSeq := p .client .index
181
174
p .client .index = p .index
175
+ p .client .client = httpClient ()
182
176
pp , err := p .client .preconnect ()
183
177
p .client .index = currentSeq
184
178
return pp , err
@@ -261,11 +255,10 @@ func (p *pendingPost) Close() error {
261
255
if err != nil {
262
256
return err
263
257
}
264
- resp , err := (& http.Client {Transport : & http.Transport {
265
- DisableKeepAlives : true ,
266
- // ignore orch certs for now
267
- TLSClientConfig : & tls.Config {InsecureSkipVerify : true },
268
- }}).Do (req )
258
+ // Since this method typically gets invoked when
259
+ // there is a problem sending the segment, use a
260
+ // new client for a fresh connection just in case
261
+ resp , err := httpClient ().Do (req )
269
262
if err != nil {
270
263
return err
271
264
}
@@ -287,6 +280,15 @@ func (c *TricklePublisher) Write(data io.Reader) error {
287
280
return err
288
281
}
289
282
283
+ func httpClient () * http.Client {
284
+ return & http.Client {Transport : & http.Transport {
285
+ // Re-enable keepalives to avoid connection pooling
286
+ // DisableKeepAlives: true,
287
+ // ignore orch certs for now
288
+ TLSClientConfig : & tls.Config {InsecureSkipVerify : true },
289
+ }}
290
+ }
291
+
290
292
func humanBytes (bytes int64 ) string {
291
293
var unit int64 = 1024
292
294
if bytes < unit {
0 commit comments