diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d6f4b65..bf6afe9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,10 +5,10 @@ jobs: name: check licenses runs-on: ubuntu-latest steps: - - name: Set up Go 1.14 + - name: Set up Go 1.16 uses: actions/setup-go@v1 with: - go-version: 1.14 + go-version: 1.16 id: go - name: Check out code into the Go module directory uses: actions/checkout@v1 @@ -28,10 +28,10 @@ jobs: name: tests runs-on: ubuntu-latest steps: - - name: Set up Go 1.14 + - name: Set up Go 1.16 uses: actions/setup-go@v1 with: - go-version: 1.14 + go-version: 1.16 id: go - name: Check out code into the Go module directory uses: actions/checkout@v1 diff --git a/README.md b/README.md index 9545aed..a8e31c5 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ According to the Redis Serialization Protocol ([RESP Specification](https://redi | Redigo | No | | GoRedis | No | -Neither **Redigo** nor **GoRedis** pools its buffers for reuse and allocates them on the stack per request. This becomes rather heavy on performance, especially as response sizes grow. You can see in the Get benchmarks for the three clients that **GoRedis** allocates the result no less than three times on the stack and **Redigo** allocates once. (Reference, *Get10000b* benchmark) +Neither **Redigo** nor **GoRedis** pools its buffers for reuse and allocates them on the heap per request. This becomes rather heavy on performance, especially as response sizes grow. You can see in the Get benchmarks for the three clients that **GoRedis** allocates the result no less than three times on the heap and **Redigo** allocates once. (Reference, *Get10000b* benchmark) ### Allows for zero-copy parsing of response? diff --git a/benchmarks/main_test.go b/benchmarks/main_test.go index 9881403..b1b2ae1 100644 --- a/benchmarks/main_test.go +++ b/benchmarks/main_test.go @@ -10,13 +10,11 @@ import ( "strconv" "syscall" "testing" - "time" "github.com/dropbox/godropbox/net2" goredis "github.com/go-redis/redis" redigo "github.com/gomodule/redigo/redis" "github.com/mikn/greddis" - "google.golang.org/grpc/benchmark/stats" ) func BenchmarkNetSingleBufIO(b *testing.B) { @@ -175,7 +173,6 @@ func BenchmarkRedigoSingle(b *testing.B) { func BenchmarkNetChanPool(b *testing.B) { b.ReportAllocs() - var s = stats.AddStats(b, 10) var pool = newChanPool("tcp", "localhost:6379", 10) var conn, err = pool.Get() if err != nil { @@ -187,7 +184,6 @@ func BenchmarkNetChanPool(b *testing.B) { conn.Read(bytes[:5]) pool.Put(conn) for i := 0; i < b.N; i++ { - var t = time.Now() conn, _ = pool.Get() bytes = bytes[:0] bytes = append(bytes, "get testkey\r\n"...) @@ -198,7 +194,6 @@ func BenchmarkNetChanPool(b *testing.B) { bytes = bytes[:length+2] conn.Read(bytes) pool.Put(conn) - s.Add(time.Now().Sub(t)) } conn, _ = pool.Get() conn.Write([]byte("del testkey\r\n")) @@ -207,7 +202,6 @@ func BenchmarkNetChanPool(b *testing.B) { func BenchmarkNetSyncPool(b *testing.B) { b.ReportAllocs() - var s = stats.AddStats(b, 10) var pool = newSyncPool("tcp", "localhost:6379", 10) var conn, err = pool.Get() if err != nil { @@ -219,7 +213,6 @@ func BenchmarkNetSyncPool(b *testing.B) { conn.Read(bytes[:5]) pool.Put(conn) for i := 0; i < b.N; i++ { - var t = time.Now() conn, _ = pool.Get() bytes = bytes[:0] bytes = append(bytes, "get testkey\r\n"...) @@ -230,7 +223,6 @@ func BenchmarkNetSyncPool(b *testing.B) { bytes = bytes[:length+2] conn.Read(bytes) pool.Put(conn) - s.Add(time.Now().Sub(t)) } conn, _ = pool.Get() conn.Write([]byte("del testkey\r\n")) @@ -239,7 +231,6 @@ func BenchmarkNetSyncPool(b *testing.B) { func BenchmarkNetAtomicPool(b *testing.B) { b.ReportAllocs() - var s = stats.AddStats(b, 10) var pool = newAtomicPool("tcp", "localhost:6379", 10) var conn, err = pool.Get() if err != nil { @@ -251,7 +242,6 @@ func BenchmarkNetAtomicPool(b *testing.B) { conn.Read(bytes[:5]) pool.Put(conn) for i := 0; i < b.N; i++ { - var t = time.Now() conn, _ = pool.Get() bytes = bytes[:0] bytes = append(bytes, "get testkey\r\n"...) @@ -262,7 +252,6 @@ func BenchmarkNetAtomicPool(b *testing.B) { bytes = bytes[:length+2] conn.Read(bytes) pool.Put(conn) - s.Add(time.Now().Sub(t)) } conn, _ = pool.Get() conn.Write([]byte("del testkey\r\n")) @@ -271,7 +260,6 @@ func BenchmarkNetAtomicPool(b *testing.B) { func BenchmarkNetSemPool(b *testing.B) { b.ReportAllocs() - var s = stats.AddStats(b, 10) var pool = newSemPool("tcp", "localhost:6379", 10) var conn, err = pool.Get() if err != nil { @@ -283,7 +271,6 @@ func BenchmarkNetSemPool(b *testing.B) { conn.Read(bytes[:5]) pool.Put(conn) for i := 0; i < b.N; i++ { - var t = time.Now() conn, _ = pool.Get() bytes = bytes[:0] bytes = append(bytes, "get testkey\r\n"...) @@ -294,7 +281,6 @@ func BenchmarkNetSemPool(b *testing.B) { bytes = bytes[:length+2] conn.Read(bytes) pool.Put(conn) - s.Add(time.Now().Sub(t)) } conn, _ = pool.Get() conn.Write([]byte("del testkey\r\n")) @@ -303,7 +289,6 @@ func BenchmarkNetSemPool(b *testing.B) { func BenchmarkNet2Pool(b *testing.B) { b.ReportAllocs() - var s = stats.AddStats(b, 10) var pool = net2.NewSimpleConnectionPool(net2.ConnectionOptions{ MaxActiveConnections: 10, MaxIdleConnections: 10, @@ -319,7 +304,6 @@ func BenchmarkNet2Pool(b *testing.B) { conn.Read(bytes[:5]) conn.ReleaseConnection() for i := 0; i < b.N; i++ { - var t = time.Now() conn, _ = pool.Get("tcp", "localhost:6379") bytes = bytes[:0] bytes = append(bytes, "get testkey\r\n"...) @@ -330,7 +314,6 @@ func BenchmarkNet2Pool(b *testing.B) { bytes = bytes[:length+2] conn.Read(bytes) conn.ReleaseConnection() - s.Add(time.Now().Sub(t)) } conn, _ = pool.Get("tcp", "localhost:6379") conn.Write([]byte("del testkey\r\n")) @@ -340,20 +323,17 @@ func BenchmarkNet2Pool(b *testing.B) { func greddisGet(addr string, key string, value string) func(*testing.B) { return func(b *testing.B) { b.ReportAllocs() - var s = stats.AddStats(b, 10) var ctx = context.Background() client, _ := greddis.NewClient(ctx, &greddis.PoolOptions{URL: fmt.Sprintf("tcp://%s", addr)}) client.Set(ctx, key, []byte(value), 0) var buf = &bytes.Buffer{} for i := 0; i < b.N; i++ { - var t = time.Now() var res, err = client.Get(ctx, key) if err != nil { fmt.Println(err) } res.Scan(buf) buf.Reset() - s.Add(time.Now().Sub(t)) } client.Del(ctx, key) } @@ -362,16 +342,13 @@ func greddisGet(addr string, key string, value string) func(*testing.B) { func goredisGet(addr string, key string, value string) func(*testing.B) { return func(b *testing.B) { b.ReportAllocs() - var s = stats.AddStats(b, 10) var client = goredis.NewClient(&goredis.Options{ Addr: addr, PoolSize: 10, }) client.Set(key, value, 0) for i := 0; i < b.N; i++ { - var t = time.Now() _ = client.Get(key).String() - s.Add(time.Now().Sub(t)) } client.Del(key) } @@ -380,7 +357,6 @@ func goredisGet(addr string, key string, value string) func(*testing.B) { func redigoGet(addr string, key string, value string) func(*testing.B) { return func(b *testing.B) { b.ReportAllocs() - var s = stats.AddStats(b, 10) var pool = redigo.Pool{ MaxIdle: 10, MaxActive: 10, @@ -391,12 +367,10 @@ func redigoGet(addr string, key string, value string) func(*testing.B) { conn.Close() var buf = make([][]byte, 1) for i := 0; i < b.N; i++ { - var t = time.Now() conn = pool.Get() var val, _ = redigo.Values(conn.Do("get", key)) redigo.Scan(val, &buf) conn.Close() - s.Add(time.Now().Sub(t)) buf[0] = buf[0][:0] } conn.Do("del", key) @@ -406,15 +380,12 @@ func redigoGet(addr string, key string, value string) func(*testing.B) { func greddisSet(addr string, key string, value string) func(*testing.B) { return func(b *testing.B) { b.ReportAllocs() - var s = stats.AddStats(b, 10) var ctx = context.Background() client, _ := greddis.NewClient(ctx, &greddis.PoolOptions{URL: fmt.Sprintf("tcp://%s", addr)}) var strPtr = &value //byteVal := []byte(value) for i := 0; i < b.N; i++ { - var t = time.Now() client.Set(ctx, key, strPtr, 0) - s.Add(time.Now().Sub(t)) } client.Del(ctx, key) } @@ -423,15 +394,12 @@ func greddisSet(addr string, key string, value string) func(*testing.B) { func goredisSet(addr string, key string, value string) func(*testing.B) { return func(b *testing.B) { b.ReportAllocs() - var s = stats.AddStats(b, 10) var client = goredis.NewClient(&goredis.Options{ Addr: addr, PoolSize: 10, }) for i := 0; i < b.N; i++ { - var t = time.Now() client.Set(key, value, 0) - s.Add(time.Now().Sub(t)) } client.Del(key) } @@ -440,18 +408,15 @@ func goredisSet(addr string, key string, value string) func(*testing.B) { func redigoSet(addr string, key string, value string) func(*testing.B) { return func(b *testing.B) { b.ReportAllocs() - var s = stats.AddStats(b, 10) var pool = redigo.Pool{ MaxIdle: 10, MaxActive: 10, Dial: func() (redigo.Conn, error) { return redigo.Dial("tcp", addr) }, } for i := 0; i < b.N; i++ { - var t = time.Now() var conn = pool.Get() conn.Do("set", key, value) conn.Close() - s.Add(time.Now().Sub(t)) } var conn = pool.Get() conn.Do("del", key) diff --git a/conn.go b/conn.go index d13de09..6a397b9 100644 --- a/conn.go +++ b/conn.go @@ -8,13 +8,13 @@ import ( ) type conn struct { - conn net.Conn - arrw *ArrayWriter - res *Result - r *Reader - created time.Time - toBeClosed int64 // only for use with atomics - inUse int64 // only for use with atomics + conn net.Conn + arrw *ArrayWriter + res *Result + r *Reader + created time.Time + toBeClosed int64 // only for use with atomics + inUse int64 // only for use with atomics } func newConn(c net.Conn, initBufSize int) *conn { diff --git a/errors.go b/errors.go index 0a4001a..0d26693 100644 --- a/errors.go +++ b/errors.go @@ -6,38 +6,49 @@ import ( ) // ErrRetryable is an error that can be retried +// TODO investigate if we can use e.Temporary() or some subset of that class of errors var ErrRetryable = errors.New("Temporary error, please retry!") // ErrMalformedString received expected length, but it isn't terminated properly +// TODO Find an appropriate error to sub-type here var ErrMalformedString = errors.New("Expected CRLF terminated string, but did not receive one") // ErrWrongPrefix returns when we expected a certain type prefix, but received another +// TODO Find an appropriate error to sub-type here var ErrWrongPrefix = errors.New("Wrong prefix on string") // ErrConnRead received error when reading from connection +// TODO Find an appropriate error to sub-type here var ErrConnRead = errors.New("Received error whilst reading from connection") // ErrConnWrite error when writing to connection +// TODO Find an appropriate error to sub-type here var ErrConnWrite = errors.New("Received error whilst writing to connection") // ErrConnDial error during dial +// TODO Find an appropriate error to sub-type here var ErrConnDial = errors.New("Received error whilst establishing connection") // ErrOptsDialAndURL cannot combine both dial and URL for pool options +// TODO Find an appropriate error to sub-type here var ErrOptsDialAndURL = errors.New("Both Dial and URL is set, can only set one") // ErrNoMoreRows is returned when an ArrayResult does not contain any more entries when Next() is called +// TODO Find an appropriate error to sub-type here var ErrNoMoreRows = errors.New("No more rows") // ErrMixedTopicTypes is given when you pass in arguments of both RedisPattern and String +// TODO Find an appropriate error to sub-type here var ErrMixedTopicTypes = errors.New("All the topics need to be either of type string or of RedisPattern, but not of both") // ErrWrongType is returned when the function receives an unsupported type +// TODO Find an appropriate error to sub-type here func ErrWrongType(v interface{}, expected string) error { return fmt.Errorf("Received an unsupported type of %t, expected %s", v, expected) } // ErrWrongToken is used internally in the Redis Reader when it checks whether the token expected and this is not the case +// TODO Find an appropriate error to sub-type here func ErrWrongToken(expToken byte, token byte) error { return fmt.Errorf("Expected token: %s but received %s", string(expToken), string(token)) } diff --git a/go.mod b/go.mod index 1632927..f046973 100644 --- a/go.mod +++ b/go.mod @@ -3,21 +3,17 @@ module github.com/mikn/greddis require ( github.com/beorn7/perks v1.0.1 github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dropbox/godropbox v0.0.0-20190205061219-becbb8a577f3 - github.com/go-redis/redis v6.15.6+incompatible - github.com/golang/mock v1.3.1 - github.com/golang/protobuf v1.3.1 // indirect - github.com/gomodule/redigo v1.7.0 - github.com/kr/pretty v0.1.0 // indirect + github.com/dropbox/godropbox v0.0.0-20200228041828-52ad444d3502 + github.com/go-redis/redis v6.15.9+incompatible + github.com/golang/mock v1.5.0 + github.com/gomodule/redigo v1.8.4 github.com/onsi/ginkgo v1.8.0 // indirect github.com/onsi/gomega v1.5.0 // indirect - github.com/stretchr/testify v1.4.0 - golang.org/x/net v0.0.0-20191003171128-d98b1b443823 // indirect - golang.org/x/sync v0.0.0-20190423024810-112230192c58 + github.com/stretchr/testify v1.7.0 + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 // indirect golang.org/x/text v0.3.2 // indirect - google.golang.org/grpc v1.21.0 - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) -go 1.14 +go 1.16 diff --git a/go.sum b/go.sum index 9ee7f7c..fa1fe9d 100644 --- a/go.sum +++ b/go.sum @@ -1,35 +1,31 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dropbox/godropbox v0.0.0-20190205061219-becbb8a577f3 h1:I8C75JVqxBSrD9lE2b/jIJY5ta3EYnXZjuiSbiZRg98= -github.com/dropbox/godropbox v0.0.0-20190205061219-becbb8a577f3/go.mod h1:glr97hP/JuXb+WMYCizc4PIFuzw1lCR97mwbe1VVXhQ= +github.com/dropbox/godropbox v0.0.0-20200228041828-52ad444d3502 h1:tEkxjWg9OqJbkpgLaYbBjFO45+XygMJAEhOS62s+jLY= +github.com/dropbox/godropbox v0.0.0-20200228041828-52ad444d3502/go.mod h1:Bv2UWEUnUi8YN4834GVjZlRcJbeOAUPp7QjRU2LhBqI= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/go-redis/redis v6.15.6+incompatible h1:H9evprGPLI8+ci7fxQx6WNZHJSb7be8FqJQRhdQZ5Sg= -github.com/go-redis/redis v6.15.6+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/gomodule/redigo v1.7.0 h1:ZKld1VOtsGhAe37E7wMxEDgAlGM5dvFY+DiOhSkhP9Y= -github.com/gomodule/redigo v1.7.0/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/gomodule/redigo v1.8.4 h1:Z5JUg94HMTR1XpwBaSH4vq3+PNSIykBLxMdglbw10gg= +github.com/gomodule/redigo v1.8.4/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kisielk/errcheck v1.2.0 h1:reN85Pxc5larApoH1keMBiu2GWtPqXQ1nc9gx+jOU+E= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -42,37 +38,38 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20191003171128-d98b1b443823 h1:Ypyv6BNJh07T1pUSrehkLemqPKXhus2MkfktJ91kRh4= -golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 h1:L2auWcuQIvxz9xSEqzESnV/QN/gNRXNApHi3fYwl2w0= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262 h1:qsl9y/CJx34tuA7QCPNp86JNJe4spst6Ff8MjvPUdPg= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/grpc v1.21.0 h1:G+97AoqBnmZIT91cLG/EkCoK9NSelj64P8bOHHNmGn0= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e h1:aZzprAO9/8oim3qStq3wc1Xuxx4QmAGriC4VU4ojemQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -80,8 +77,9 @@ gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/mocks/mock_driver/mock_valuer.go b/mocks/mock_driver/mock_valuer.go index ff3a6a6..8f68b0a 100644 --- a/mocks/mock_driver/mock_valuer.go +++ b/mocks/mock_driver/mock_valuer.go @@ -6,34 +6,35 @@ package mock_driver import ( driver "database/sql/driver" - gomock "github.com/golang/mock/gomock" reflect "reflect" + + gomock "github.com/golang/mock/gomock" ) -// MockValuer is a mock of Valuer interface +// MockValuer is a mock of Valuer interface. type MockValuer struct { ctrl *gomock.Controller recorder *MockValuerMockRecorder } -// MockValuerMockRecorder is the mock recorder for MockValuer +// MockValuerMockRecorder is the mock recorder for MockValuer. type MockValuerMockRecorder struct { mock *MockValuer } -// NewMockValuer creates a new mock instance +// NewMockValuer creates a new mock instance. func NewMockValuer(ctrl *gomock.Controller) *MockValuer { mock := &MockValuer{ctrl: ctrl} mock.recorder = &MockValuerMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockValuer) EXPECT() *MockValuerMockRecorder { return m.recorder } -// Value mocks base method +// Value mocks base method. func (m *MockValuer) Value() (driver.Value, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Value") @@ -42,7 +43,7 @@ func (m *MockValuer) Value() (driver.Value, error) { return ret0, ret1 } -// Value indicates an expected call of Value +// Value indicates an expected call of Value. func (mr *MockValuerMockRecorder) Value() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Value", reflect.TypeOf((*MockValuer)(nil).Value)) diff --git a/mocks/mock_greddis/mock_client.go b/mocks/mock_greddis/mock_client.go index 24098aa..62cd95a 100644 --- a/mocks/mock_greddis/mock_client.go +++ b/mocks/mock_greddis/mock_client.go @@ -7,35 +7,36 @@ package mock_greddis import ( context "context" driver "database/sql/driver" + reflect "reflect" + gomock "github.com/golang/mock/gomock" greddis "github.com/mikn/greddis" - reflect "reflect" ) -// MockSubscriber is a mock of Subscriber interface +// MockSubscriber is a mock of Subscriber interface. type MockSubscriber struct { ctrl *gomock.Controller recorder *MockSubscriberMockRecorder } -// MockSubscriberMockRecorder is the mock recorder for MockSubscriber +// MockSubscriberMockRecorder is the mock recorder for MockSubscriber. type MockSubscriberMockRecorder struct { mock *MockSubscriber } -// NewMockSubscriber creates a new mock instance +// NewMockSubscriber creates a new mock instance. func NewMockSubscriber(ctrl *gomock.Controller) *MockSubscriber { mock := &MockSubscriber{ctrl: ctrl} mock.recorder = &MockSubscriberMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockSubscriber) EXPECT() *MockSubscriberMockRecorder { return m.recorder } -// Subscribe mocks base method +// Subscribe mocks base method. func (m *MockSubscriber) Subscribe(ctx context.Context, topics ...interface{}) (greddis.MessageChanMap, error) { m.ctrl.T.Helper() varargs := []interface{}{ctx} @@ -48,14 +49,14 @@ func (m *MockSubscriber) Subscribe(ctx context.Context, topics ...interface{}) ( return ret0, ret1 } -// Subscribe indicates an expected call of Subscribe +// Subscribe indicates an expected call of Subscribe. func (mr *MockSubscriberMockRecorder) Subscribe(ctx interface{}, topics ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]interface{}{ctx}, topics...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Subscribe", reflect.TypeOf((*MockSubscriber)(nil).Subscribe), varargs...) } -// Unsubscribe mocks base method +// Unsubscribe mocks base method. func (m *MockSubscriber) Unsubscribe(ctx context.Context, topics ...interface{}) error { m.ctrl.T.Helper() varargs := []interface{}{ctx} @@ -67,80 +68,66 @@ func (m *MockSubscriber) Unsubscribe(ctx context.Context, topics ...interface{}) return ret0 } -// Unsubscribe indicates an expected call of Unsubscribe +// Unsubscribe indicates an expected call of Unsubscribe. func (mr *MockSubscriberMockRecorder) Unsubscribe(ctx interface{}, topics ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]interface{}{ctx}, topics...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unsubscribe", reflect.TypeOf((*MockSubscriber)(nil).Unsubscribe), varargs...) } -// MockClient is a mock of Client interface +// MockClient is a mock of Client interface. type MockClient struct { ctrl *gomock.Controller recorder *MockClientMockRecorder } -// MockClientMockRecorder is the mock recorder for MockClient +// MockClientMockRecorder is the mock recorder for MockClient. type MockClientMockRecorder struct { mock *MockClient } -// NewMockClient creates a new mock instance +// NewMockClient creates a new mock instance. func NewMockClient(ctrl *gomock.Controller) *MockClient { mock := &MockClient{ctrl: ctrl} mock.recorder = &MockClientMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockClient) EXPECT() *MockClientMockRecorder { return m.recorder } -// Get mocks base method -func (m *MockClient) Get(ctx context.Context, key string) (*greddis.Result, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", ctx, key) - ret0, _ := ret[0].(*greddis.Result) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get -func (mr *MockClientMockRecorder) Get(ctx, key interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockClient)(nil).Get), ctx, key) -} - -// Set mocks base method -func (m *MockClient) Set(ctx context.Context, key string, value driver.Value, ttl int) error { +// Del mocks base method. +func (m *MockClient) Del(ctx context.Context, key string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Set", ctx, key, value, ttl) + ret := m.ctrl.Call(m, "Del", ctx, key) ret0, _ := ret[0].(error) return ret0 } -// Set indicates an expected call of Set -func (mr *MockClientMockRecorder) Set(ctx, key, value, ttl interface{}) *gomock.Call { +// Del indicates an expected call of Del. +func (mr *MockClientMockRecorder) Del(ctx, key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockClient)(nil).Set), ctx, key, value, ttl) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Del", reflect.TypeOf((*MockClient)(nil).Del), ctx, key) } -// Del mocks base method -func (m *MockClient) Del(ctx context.Context, key string) error { +// Get mocks base method. +func (m *MockClient) Get(ctx context.Context, key string) (*greddis.Result, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Del", ctx, key) - ret0, _ := ret[0].(error) - return ret0 + ret := m.ctrl.Call(m, "Get", ctx, key) + ret0, _ := ret[0].(*greddis.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// Del indicates an expected call of Del -func (mr *MockClientMockRecorder) Del(ctx, key interface{}) *gomock.Call { +// Get indicates an expected call of Get. +func (mr *MockClientMockRecorder) Get(ctx, key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Del", reflect.TypeOf((*MockClient)(nil).Del), ctx, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockClient)(nil).Get), ctx, key) } -// Ping mocks base method +// Ping mocks base method. func (m *MockClient) Ping(ctx context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Ping", ctx) @@ -148,13 +135,13 @@ func (m *MockClient) Ping(ctx context.Context) error { return ret0 } -// Ping indicates an expected call of Ping +// Ping indicates an expected call of Ping. func (mr *MockClientMockRecorder) Ping(ctx interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ping", reflect.TypeOf((*MockClient)(nil).Ping), ctx) } -// Publish mocks base method +// Publish mocks base method. func (m *MockClient) Publish(ctx context.Context, topic string, message driver.Value) (int, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Publish", ctx, topic, message) @@ -163,75 +150,64 @@ func (m *MockClient) Publish(ctx context.Context, topic string, message driver.V return ret0, ret1 } -// Publish indicates an expected call of Publish +// Publish indicates an expected call of Publish. func (mr *MockClientMockRecorder) Publish(ctx, topic, message interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Publish", reflect.TypeOf((*MockClient)(nil).Publish), ctx, topic, message) } -// MockSubClient is a mock of SubClient interface +// Set mocks base method. +func (m *MockClient) Set(ctx context.Context, key string, value driver.Value, ttl int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Set", ctx, key, value, ttl) + ret0, _ := ret[0].(error) + return ret0 +} + +// Set indicates an expected call of Set. +func (mr *MockClientMockRecorder) Set(ctx, key, value, ttl interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockClient)(nil).Set), ctx, key, value, ttl) +} + +// MockSubClient is a mock of SubClient interface. type MockSubClient struct { ctrl *gomock.Controller recorder *MockSubClientMockRecorder } -// MockSubClientMockRecorder is the mock recorder for MockSubClient +// MockSubClientMockRecorder is the mock recorder for MockSubClient. type MockSubClientMockRecorder struct { mock *MockSubClient } -// NewMockSubClient creates a new mock instance +// NewMockSubClient creates a new mock instance. func NewMockSubClient(ctrl *gomock.Controller) *MockSubClient { mock := &MockSubClient{ctrl: ctrl} mock.recorder = &MockSubClientMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockSubClient) EXPECT() *MockSubClientMockRecorder { return m.recorder } -// Subscribe mocks base method -func (m *MockSubClient) Subscribe(ctx context.Context, topics ...interface{}) (greddis.MessageChanMap, error) { - m.ctrl.T.Helper() - varargs := []interface{}{ctx} - for _, a := range topics { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "Subscribe", varargs...) - ret0, _ := ret[0].(greddis.MessageChanMap) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Subscribe indicates an expected call of Subscribe -func (mr *MockSubClientMockRecorder) Subscribe(ctx interface{}, topics ...interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx}, topics...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Subscribe", reflect.TypeOf((*MockSubClient)(nil).Subscribe), varargs...) -} - -// Unsubscribe mocks base method -func (m *MockSubClient) Unsubscribe(ctx context.Context, topics ...interface{}) error { +// Del mocks base method. +func (m *MockSubClient) Del(ctx context.Context, key string) error { m.ctrl.T.Helper() - varargs := []interface{}{ctx} - for _, a := range topics { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "Unsubscribe", varargs...) + ret := m.ctrl.Call(m, "Del", ctx, key) ret0, _ := ret[0].(error) return ret0 } -// Unsubscribe indicates an expected call of Unsubscribe -func (mr *MockSubClientMockRecorder) Unsubscribe(ctx interface{}, topics ...interface{}) *gomock.Call { +// Del indicates an expected call of Del. +func (mr *MockSubClientMockRecorder) Del(ctx, key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx}, topics...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unsubscribe", reflect.TypeOf((*MockSubClient)(nil).Unsubscribe), varargs...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Del", reflect.TypeOf((*MockSubClient)(nil).Del), ctx, key) } -// Get mocks base method +// Get mocks base method. func (m *MockSubClient) Get(ctx context.Context, key string) (*greddis.Result, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", ctx, key) @@ -240,65 +216,90 @@ func (m *MockSubClient) Get(ctx context.Context, key string) (*greddis.Result, e return ret0, ret1 } -// Get indicates an expected call of Get +// Get indicates an expected call of Get. func (mr *MockSubClientMockRecorder) Get(ctx, key interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockSubClient)(nil).Get), ctx, key) } -// Set mocks base method -func (m *MockSubClient) Set(ctx context.Context, key string, value driver.Value, ttl int) error { +// Ping mocks base method. +func (m *MockSubClient) Ping(ctx context.Context) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Set", ctx, key, value, ttl) + ret := m.ctrl.Call(m, "Ping", ctx) ret0, _ := ret[0].(error) return ret0 } -// Set indicates an expected call of Set -func (mr *MockSubClientMockRecorder) Set(ctx, key, value, ttl interface{}) *gomock.Call { +// Ping indicates an expected call of Ping. +func (mr *MockSubClientMockRecorder) Ping(ctx interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockSubClient)(nil).Set), ctx, key, value, ttl) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ping", reflect.TypeOf((*MockSubClient)(nil).Ping), ctx) } -// Del mocks base method -func (m *MockSubClient) Del(ctx context.Context, key string) error { +// Publish mocks base method. +func (m *MockSubClient) Publish(ctx context.Context, topic string, message driver.Value) (int, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Del", ctx, key) - ret0, _ := ret[0].(error) - return ret0 + ret := m.ctrl.Call(m, "Publish", ctx, topic, message) + ret0, _ := ret[0].(int) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// Del indicates an expected call of Del -func (mr *MockSubClientMockRecorder) Del(ctx, key interface{}) *gomock.Call { +// Publish indicates an expected call of Publish. +func (mr *MockSubClientMockRecorder) Publish(ctx, topic, message interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Del", reflect.TypeOf((*MockSubClient)(nil).Del), ctx, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Publish", reflect.TypeOf((*MockSubClient)(nil).Publish), ctx, topic, message) } -// Ping mocks base method -func (m *MockSubClient) Ping(ctx context.Context) error { +// Set mocks base method. +func (m *MockSubClient) Set(ctx context.Context, key string, value driver.Value, ttl int) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Ping", ctx) + ret := m.ctrl.Call(m, "Set", ctx, key, value, ttl) ret0, _ := ret[0].(error) return ret0 } -// Ping indicates an expected call of Ping -func (mr *MockSubClientMockRecorder) Ping(ctx interface{}) *gomock.Call { +// Set indicates an expected call of Set. +func (mr *MockSubClientMockRecorder) Set(ctx, key, value, ttl interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ping", reflect.TypeOf((*MockSubClient)(nil).Ping), ctx) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockSubClient)(nil).Set), ctx, key, value, ttl) } -// Publish mocks base method -func (m *MockSubClient) Publish(ctx context.Context, topic string, message driver.Value) (int, error) { +// Subscribe mocks base method. +func (m *MockSubClient) Subscribe(ctx context.Context, topics ...interface{}) (greddis.MessageChanMap, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Publish", ctx, topic, message) - ret0, _ := ret[0].(int) + varargs := []interface{}{ctx} + for _, a := range topics { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Subscribe", varargs...) + ret0, _ := ret[0].(greddis.MessageChanMap) ret1, _ := ret[1].(error) return ret0, ret1 } -// Publish indicates an expected call of Publish -func (mr *MockSubClientMockRecorder) Publish(ctx, topic, message interface{}) *gomock.Call { +// Subscribe indicates an expected call of Subscribe. +func (mr *MockSubClientMockRecorder) Subscribe(ctx interface{}, topics ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Publish", reflect.TypeOf((*MockSubClient)(nil).Publish), ctx, topic, message) + varargs := append([]interface{}{ctx}, topics...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Subscribe", reflect.TypeOf((*MockSubClient)(nil).Subscribe), varargs...) +} + +// Unsubscribe mocks base method. +func (m *MockSubClient) Unsubscribe(ctx context.Context, topics ...interface{}) error { + m.ctrl.T.Helper() + varargs := []interface{}{ctx} + for _, a := range topics { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Unsubscribe", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Unsubscribe indicates an expected call of Unsubscribe. +func (mr *MockSubClientMockRecorder) Unsubscribe(ctx interface{}, topics ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx}, topics...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unsubscribe", reflect.TypeOf((*MockSubClient)(nil).Unsubscribe), varargs...) } diff --git a/mocks/mock_greddis/mock_result.go b/mocks/mock_greddis/mock_result.go index 9243037..c2d56f3 100644 --- a/mocks/mock_greddis/mock_result.go +++ b/mocks/mock_greddis/mock_result.go @@ -5,34 +5,35 @@ package mock_greddis import ( - gomock "github.com/golang/mock/gomock" reflect "reflect" + + gomock "github.com/golang/mock/gomock" ) -// MockScanner is a mock of Scanner interface +// MockScanner is a mock of Scanner interface. type MockScanner struct { ctrl *gomock.Controller recorder *MockScannerMockRecorder } -// MockScannerMockRecorder is the mock recorder for MockScanner +// MockScannerMockRecorder is the mock recorder for MockScanner. type MockScannerMockRecorder struct { mock *MockScanner } -// NewMockScanner creates a new mock instance +// NewMockScanner creates a new mock instance. func NewMockScanner(ctrl *gomock.Controller) *MockScanner { mock := &MockScanner{ctrl: ctrl} mock.recorder = &MockScannerMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockScanner) EXPECT() *MockScannerMockRecorder { return m.recorder } -// Scan mocks base method +// Scan mocks base method. func (m *MockScanner) Scan(dst interface{}) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Scan", dst) @@ -40,7 +41,7 @@ func (m *MockScanner) Scan(dst interface{}) error { return ret0 } -// Scan indicates an expected call of Scan +// Scan indicates an expected call of Scan. func (mr *MockScannerMockRecorder) Scan(dst interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Scan", reflect.TypeOf((*MockScanner)(nil).Scan), dst) diff --git a/mocks/mock_io/mock_writer.go b/mocks/mock_io/mock_writer.go index 00da57b..5697b69 100644 --- a/mocks/mock_io/mock_writer.go +++ b/mocks/mock_io/mock_writer.go @@ -5,34 +5,35 @@ package mock_io import ( - gomock "github.com/golang/mock/gomock" reflect "reflect" + + gomock "github.com/golang/mock/gomock" ) -// MockWriter is a mock of Writer interface +// MockWriter is a mock of Writer interface. type MockWriter struct { ctrl *gomock.Controller recorder *MockWriterMockRecorder } -// MockWriterMockRecorder is the mock recorder for MockWriter +// MockWriterMockRecorder is the mock recorder for MockWriter. type MockWriterMockRecorder struct { mock *MockWriter } -// NewMockWriter creates a new mock instance +// NewMockWriter creates a new mock instance. func NewMockWriter(ctrl *gomock.Controller) *MockWriter { mock := &MockWriter{ctrl: ctrl} mock.recorder = &MockWriterMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockWriter) EXPECT() *MockWriterMockRecorder { return m.recorder } -// Write mocks base method +// Write mocks base method. func (m *MockWriter) Write(arg0 []byte) (int, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Write", arg0) @@ -41,7 +42,7 @@ func (m *MockWriter) Write(arg0 []byte) (int, error) { return ret0, ret1 } -// Write indicates an expected call of Write +// Write indicates an expected call of Write. func (mr *MockWriterMockRecorder) Write(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Write", reflect.TypeOf((*MockWriter)(nil).Write), arg0) diff --git a/mocks/mock_net/mock_conn.go b/mocks/mock_net/mock_conn.go index ca7f9b0..5a80838 100644 --- a/mocks/mock_net/mock_conn.go +++ b/mocks/mock_net/mock_conn.go @@ -5,36 +5,37 @@ package mock_net import ( - gomock "github.com/golang/mock/gomock" net "net" reflect "reflect" time "time" + + gomock "github.com/golang/mock/gomock" ) -// MockConn is a mock of Conn interface +// MockConn is a mock of Conn interface. type MockConn struct { ctrl *gomock.Controller recorder *MockConnMockRecorder } -// MockConnMockRecorder is the mock recorder for MockConn +// MockConnMockRecorder is the mock recorder for MockConn. type MockConnMockRecorder struct { mock *MockConn } -// NewMockConn creates a new mock instance +// NewMockConn creates a new mock instance. func NewMockConn(ctrl *gomock.Controller) *MockConn { mock := &MockConn{ctrl: ctrl} mock.recorder = &MockConnMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockConn) EXPECT() *MockConnMockRecorder { return m.recorder } -// Close mocks base method +// Close mocks base method. func (m *MockConn) Close() error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Close") @@ -42,13 +43,13 @@ func (m *MockConn) Close() error { return ret0 } -// Close indicates an expected call of Close +// Close indicates an expected call of Close. func (mr *MockConnMockRecorder) Close() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockConn)(nil).Close)) } -// LocalAddr mocks base method +// LocalAddr mocks base method. func (m *MockConn) LocalAddr() net.Addr { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "LocalAddr") @@ -56,13 +57,13 @@ func (m *MockConn) LocalAddr() net.Addr { return ret0 } -// LocalAddr indicates an expected call of LocalAddr +// LocalAddr indicates an expected call of LocalAddr. func (mr *MockConnMockRecorder) LocalAddr() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LocalAddr", reflect.TypeOf((*MockConn)(nil).LocalAddr)) } -// Read mocks base method +// Read mocks base method. func (m *MockConn) Read(arg0 []byte) (int, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Read", arg0) @@ -71,13 +72,13 @@ func (m *MockConn) Read(arg0 []byte) (int, error) { return ret0, ret1 } -// Read indicates an expected call of Read +// Read indicates an expected call of Read. func (mr *MockConnMockRecorder) Read(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Read", reflect.TypeOf((*MockConn)(nil).Read), arg0) } -// RemoteAddr mocks base method +// RemoteAddr mocks base method. func (m *MockConn) RemoteAddr() net.Addr { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RemoteAddr") @@ -85,13 +86,13 @@ func (m *MockConn) RemoteAddr() net.Addr { return ret0 } -// RemoteAddr indicates an expected call of RemoteAddr +// RemoteAddr indicates an expected call of RemoteAddr. func (mr *MockConnMockRecorder) RemoteAddr() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoteAddr", reflect.TypeOf((*MockConn)(nil).RemoteAddr)) } -// SetDeadline mocks base method +// SetDeadline mocks base method. func (m *MockConn) SetDeadline(arg0 time.Time) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SetDeadline", arg0) @@ -99,13 +100,13 @@ func (m *MockConn) SetDeadline(arg0 time.Time) error { return ret0 } -// SetDeadline indicates an expected call of SetDeadline +// SetDeadline indicates an expected call of SetDeadline. func (mr *MockConnMockRecorder) SetDeadline(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetDeadline", reflect.TypeOf((*MockConn)(nil).SetDeadline), arg0) } -// SetReadDeadline mocks base method +// SetReadDeadline mocks base method. func (m *MockConn) SetReadDeadline(arg0 time.Time) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SetReadDeadline", arg0) @@ -113,13 +114,13 @@ func (m *MockConn) SetReadDeadline(arg0 time.Time) error { return ret0 } -// SetReadDeadline indicates an expected call of SetReadDeadline +// SetReadDeadline indicates an expected call of SetReadDeadline. func (mr *MockConnMockRecorder) SetReadDeadline(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetReadDeadline", reflect.TypeOf((*MockConn)(nil).SetReadDeadline), arg0) } -// SetWriteDeadline mocks base method +// SetWriteDeadline mocks base method. func (m *MockConn) SetWriteDeadline(arg0 time.Time) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SetWriteDeadline", arg0) @@ -127,13 +128,13 @@ func (m *MockConn) SetWriteDeadline(arg0 time.Time) error { return ret0 } -// SetWriteDeadline indicates an expected call of SetWriteDeadline +// SetWriteDeadline indicates an expected call of SetWriteDeadline. func (mr *MockConnMockRecorder) SetWriteDeadline(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetWriteDeadline", reflect.TypeOf((*MockConn)(nil).SetWriteDeadline), arg0) } -// Write mocks base method +// Write mocks base method. func (m *MockConn) Write(arg0 []byte) (int, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Write", arg0) @@ -142,7 +143,7 @@ func (m *MockConn) Write(arg0 []byte) (int, error) { return ret0, ret1 } -// Write indicates an expected call of Write +// Write indicates an expected call of Write. func (mr *MockConnMockRecorder) Write(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Write", reflect.TypeOf((*MockConn)(nil).Write), arg0) diff --git a/mocks/mock_net/mock_error.go b/mocks/mock_net/mock_error.go deleted file mode 100644 index 9777027..0000000 --- a/mocks/mock_net/mock_error.go +++ /dev/null @@ -1,75 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: net (interfaces: Error) - -// Package mock_net is a generated GoMock package. -package mock_net - -import ( - gomock "github.com/golang/mock/gomock" - reflect "reflect" -) - -// MockError is a mock of Error interface -type MockError struct { - ctrl *gomock.Controller - recorder *MockErrorMockRecorder -} - -// MockErrorMockRecorder is the mock recorder for MockError -type MockErrorMockRecorder struct { - mock *MockError -} - -// NewMockError creates a new mock instance -func NewMockError(ctrl *gomock.Controller) *MockError { - mock := &MockError{ctrl: ctrl} - mock.recorder = &MockErrorMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockError) EXPECT() *MockErrorMockRecorder { - return m.recorder -} - -// Error mocks base method -func (m *MockError) Error() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Error") - ret0, _ := ret[0].(string) - return ret0 -} - -// Error indicates an expected call of Error -func (mr *MockErrorMockRecorder) Error() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Error", reflect.TypeOf((*MockError)(nil).Error)) -} - -// Temporary mocks base method -func (m *MockError) Temporary() bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Temporary") - ret0, _ := ret[0].(bool) - return ret0 -} - -// Temporary indicates an expected call of Temporary -func (mr *MockErrorMockRecorder) Temporary() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Temporary", reflect.TypeOf((*MockError)(nil).Temporary)) -} - -// Timeout mocks base method -func (m *MockError) Timeout() bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Timeout") - ret0, _ := ret[0].(bool) - return ret0 -} - -// Timeout indicates an expected call of Timeout -func (mr *MockErrorMockRecorder) Timeout() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Timeout", reflect.TypeOf((*MockError)(nil).Timeout)) -} diff --git a/pubsub.go b/pubsub.go index ef6ba50..62c8371 100644 --- a/pubsub.go +++ b/pubsub.go @@ -6,7 +6,7 @@ import ( "fmt" "log" "math" - "net" + "os" "sync" "time" "unsafe" @@ -19,11 +19,6 @@ const ( subPattern ) -// I can't really have more than one message per connection "active" at a time -// because the reader, the result etc are all tied to the connection (and we should really not -// be advancing the reader in another thread) - so the idea here with the pool and stuff -// is pretty stupid. I should add the message to the subscription manager and listen for it -// on the channel at the top of every loop of Listen() type Message struct { Ctx context.Context pattern []byte @@ -143,8 +138,7 @@ func (s *subscriptionManager) Listen(ctx context.Context, c *conn) { m.Init() c.conn.SetReadDeadline(time.Now().Add(s.opts.PingInterval)) err = array.Init(ScanBulkString) - // TODO when 1.15 is out, change this to this: https://github.com/golang/go/issues/31449 - if nErr, ok := err.(net.Error); ok && nErr.Timeout() { + if errors.Is(err, os.ErrDeadlineExceeded) { c.conn.SetReadDeadline(time.Now().Add(s.opts.ReadTimeout)) if err := ping(ctx, c); err != nil { log.Printf("Ping error: %s", err) diff --git a/pubsub_test.go b/pubsub_test.go index 3aae4d9..58b75b7 100644 --- a/pubsub_test.go +++ b/pubsub_test.go @@ -1,4 +1,3 @@ -//go:generate mockgen -destination ./mocks/mock_net/mock_error.go net Error package greddis import ( @@ -117,9 +116,8 @@ func TestSubscriptionManager(t *testing.T) { defer ctrl.Finish() subMngr := getSubMngr(ctx, ctrl) mockConn := subMngr.conn.conn.(*mock_net.MockConn) - mockErr := mock_net.NewMockError(ctrl) + mockErr := fmt.Errorf("MOCKERROR: %w", os.ErrDeadlineExceeded) testErr := errors.New("TESTERROR") - mockErr.EXPECT().Timeout().Return(true) mockConn.EXPECT().SetReadDeadline(gomock.Any()) mockConn.EXPECT().Read(gomock.Any()).Return(0, mockErr) mockConn.EXPECT().SetReadDeadline(gomock.Any()) @@ -169,8 +167,7 @@ func TestSubscriptionManager(t *testing.T) { defer ctrl.Finish() subMngr := getSubMngr(ctx, ctrl) mockConn := subMngr.conn.conn.(*mock_net.MockConn) - mockErr := mock_net.NewMockError(ctrl) - mockErr.EXPECT().Timeout().Return(true) + mockErr := fmt.Errorf("MOCKERROR: %w", os.ErrDeadlineExceeded) mockConn.EXPECT().SetReadDeadline(gomock.Any()) mockConn.EXPECT().Read(gomock.Any()).Return(0, mockErr) mockConn.EXPECT().SetReadDeadline(gomock.Any()) diff --git a/reader.go b/reader.go index 57d53a8..fd8e725 100644 --- a/reader.go +++ b/reader.go @@ -28,6 +28,8 @@ type Reader struct { intToken int } +// TODO Do not hide the potential error from Peek, make sure it is properly propagated +// TODO propagate error from Atoi() in Int() call func NewReader(r *bufio.Reader) *Reader { return &Reader{ r: r, diff --git a/result.go b/result.go index 3ccfe2e..8436c14 100644 --- a/result.go +++ b/result.go @@ -45,6 +45,7 @@ func scan(r *Reader, dst interface{}) (err error) { *d = string(r.Bytes()) case *int: var val int + // TODO switch to use r.Int() once error is being returned val, err = strconv.Atoi(r.String()) if err == nil { *d = int(val)