refactor: move request-compression out of codegen, avoid some buffering (#118)

This commit is contained in:
Daniel Moran
2021-06-11 16:01:34 -04:00
committed by GitHub
parent a1f8e0edf1
commit b1ba53bae2
8 changed files with 202 additions and 149 deletions

47
pkg/gzip/pipe.go Normal file
View File

@ -0,0 +1,47 @@
package gzip
import (
"compress/gzip"
"io"
)
var _ io.ReadCloser = (*gzipPipe)(nil)
type gzipPipe struct {
underlying io.ReadCloser
pipeOut io.ReadCloser
}
// NewGzipPipe returns an io.ReadCloser that wraps an input data stream,
// applying gzip compression to the underlying data on Read and closing the
// underlying data on Close.
func NewGzipPipe(in io.ReadCloser) *gzipPipe {
pr, pw := io.Pipe()
gw := gzip.NewWriter(pw)
go func() {
_, err := io.Copy(gw, in)
gw.Close()
if err != nil {
pw.CloseWithError(err)
} else {
pw.Close()
}
}()
return &gzipPipe{underlying: in, pipeOut: pr}
}
func (gzp gzipPipe) Read(p []byte) (int, error) {
return gzp.pipeOut.Read(p)
}
func (gzp gzipPipe) Close() error {
if err := gzp.pipeOut.Close(); err != nil {
return err
}
if err := gzp.underlying.Close(); err != nil {
return err
}
return nil
}

66
pkg/gzip/pipe_test.go Normal file
View File

@ -0,0 +1,66 @@
package gzip_test
import (
"bytes"
"compress/gzip"
"errors"
"io"
"io/ioutil"
"strings"
"testing"
pgzip "github.com/influxdata/influx-cli/v2/pkg/gzip"
"github.com/stretchr/testify/require"
)
func TestGzipPipe(t *testing.T) {
t.Parallel()
t.Run("success", func(t *testing.T) {
t.Parallel()
data := strings.Repeat("Data data I'm some data\n", 1024)
reader := strings.NewReader(data)
pipe := pgzip.NewGzipPipe(ioutil.NopCloser(reader))
defer pipe.Close()
gunzip, err := gzip.NewReader(pipe)
require.NoError(t, err)
defer gunzip.Close()
out := bytes.Buffer{}
_, err = io.Copy(&out, gunzip)
require.NoError(t, err)
require.Equal(t, data, out.String())
})
t.Run("error", func(t *testing.T) {
t.Parallel()
reader := &failingReader{n: 3, err: errors.New("I BROKE")}
pipe := pgzip.NewGzipPipe(ioutil.NopCloser(reader))
defer pipe.Close()
gunzip, err := gzip.NewReader(pipe)
require.NoError(t, err)
defer gunzip.Close()
out := bytes.Buffer{}
_, err = io.Copy(&out, gunzip)
require.Error(t, err)
require.Equal(t, reader.err, err)
})
}
type failingReader struct {
n int
err error
}
func (frc *failingReader) Read(p []byte) (int, error) {
if frc.n <= 0 {
return 0, frc.err
}
frc.n--
p[0] = 'a'
return 1, nil
}