Closed dillonstreator closed 2 years ago
It has a performance hit, that's why we don't want to do it by default.
https://github.com/GetStream/stream-chat-go/releases/tag/v5.0.0 and above has good defaults to handle it and if really needed, you can override the client as you wish https://github.com/GetStream/stream-chat-go/commit/328e7677ac5c32496c7cedaf7ca51e8fcf2dbed3#diff-4b667feae66c9d46b21b9ecc19e8958cf4472d162ce0a47ac3e8386af8bbd8cfR95
@ferhatelmas and @DillonStreator
I am experiencing a similar issue, when updating chat channels using batch tasks.
In order to avoid hitting API Rate Limits I created a sort of timed-barrier which allows any task to proceed only if api rate limit has not been reached, otherwise the task will wait until a timer has expired.
It works but when the batch following the first proceeds, all the calls end unexpectedly with
https://chat.stream-io-api.com/channels?api_key=API_KEY
--> unexpected EOF
I tried increasing the HTTP client timeout via the env variable STREAM_CHAT_TIMEOUT, but it does not change anything. Can you suggest me how to deal with that or point me to any example. The official doc does not seem to be very consistent with this specific issue.
@sw360cab My solution was to roll a custom http client and wrap the transport to intercept the request and set the Close
property to true. The performance hit of not keeping the connection open is not a concern for my implementation.
This is our custom http client with the transport wrapping.
import (
httptrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/net/http"
)
func ...() {
httpClient := &http.Client{
Timeout: 30 * time.Second,
// default transport options from https://go.dev/src/net/http/transport.go
// don't use http.DefaultTransport as we don't want to set req.Close for every other request that uses the default transport
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
}
httpClient.Transport = httptrace.WrapRoundTripper(httpClient.Transport, []httptrace.RoundTripperOption{
httptrace.WithBefore(func(req *http.Request, span ddtrace.Span) {
// ensure the connection is closed after request ends to prevent EOF errors
// https://github.com/GetStream/stream-chat-go/issues/217
req.Close = true
span.SetTag(ext.ServiceName, "our-service-name")
span.SetTag(ext.SpanType, ext.SpanTypeHTTP)
span.SetTag(ext.HTTPMethod, req.Method)
span.SetTag(ext.HTTPURL, req.URL.Path)
}),
}...)
streamClient.SetClient(httpClient)
return streamClient
}
wrapping the transport was pretty easy with the httptrace.WrapRoundTripper
and httptrace.WithBefore
helper methods from gopkg.in/DataDog/dd-trace-go.v1/contrib/net/http
since we wanted to configure datadog tracing anyway.
Getting the error
unexpected EOF
when making successive calls.I believe the open connection is being reused and is unexpectedly being closed by stream. We probably want to set the
Close
boolean to true when creating the request. https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/net/http/request.go;l=208-218