github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/exp/kvutil/sharding_json_test.go (about)

     1  package kvutil
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  type TestJSONShardData struct {
    14  	TotalNum int32  `json:"totalNum"`
    15  	ShardNum int32  `json:"shardNum"`
    16  	Digest   []byte `json:"digest"`
    17  
    18  	// Data ...
    19  	// As an example, JSON data is always valid UTF-8 strings,
    20  	// string and []byte are exchangeable here,
    21  	// using string here avoids unnecessary base64 encoding and decoding
    22  	// when doing JSON serialization.
    23  	Data string `json:"data"`
    24  }
    25  
    26  type TestJSONShardingModel struct {
    27  	ID        int64  `json:"id,omitempty"`
    28  	InnerData string `json:"innerData,omitempty"`
    29  
    30  	// ShardData helps to do big value sharding.
    31  	ShardData *TestJSONShardData `json:"shardData"`
    32  }
    33  
    34  func (m *TestJSONShardingModel) MarshalBinary() (data []byte, err error) {
    35  	return json.Marshal(m)
    36  }
    37  
    38  func (m *TestJSONShardingModel) UnmarshalBinary(data []byte) error {
    39  	return json.Unmarshal(data, m)
    40  }
    41  
    42  func (m *TestJSONShardingModel) GetShardingData() (ShardingData, bool) {
    43  	if m.ShardData == nil {
    44  		return ShardingData{}, false
    45  	}
    46  	return ShardingData{
    47  		TotalNum: m.ShardData.TotalNum,
    48  		ShardNum: m.ShardData.ShardNum,
    49  		Digest:   m.ShardData.Digest,
    50  		Data:     []byte(m.ShardData.Data),
    51  	}, true
    52  }
    53  
    54  func (m *TestJSONShardingModel) SetShardingData(data ShardingData) {
    55  	m.ShardData = &TestJSONShardData{
    56  		TotalNum: data.TotalNum,
    57  		ShardNum: data.ShardNum,
    58  		Digest:   data.Digest,
    59  		Data:     string(data.Data),
    60  	}
    61  }
    62  
    63  var (
    64  	testJSONShardingModelList = []*TestJSONShardingModel{
    65  		{
    66  			ID:        111,
    67  			InnerData: "test",
    68  		},
    69  		{
    70  			ID:        112,
    71  			InnerData: strings.Repeat("test ", 10),
    72  		},
    73  		{
    74  			ID:        113,
    75  			InnerData: strings.Repeat("test ", 50),
    76  		},
    77  	}
    78  )
    79  
    80  //nolint:dupl
    81  func TestShardingCache_JSON(t *testing.T) {
    82  	kf := KeyFactory{}
    83  	cfg := &ShardingCacheConfig[int64, *TestJSONShardingModel]{
    84  		Storage: testClientFunc("testShardingCache_JSON"),
    85  		IDFunc: func(model *TestJSONShardingModel) int64 {
    86  			return model.ID
    87  		},
    88  		KeyFunc:         kf.NewKey("testShardingCache:{id}"),
    89  		ShardingSize:    50,
    90  		MGetBatchSize:   2,
    91  		MSetBatchSize:   2,
    92  		DeleteBatchSize: 2,
    93  	}
    94  
    95  	ctx := context.Background()
    96  	sc := NewShardingCache[int64, *TestJSONShardingModel](cfg)
    97  
    98  	t.Run("Get / not found", func(t *testing.T) {
    99  		gotModel, err := sc.Get(ctx, testIntIds[0])
   100  		assert.Equal(t, ErrDataNotFound, err)
   101  		assert.Nil(t, gotModel)
   102  	})
   103  
   104  	t.Run("MGet / not found", func(t *testing.T) {
   105  		modelMap, errMap, err := sc.MGet(ctx, testIntIds)
   106  		assert.Nil(t, err)
   107  		assert.Len(t, errMap, 0)
   108  		assert.Len(t, modelMap, 0)
   109  	})
   110  
   111  	t.Run("Set", func(t *testing.T) {
   112  		clearMemoryStorage(ctx, sc.config.Storage)
   113  		stor := getMemoryStorage(ctx, sc.config.Storage)
   114  		_ = stor
   115  
   116  		err1 := sc.Set(ctx, 111, testJSONShardingModelList[0], 0)
   117  		assert.Nil(t, err1)
   118  
   119  		err2 := sc.Set(ctx, 112, testJSONShardingModelList[1], 0)
   120  		assert.Nil(t, err2)
   121  
   122  		err3 := sc.Set(ctx, 113, testJSONShardingModelList[2], 0)
   123  		assert.Nil(t, err3)
   124  
   125  		got1, err1 := sc.Get(ctx, 111)
   126  		assert.Nil(t, err1)
   127  		assert.NotNil(t, got1)
   128  		assert.Nil(t, got1.ShardData)
   129  		assert.Equal(t, testJSONShardingModelList[0].InnerData, got1.InnerData)
   130  
   131  		got2, err2 := sc.Get(ctx, 112)
   132  		assert.Nil(t, err2)
   133  		assert.NotNil(t, got2)
   134  		assert.Nil(t, got2.ShardData)
   135  		assert.Equal(t, testJSONShardingModelList[1].InnerData, got2.InnerData)
   136  
   137  		got3, err3 := sc.Get(ctx, 113)
   138  		assert.Nil(t, err3)
   139  		assert.NotNil(t, got3)
   140  		assert.Nil(t, got3.ShardData)
   141  		assert.Equal(t, testJSONShardingModelList[2].InnerData, got3.InnerData)
   142  
   143  		mgetRet, errMap, err := sc.MGet(ctx, []int64{111, 112, 113, 114})
   144  		assert.Nil(t, err)
   145  		assert.Len(t, errMap, 0)
   146  		assert.Len(t, mgetRet, 3)
   147  		assert.Equal(t, testJSONShardingModelList[0].InnerData, mgetRet[111].InnerData)
   148  		assert.Equal(t, testJSONShardingModelList[1].InnerData, mgetRet[112].InnerData)
   149  		assert.Equal(t, testJSONShardingModelList[2].InnerData, mgetRet[113].InnerData)
   150  	})
   151  
   152  	t.Run("MSet", func(t *testing.T) {
   153  		clearMemoryStorage(ctx, sc.config.Storage)
   154  		stor := getMemoryStorage(ctx, sc.config.Storage)
   155  		_ = stor
   156  
   157  		err := sc.MSet(ctx, testJSONShardingModelList, 0)
   158  		require.Nil(t, err)
   159  
   160  		mgetRet, errMap, err := sc.MGet(ctx, []int64{111, 112, 113, 114})
   161  		assert.Nil(t, err)
   162  		assert.Len(t, errMap, 0)
   163  		assert.Len(t, mgetRet, 3)
   164  		assert.Equal(t, testJSONShardingModelList[0].InnerData, mgetRet[111].InnerData)
   165  		assert.Equal(t, testJSONShardingModelList[1].InnerData, mgetRet[112].InnerData)
   166  		assert.Equal(t, testJSONShardingModelList[2].InnerData, mgetRet[113].InnerData)
   167  	})
   168  
   169  	t.Run("Delete", func(t *testing.T) {
   170  		clearMemoryStorage(ctx, sc.config.Storage)
   171  		stor := getMemoryStorage(ctx, sc.config.Storage)
   172  		_ = stor
   173  
   174  		err := sc.MSet(ctx, testJSONShardingModelList, 0)
   175  		require.Nil(t, err)
   176  
   177  		err = sc.Delete(ctx, false, 111, 112)
   178  		require.Nil(t, err)
   179  
   180  		got1, err1 := sc.Get(ctx, 111)
   181  		assert.Equal(t, ErrDataNotFound, err1)
   182  		assert.Nil(t, got1)
   183  
   184  		got2, err2 := sc.Get(ctx, 112)
   185  		assert.Equal(t, ErrDataNotFound, err2)
   186  		assert.Nil(t, got2)
   187  
   188  		err = sc.Delete(ctx, true, 113)
   189  		require.Nil(t, err)
   190  
   191  		got3, err3 := sc.Get(ctx, 113)
   192  		assert.Equal(t, ErrDataNotFound, err3)
   193  		assert.Nil(t, got3)
   194  
   195  		assert.Nil(t, stor.data[sc.config.KeyFunc(111)])
   196  		assert.Nil(t, stor.data[sc.config.KeyFunc(112)])
   197  		assert.NotNil(t, stor.data[GetShardKey(sc.config.KeyFunc(112), 1)])
   198  		assert.Nil(t, stor.data[sc.config.KeyFunc(113)])
   199  		assert.Nil(t, stor.data[GetShardKey(sc.config.KeyFunc(113), 1)])
   200  		assert.Nil(t, stor.data[GetShardKey(sc.config.KeyFunc(113), 2)])
   201  		assert.Nil(t, stor.data[GetShardKey(sc.config.KeyFunc(113), 3)])
   202  	})
   203  
   204  }