avoid bigint converted into float64 when unmarshaling

master v1.0.20
kevin 4 years ago
parent 3f8b080882
commit fe855c52f1

@ -1,13 +1,13 @@
package cache package cache
import ( import (
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"math/rand" "math/rand"
"sync" "sync"
"time" "time"
"github.com/tal-tech/go-zero/core/jsonx"
"github.com/tal-tech/go-zero/core/logx" "github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/mathx" "github.com/tal-tech/go-zero/core/mathx"
"github.com/tal-tech/go-zero/core/stat" "github.com/tal-tech/go-zero/core/stat"
@ -79,7 +79,7 @@ func (c cacheNode) SetCache(key string, v interface{}) error {
} }
func (c cacheNode) SetCacheWithExpire(key string, v interface{}, expire time.Duration) error { func (c cacheNode) SetCacheWithExpire(key string, v interface{}, expire time.Duration) error {
data, err := json.Marshal(v) data, err := jsonx.Marshal(v)
if err != nil { if err != nil {
return err return err
} }
@ -168,7 +168,7 @@ func (c cacheNode) doTake(v interface{}, key string, query func(v interface{}) e
} }
} }
return json.Marshal(v) return jsonx.Marshal(v)
}) })
if err != nil { if err != nil {
return err return err
@ -181,11 +181,11 @@ func (c cacheNode) doTake(v interface{}, key string, query func(v interface{}) e
c.stat.IncrementHit() c.stat.IncrementHit()
} }
return json.Unmarshal(val.([]byte), v) return jsonx.Unmarshal(val.([]byte), v)
} }
func (c cacheNode) processCache(key string, data string, v interface{}) error { func (c cacheNode) processCache(key string, data string, v interface{}) error {
err := json.Unmarshal([]byte(data), v) err := jsonx.Unmarshal([]byte(data), v)
if err == nil { if err == nil {
return nil return nil
} }

@ -2,7 +2,9 @@ package cache
import ( import (
"errors" "errors"
"fmt"
"math/rand" "math/rand"
"strconv"
"sync" "sync"
"testing" "testing"
"time" "time"
@ -176,3 +178,31 @@ func TestCacheNode_String(t *testing.T) {
} }
assert.Equal(t, s.Addr(), cn.String()) assert.Equal(t, s.Addr(), cn.String())
} }
func TestCacheValueWithBigInt(t *testing.T) {
s, err := miniredis.Run()
if err != nil {
t.Error(err)
}
defer s.Close()
cn := cacheNode{
rds: redis.NewRedis(s.Addr(), redis.NodeType),
r: rand.New(rand.NewSource(time.Now().UnixNano())),
barrier: syncx.NewSharedCalls(),
lock: new(sync.Mutex),
unstableExpiry: mathx.NewUnstable(expiryDeviation),
stat: NewCacheStat("any"),
errNotFound: errors.New("any"),
}
const (
key = "key"
value int64 = 323427211229009810
)
assert.Nil(t, cn.SetCache(key, value))
var val interface{}
assert.Nil(t, cn.GetCache(key, &val))
assert.Equal(t, strconv.FormatInt(value, 10), fmt.Sprintf("%v", val))
}

@ -83,10 +83,6 @@ func (cc CachedConn) QueryRowIndex(v interface{}, key string, keyer func(primary
var primaryKey interface{} var primaryKey interface{}
var found bool var found bool
// if don't use convert numeric primary key into int64,
// then it will be represented as scientific notion, like 2e6
// which will make the cache doesn't match with the previous insert one
keyer = floatKeyer(keyer)
if err := cc.cache.TakeWithExpire(&primaryKey, key, func(val interface{}, expire time.Duration) (err error) { if err := cc.cache.TakeWithExpire(&primaryKey, key, func(val interface{}, expire time.Duration) (err error) {
primaryKey, err = indexQuery(cc.db, v) primaryKey, err = indexQuery(cc.db, v)
if err != nil { if err != nil {
@ -124,16 +120,3 @@ func (cc CachedConn) SetCache(key string, v interface{}) error {
func (cc CachedConn) Transact(fn func(sqlx.Session) error) error { func (cc CachedConn) Transact(fn func(sqlx.Session) error) error {
return cc.db.Transact(fn) return cc.db.Transact(fn)
} }
func floatKeyer(fn func(interface{}) string) func(interface{}) string {
return func(primary interface{}) string {
switch v := primary.(type) {
case float32:
return fn(int64(v))
case float64:
return fn(int64(v))
default:
return fn(primary)
}
}
}

@ -594,20 +594,6 @@ func TestQueryRowNoCache(t *testing.T) {
assert.True(t, ran) assert.True(t, ran)
} }
func TestFloatKeyer(t *testing.T) {
primaries := []interface{}{
float32(1),
float64(1),
}
for _, primary := range primaries {
val := floatKeyer(func(i interface{}) string {
return fmt.Sprint(i)
})(primary)
assert.Equal(t, "1", val)
}
}
func resetStats() { func resetStats() {
atomic.StoreUint64(&stats.Total, 0) atomic.StoreUint64(&stats.Total, 0)
atomic.StoreUint64(&stats.Hit, 0) atomic.StoreUint64(&stats.Hit, 0)

Loading…
Cancel
Save