Don't pass a reused bytes.Buffer to the ES client #162
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
See comments.
Directly passing a reusable bytes.Buffer is unsafe because of potential race condition on error scenarios introduced by the underlying RoundTripper implementation.
See:
https://pkg.go.dev/net/http#RoundTripper
We don't need a full copy of the buffer underlying slice since the sending goroutine is only reading from the buffer. We just need to make sure that
bytes.Buffer
other member variables aren't accessed and modified concurrently by different goroutines.The call to
bytes.NewBuffer(b.buf.Bytes())
mimics what's done internally by thenet/http
library (and other implementations) on every retry: https://github.com/golang/go/blob/08e73e61521d7b83198407211aa232ed4f572f18/src/net/http/request.go#L929 - that is, taking the underlying byte slice and wrapping it in a brand new bytes.Buffer prior to any retry.Note that
GetBody
is generally not invoked on the first try of a request, which means the original request body is directly read from. Prior to this PR,b.buf
could be directly read from even after the call toreq.Do
returned.Related: golang/go#51907