Przeglądaj źródła

avoid bigint converted into float64 when unmarshaling

kevin 4 lat temu
rodzic
commit
fe855c52f1

+ 5 - 5
core/stores/cache/cachenode.go

@@ -1,13 +1,13 @@
 package cache
 
 import (
-	"encoding/json"
 	"errors"
 	"fmt"
 	"math/rand"
 	"sync"
 	"time"
 
+	"github.com/tal-tech/go-zero/core/jsonx"
 	"github.com/tal-tech/go-zero/core/logx"
 	"github.com/tal-tech/go-zero/core/mathx"
 	"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 {
-	data, err := json.Marshal(v)
+	data, err := jsonx.Marshal(v)
 	if err != nil {
 		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 {
 		return err
@@ -181,11 +181,11 @@ func (c cacheNode) doTake(v interface{}, key string, query func(v interface{}) e
 		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 {
-	err := json.Unmarshal([]byte(data), v)
+	err := jsonx.Unmarshal([]byte(data), v)
 	if err == nil {
 		return nil
 	}

+ 30 - 0
core/stores/cache/cachenode_test.go

@@ -2,7 +2,9 @@ package cache
 
 import (
 	"errors"
+	"fmt"
 	"math/rand"
+	"strconv"
 	"sync"
 	"testing"
 	"time"
@@ -176,3 +178,31 @@ func TestCacheNode_String(t *testing.T) {
 	}
 	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))
+}

+ 0 - 17
core/stores/sqlc/cachedsql.go

@@ -83,10 +83,6 @@ func (cc CachedConn) QueryRowIndex(v interface{}, key string, keyer func(primary
 	var primaryKey interface{}
 	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) {
 		primaryKey, err = indexQuery(cc.db, v)
 		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 {
 	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)
-		}
-	}
-}

+ 0 - 14
core/stores/sqlc/cachedsql_test.go

@@ -594,20 +594,6 @@ func TestQueryRowNoCache(t *testing.T) {
 	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() {
 	atomic.StoreUint64(&stats.Total, 0)
 	atomic.StoreUint64(&stats.Hit, 0)