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 }