github.com/KinWaiYuen/client-go/v2@v2.5.4/internal/locate/region_request_test.go (about) 1 // Copyright 2021 TiKV Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // NOTE: The code in this file is based on code from the 16 // TiDB project, licensed under the Apache License v 2.0 17 // 18 // https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/locate/region_request_test.go 19 // 20 21 // Copyright 2017 PingCAP, Inc. 22 // 23 // Licensed under the Apache License, Version 2.0 (the "License"); 24 // you may not use this file except in compliance with the License. 25 // You may obtain a copy of the License at 26 // 27 // http://www.apache.org/licenses/LICENSE-2.0 28 // 29 // Unless required by applicable law or agreed to in writing, software 30 // distributed under the License is distributed on an "AS IS" BASIS, 31 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 32 // See the License for the specific language governing permissions and 33 // limitations under the License. 34 35 package locate 36 37 import ( 38 "context" 39 "fmt" 40 "net" 41 "sync" 42 "testing" 43 "time" 44 "unsafe" 45 46 "github.com/KinWaiYuen/client-go/v2/internal/client" 47 "github.com/KinWaiYuen/client-go/v2/internal/mockstore/mocktikv" 48 "github.com/KinWaiYuen/client-go/v2/internal/retry" 49 "github.com/KinWaiYuen/client-go/v2/tikvrpc" 50 "github.com/pingcap/errors" 51 "github.com/pingcap/kvproto/pkg/coprocessor" 52 "github.com/pingcap/kvproto/pkg/errorpb" 53 "github.com/pingcap/kvproto/pkg/kvrpcpb" 54 "github.com/pingcap/kvproto/pkg/metapb" 55 "github.com/pingcap/kvproto/pkg/mpp" 56 "github.com/pingcap/kvproto/pkg/tikvpb" 57 "github.com/stretchr/testify/suite" 58 "google.golang.org/grpc" 59 ) 60 61 func TestRegionRequestToSingleStore(t *testing.T) { 62 suite.Run(t, new(testRegionRequestToSingleStoreSuite)) 63 } 64 65 type testRegionRequestToSingleStoreSuite struct { 66 suite.Suite 67 cluster *mocktikv.Cluster 68 store uint64 69 peer uint64 70 region uint64 71 cache *RegionCache 72 bo *retry.Backoffer 73 regionRequestSender *RegionRequestSender 74 mvccStore mocktikv.MVCCStore 75 } 76 77 func (s *testRegionRequestToSingleStoreSuite) SetupTest() { 78 s.mvccStore = mocktikv.MustNewMVCCStore() 79 s.cluster = mocktikv.NewCluster(s.mvccStore) 80 s.store, s.peer, s.region = mocktikv.BootstrapWithSingleStore(s.cluster) 81 pdCli := &CodecPDClient{mocktikv.NewPDClient(s.cluster)} 82 s.cache = NewRegionCache(pdCli) 83 s.bo = retry.NewNoopBackoff(context.Background()) 84 client := mocktikv.NewRPCClient(s.cluster, s.mvccStore, nil) 85 s.regionRequestSender = NewRegionRequestSender(s.cache, client) 86 } 87 88 func (s *testRegionRequestToSingleStoreSuite) TearDownTest() { 89 s.cache.Close() 90 s.mvccStore.Close() 91 } 92 93 type fnClient struct { 94 fn func(ctx context.Context, addr string, req *tikvrpc.Request, timeout time.Duration) (*tikvrpc.Response, error) 95 } 96 97 func (f *fnClient) Close() error { 98 return nil 99 } 100 101 func (f *fnClient) SendRequest(ctx context.Context, addr string, req *tikvrpc.Request, timeout time.Duration) (*tikvrpc.Response, error) { 102 return f.fn(ctx, addr, req, timeout) 103 } 104 105 func (s *testRegionRequestToSingleStoreSuite) TestOnRegionError() { 106 req := tikvrpc.NewRequest(tikvrpc.CmdRawPut, &kvrpcpb.RawPutRequest{ 107 Key: []byte("key"), 108 Value: []byte("value"), 109 }) 110 region, err := s.cache.LocateRegionByID(s.bo, s.region) 111 s.Nil(err) 112 s.NotNil(region) 113 114 // test stale command retry. 115 func() { 116 oc := s.regionRequestSender.client 117 defer func() { 118 s.regionRequestSender.client = oc 119 }() 120 s.regionRequestSender.client = &fnClient{func(ctx context.Context, addr string, req *tikvrpc.Request, timeout time.Duration) (response *tikvrpc.Response, err error) { 121 staleResp := &tikvrpc.Response{Resp: &kvrpcpb.GetResponse{ 122 RegionError: &errorpb.Error{StaleCommand: &errorpb.StaleCommand{}}, 123 }} 124 return staleResp, nil 125 }} 126 bo := retry.NewBackofferWithVars(context.Background(), 5, nil) 127 resp, err := s.regionRequestSender.SendReq(bo, req, region.Region, time.Second) 128 s.Nil(err) 129 s.NotNil(resp) 130 regionErr, _ := resp.GetRegionError() 131 s.NotNil(regionErr) 132 }() 133 } 134 135 func (s *testRegionRequestToSingleStoreSuite) TestOnSendFailedWithStoreRestart() { 136 req := tikvrpc.NewRequest(tikvrpc.CmdRawPut, &kvrpcpb.RawPutRequest{ 137 Key: []byte("key"), 138 Value: []byte("value"), 139 }) 140 region, err := s.cache.LocateRegionByID(s.bo, s.region) 141 s.Nil(err) 142 s.NotNil(region) 143 resp, err := s.regionRequestSender.SendReq(s.bo, req, region.Region, time.Second) 144 s.Nil(err) 145 s.NotNil(resp.Resp) 146 s.Nil(s.regionRequestSender.rpcError) 147 148 // stop store. 149 s.cluster.StopStore(s.store) 150 _, err = s.regionRequestSender.SendReq(s.bo, req, region.Region, time.Second) 151 s.NotNil(err) 152 // The RPC error shouldn't be nil since it failed to sent the request. 153 s.NotNil(s.regionRequestSender.rpcError) 154 155 // start store. 156 s.cluster.StartStore(s.store) 157 158 // locate region again is needed 159 // since last request on the region failed and region's info had been cleared. 160 region, err = s.cache.LocateRegionByID(s.bo, s.region) 161 s.Nil(err) 162 s.NotNil(region) 163 s.NotNil(s.regionRequestSender.rpcError) 164 resp, err = s.regionRequestSender.SendReq(s.bo, req, region.Region, time.Second) 165 s.Nil(err) 166 s.NotNil(resp.Resp) 167 } 168 169 func (s *testRegionRequestToSingleStoreSuite) TestOnSendFailedWithCloseKnownStoreThenUseNewOne() { 170 req := tikvrpc.NewRequest(tikvrpc.CmdRawPut, &kvrpcpb.RawPutRequest{ 171 Key: []byte("key"), 172 Value: []byte("value"), 173 }) 174 175 // add new store2 and make store2 as leader. 176 store2 := s.cluster.AllocID() 177 peer2 := s.cluster.AllocID() 178 s.cluster.AddStore(store2, fmt.Sprintf("store%d", store2)) 179 s.cluster.AddPeer(s.region, store2, peer2) 180 s.cluster.ChangeLeader(s.region, peer2) 181 182 region, err := s.cache.LocateRegionByID(s.bo, s.region) 183 s.Nil(err) 184 s.NotNil(region) 185 resp, err := s.regionRequestSender.SendReq(s.bo, req, region.Region, time.Second) 186 s.Nil(err) 187 s.NotNil(resp.Resp) 188 189 // stop store2 and make store1 as new leader. 190 s.cluster.StopStore(store2) 191 s.cluster.ChangeLeader(s.region, s.peer) 192 193 // send to store2 fail and send to new leader store1. 194 bo2 := retry.NewBackofferWithVars(context.Background(), 100, nil) 195 resp, err = s.regionRequestSender.SendReq(bo2, req, region.Region, time.Second) 196 s.Nil(err) 197 regionErr, err := resp.GetRegionError() 198 s.Nil(err) 199 s.Nil(regionErr) 200 s.NotNil(resp.Resp) 201 } 202 203 func (s *testRegionRequestToSingleStoreSuite) TestSendReqCtx() { 204 req := tikvrpc.NewRequest(tikvrpc.CmdRawPut, &kvrpcpb.RawPutRequest{ 205 Key: []byte("key"), 206 Value: []byte("value"), 207 }) 208 region, err := s.cache.LocateRegionByID(s.bo, s.region) 209 s.Nil(err) 210 s.NotNil(region) 211 resp, ctx, err := s.regionRequestSender.SendReqCtx(s.bo, req, region.Region, time.Second, tikvrpc.TiKV) 212 s.Nil(err) 213 s.NotNil(resp.Resp) 214 s.NotNil(ctx) 215 req.ReplicaRead = true 216 resp, ctx, err = s.regionRequestSender.SendReqCtx(s.bo, req, region.Region, time.Second, tikvrpc.TiKV) 217 s.Nil(err) 218 s.NotNil(resp.Resp) 219 s.NotNil(ctx) 220 } 221 222 func (s *testRegionRequestToSingleStoreSuite) TestOnSendFailedWithCancelled() { 223 req := tikvrpc.NewRequest(tikvrpc.CmdRawPut, &kvrpcpb.RawPutRequest{ 224 Key: []byte("key"), 225 Value: []byte("value"), 226 }) 227 region, err := s.cache.LocateRegionByID(s.bo, s.region) 228 s.Nil(err) 229 s.NotNil(region) 230 resp, err := s.regionRequestSender.SendReq(s.bo, req, region.Region, time.Second) 231 s.Nil(err) 232 s.NotNil(resp.Resp) 233 234 // set store to cancel state. 235 s.cluster.CancelStore(s.store) 236 // locate region again is needed 237 // since last request on the region failed and region's info had been cleared. 238 _, err = s.regionRequestSender.SendReq(s.bo, req, region.Region, time.Second) 239 s.NotNil(err) 240 s.Equal(errors.Cause(err), context.Canceled) 241 242 // set store to normal state. 243 s.cluster.UnCancelStore(s.store) 244 region, err = s.cache.LocateRegionByID(s.bo, s.region) 245 s.Nil(err) 246 s.NotNil(region) 247 resp, err = s.regionRequestSender.SendReq(s.bo, req, region.Region, time.Second) 248 s.Nil(err) 249 s.NotNil(resp.Resp) 250 } 251 252 func (s *testRegionRequestToSingleStoreSuite) TestNoReloadRegionWhenCtxCanceled() { 253 req := tikvrpc.NewRequest(tikvrpc.CmdRawPut, &kvrpcpb.RawPutRequest{ 254 Key: []byte("key"), 255 Value: []byte("value"), 256 }) 257 region, err := s.cache.LocateRegionByID(s.bo, s.region) 258 s.Nil(err) 259 s.NotNil(region) 260 261 sender := s.regionRequestSender 262 bo, cancel := s.bo.Fork() 263 cancel() 264 // Call SendKVReq with a canceled context. 265 _, err = sender.SendReq(bo, req, region.Region, time.Second) 266 // Check this kind of error won't cause region cache drop. 267 s.Equal(errors.Cause(err), context.Canceled) 268 s.NotNil(sender.regionCache.getRegionByIDFromCache(s.region)) 269 } 270 271 // cancelContextClient wraps rpcClient and always cancels context before sending requests. 272 type cancelContextClient struct { 273 client.Client 274 redirectAddr string 275 } 276 277 func (c *cancelContextClient) SendRequest(ctx context.Context, addr string, req *tikvrpc.Request, timeout time.Duration) (*tikvrpc.Response, error) { 278 childCtx, cancel := context.WithCancel(ctx) 279 cancel() 280 return c.Client.SendRequest(childCtx, c.redirectAddr, req, timeout) 281 } 282 283 // mockTikvGrpcServer mock a tikv gprc server for testing. 284 type mockTikvGrpcServer struct{} 285 286 // KvGet commands with mvcc/txn supported. 287 func (s *mockTikvGrpcServer) KvGet(context.Context, *kvrpcpb.GetRequest) (*kvrpcpb.GetResponse, error) { 288 return nil, errors.New("unreachable") 289 } 290 func (s *mockTikvGrpcServer) KvScan(context.Context, *kvrpcpb.ScanRequest) (*kvrpcpb.ScanResponse, error) { 291 return nil, errors.New("unreachable") 292 } 293 func (s *mockTikvGrpcServer) KvPrewrite(context.Context, *kvrpcpb.PrewriteRequest) (*kvrpcpb.PrewriteResponse, error) { 294 return nil, errors.New("unreachable") 295 } 296 func (s *mockTikvGrpcServer) KvCommit(context.Context, *kvrpcpb.CommitRequest) (*kvrpcpb.CommitResponse, error) { 297 return nil, errors.New("unreachable") 298 } 299 func (s *mockTikvGrpcServer) KvImport(context.Context, *kvrpcpb.ImportRequest) (*kvrpcpb.ImportResponse, error) { 300 return nil, errors.New("unreachable") 301 } 302 func (s *mockTikvGrpcServer) KvCleanup(context.Context, *kvrpcpb.CleanupRequest) (*kvrpcpb.CleanupResponse, error) { 303 return nil, errors.New("unreachable") 304 } 305 func (s *mockTikvGrpcServer) KvBatchGet(context.Context, *kvrpcpb.BatchGetRequest) (*kvrpcpb.BatchGetResponse, error) { 306 return nil, errors.New("unreachable") 307 } 308 func (s *mockTikvGrpcServer) KvBatchRollback(context.Context, *kvrpcpb.BatchRollbackRequest) (*kvrpcpb.BatchRollbackResponse, error) { 309 return nil, errors.New("unreachable") 310 } 311 func (s *mockTikvGrpcServer) KvScanLock(context.Context, *kvrpcpb.ScanLockRequest) (*kvrpcpb.ScanLockResponse, error) { 312 return nil, errors.New("unreachable") 313 } 314 func (s *mockTikvGrpcServer) KvResolveLock(context.Context, *kvrpcpb.ResolveLockRequest) (*kvrpcpb.ResolveLockResponse, error) { 315 return nil, errors.New("unreachable") 316 } 317 func (s *mockTikvGrpcServer) KvPessimisticLock(context.Context, *kvrpcpb.PessimisticLockRequest) (*kvrpcpb.PessimisticLockResponse, error) { 318 return nil, errors.New("unreachable") 319 } 320 func (s *mockTikvGrpcServer) KVPessimisticRollback(context.Context, *kvrpcpb.PessimisticRollbackRequest) (*kvrpcpb.PessimisticRollbackResponse, error) { 321 return nil, errors.New("unreachable") 322 } 323 func (s *mockTikvGrpcServer) KvCheckTxnStatus(ctx context.Context, in *kvrpcpb.CheckTxnStatusRequest) (*kvrpcpb.CheckTxnStatusResponse, error) { 324 return nil, errors.New("unreachable") 325 } 326 func (s *mockTikvGrpcServer) KvCheckSecondaryLocks(ctx context.Context, in *kvrpcpb.CheckSecondaryLocksRequest) (*kvrpcpb.CheckSecondaryLocksResponse, error) { 327 return nil, errors.New("unreachable") 328 } 329 func (s *mockTikvGrpcServer) KvTxnHeartBeat(ctx context.Context, in *kvrpcpb.TxnHeartBeatRequest) (*kvrpcpb.TxnHeartBeatResponse, error) { 330 return nil, errors.New("unreachable") 331 } 332 func (s *mockTikvGrpcServer) KvGC(context.Context, *kvrpcpb.GCRequest) (*kvrpcpb.GCResponse, error) { 333 return nil, errors.New("unreachable") 334 } 335 func (s *mockTikvGrpcServer) KvDeleteRange(context.Context, *kvrpcpb.DeleteRangeRequest) (*kvrpcpb.DeleteRangeResponse, error) { 336 return nil, errors.New("unreachable") 337 } 338 func (s *mockTikvGrpcServer) RawGet(context.Context, *kvrpcpb.RawGetRequest) (*kvrpcpb.RawGetResponse, error) { 339 return nil, errors.New("unreachable") 340 } 341 func (s *mockTikvGrpcServer) RawBatchGet(context.Context, *kvrpcpb.RawBatchGetRequest) (*kvrpcpb.RawBatchGetResponse, error) { 342 return nil, errors.New("unreachable") 343 } 344 func (s *mockTikvGrpcServer) RawPut(context.Context, *kvrpcpb.RawPutRequest) (*kvrpcpb.RawPutResponse, error) { 345 return nil, errors.New("unreachable") 346 } 347 func (s *mockTikvGrpcServer) RawBatchPut(context.Context, *kvrpcpb.RawBatchPutRequest) (*kvrpcpb.RawBatchPutResponse, error) { 348 return nil, errors.New("unreachable") 349 } 350 func (s *mockTikvGrpcServer) RawDelete(context.Context, *kvrpcpb.RawDeleteRequest) (*kvrpcpb.RawDeleteResponse, error) { 351 return nil, errors.New("unreachable") 352 } 353 func (s *mockTikvGrpcServer) RawBatchDelete(context.Context, *kvrpcpb.RawBatchDeleteRequest) (*kvrpcpb.RawBatchDeleteResponse, error) { 354 return nil, errors.New("unreachable") 355 } 356 func (s *mockTikvGrpcServer) RawScan(context.Context, *kvrpcpb.RawScanRequest) (*kvrpcpb.RawScanResponse, error) { 357 return nil, errors.New("unreachable") 358 } 359 func (s *mockTikvGrpcServer) RawDeleteRange(context.Context, *kvrpcpb.RawDeleteRangeRequest) (*kvrpcpb.RawDeleteRangeResponse, error) { 360 return nil, errors.New("unreachable") 361 } 362 func (s *mockTikvGrpcServer) RawBatchScan(context.Context, *kvrpcpb.RawBatchScanRequest) (*kvrpcpb.RawBatchScanResponse, error) { 363 return nil, errors.New("unreachable") 364 } 365 func (s *mockTikvGrpcServer) RawGetKeyTTL(context.Context, *kvrpcpb.RawGetKeyTTLRequest) (*kvrpcpb.RawGetKeyTTLResponse, error) { 366 return nil, errors.New("unreachable") 367 } 368 func (s *mockTikvGrpcServer) UnsafeDestroyRange(context.Context, *kvrpcpb.UnsafeDestroyRangeRequest) (*kvrpcpb.UnsafeDestroyRangeResponse, error) { 369 return nil, errors.New("unreachable") 370 } 371 func (s *mockTikvGrpcServer) RegisterLockObserver(context.Context, *kvrpcpb.RegisterLockObserverRequest) (*kvrpcpb.RegisterLockObserverResponse, error) { 372 return nil, errors.New("unreachable") 373 } 374 func (s *mockTikvGrpcServer) CheckLockObserver(context.Context, *kvrpcpb.CheckLockObserverRequest) (*kvrpcpb.CheckLockObserverResponse, error) { 375 return nil, errors.New("unreachable") 376 } 377 func (s *mockTikvGrpcServer) RemoveLockObserver(context.Context, *kvrpcpb.RemoveLockObserverRequest) (*kvrpcpb.RemoveLockObserverResponse, error) { 378 return nil, errors.New("unreachable") 379 } 380 func (s *mockTikvGrpcServer) PhysicalScanLock(context.Context, *kvrpcpb.PhysicalScanLockRequest) (*kvrpcpb.PhysicalScanLockResponse, error) { 381 return nil, errors.New("unreachable") 382 } 383 func (s *mockTikvGrpcServer) Coprocessor(context.Context, *coprocessor.Request) (*coprocessor.Response, error) { 384 return nil, errors.New("unreachable") 385 } 386 func (s *mockTikvGrpcServer) BatchCoprocessor(*coprocessor.BatchRequest, tikvpb.Tikv_BatchCoprocessorServer) error { 387 return errors.New("unreachable") 388 } 389 func (s *mockTikvGrpcServer) RawCoprocessor(context.Context, *kvrpcpb.RawCoprocessorRequest) (*kvrpcpb.RawCoprocessorResponse, error) { 390 return nil, errors.New("unreachable") 391 } 392 func (s *mockTikvGrpcServer) DispatchMPPTask(context.Context, *mpp.DispatchTaskRequest) (*mpp.DispatchTaskResponse, error) { 393 return nil, errors.New("unreachable") 394 } 395 396 func (s *mockTikvGrpcServer) IsAlive(context.Context, *mpp.IsAliveRequest) (*mpp.IsAliveResponse, error) { 397 return nil, errors.New("unreachable") 398 } 399 400 func (s *mockTikvGrpcServer) EstablishMPPConnection(*mpp.EstablishMPPConnectionRequest, tikvpb.Tikv_EstablishMPPConnectionServer) error { 401 return errors.New("unreachable") 402 } 403 func (s *mockTikvGrpcServer) CancelMPPTask(context.Context, *mpp.CancelTaskRequest) (*mpp.CancelTaskResponse, error) { 404 return nil, errors.New("unreachable") 405 } 406 func (s *mockTikvGrpcServer) Raft(tikvpb.Tikv_RaftServer) error { 407 return errors.New("unreachable") 408 } 409 func (s *mockTikvGrpcServer) BatchRaft(tikvpb.Tikv_BatchRaftServer) error { 410 return errors.New("unreachable") 411 } 412 func (s *mockTikvGrpcServer) Snapshot(tikvpb.Tikv_SnapshotServer) error { 413 return errors.New("unreachable") 414 } 415 func (s *mockTikvGrpcServer) MvccGetByKey(context.Context, *kvrpcpb.MvccGetByKeyRequest) (*kvrpcpb.MvccGetByKeyResponse, error) { 416 return nil, errors.New("unreachable") 417 } 418 func (s *mockTikvGrpcServer) MvccGetByStartTs(context.Context, *kvrpcpb.MvccGetByStartTsRequest) (*kvrpcpb.MvccGetByStartTsResponse, error) { 419 return nil, errors.New("unreachable") 420 } 421 func (s *mockTikvGrpcServer) SplitRegion(context.Context, *kvrpcpb.SplitRegionRequest) (*kvrpcpb.SplitRegionResponse, error) { 422 return nil, errors.New("unreachable") 423 } 424 425 func (s *mockTikvGrpcServer) CoprocessorStream(*coprocessor.Request, tikvpb.Tikv_CoprocessorStreamServer) error { 426 return errors.New("unreachable") 427 } 428 429 func (s *mockTikvGrpcServer) BatchCommands(tikvpb.Tikv_BatchCommandsServer) error { 430 return errors.New("unreachable") 431 } 432 433 func (s *mockTikvGrpcServer) ReadIndex(context.Context, *kvrpcpb.ReadIndexRequest) (*kvrpcpb.ReadIndexResponse, error) { 434 return nil, errors.New("unreachable") 435 } 436 437 func (s *mockTikvGrpcServer) CheckLeader(context.Context, *kvrpcpb.CheckLeaderRequest) (*kvrpcpb.CheckLeaderResponse, error) { 438 return nil, errors.New("unreachable") 439 } 440 441 func (s *mockTikvGrpcServer) GetStoreSafeTS(context.Context, *kvrpcpb.StoreSafeTSRequest) (*kvrpcpb.StoreSafeTSResponse, error) { 442 return nil, errors.New("unreachable") 443 } 444 445 func (s *mockTikvGrpcServer) RawCompareAndSwap(context.Context, *kvrpcpb.RawCASRequest) (*kvrpcpb.RawCASResponse, error) { 446 return nil, errors.New("unreachable") 447 } 448 449 func (s *mockTikvGrpcServer) GetLockWaitInfo(context.Context, *kvrpcpb.GetLockWaitInfoRequest) (*kvrpcpb.GetLockWaitInfoResponse, error) { 450 return nil, errors.New("unreachable") 451 } 452 453 func (s *mockTikvGrpcServer) RawChecksum(context.Context, *kvrpcpb.RawChecksumRequest) (*kvrpcpb.RawChecksumResponse, error) { 454 return nil, errors.New("unreachable") 455 } 456 457 func (s *testRegionRequestToSingleStoreSuite) TestNoReloadRegionForGrpcWhenCtxCanceled() { 458 // prepare a mock tikv grpc server 459 addr := "localhost:56341" 460 lis, err := net.Listen("tcp", addr) 461 s.Nil(err) 462 server := grpc.NewServer() 463 tikvpb.RegisterTikvServer(server, &mockTikvGrpcServer{}) 464 wg := &sync.WaitGroup{} 465 wg.Add(1) 466 go func() { 467 server.Serve(lis) 468 wg.Done() 469 }() 470 471 cli := client.NewRPCClient() 472 sender := NewRegionRequestSender(s.cache, cli) 473 req := tikvrpc.NewRequest(tikvrpc.CmdRawPut, &kvrpcpb.RawPutRequest{ 474 Key: []byte("key"), 475 Value: []byte("value"), 476 }) 477 region, err := s.cache.LocateRegionByID(s.bo, s.region) 478 s.Nil(err) 479 480 bo, cancel := s.bo.Fork() 481 cancel() 482 _, err = sender.SendReq(bo, req, region.Region, 3*time.Second) 483 s.Equal(errors.Cause(err), context.Canceled) 484 s.NotNil(s.cache.getRegionByIDFromCache(s.region)) 485 486 // Just for covering error code = codes.Canceled. 487 client1 := &cancelContextClient{ 488 Client: client.NewRPCClient(), 489 redirectAddr: addr, 490 } 491 sender = NewRegionRequestSender(s.cache, client1) 492 sender.SendReq(s.bo, req, region.Region, 3*time.Second) 493 494 // cleanup 495 server.Stop() 496 wg.Wait() 497 cli.Close() 498 client1.Close() 499 } 500 501 func (s *testRegionRequestToSingleStoreSuite) TestOnMaxTimestampNotSyncedError() { 502 req := tikvrpc.NewRequest(tikvrpc.CmdPrewrite, &kvrpcpb.PrewriteRequest{}) 503 region, err := s.cache.LocateRegionByID(s.bo, s.region) 504 s.Nil(err) 505 s.NotNil(region) 506 507 // test retry for max timestamp not synced 508 func() { 509 oc := s.regionRequestSender.client 510 defer func() { 511 s.regionRequestSender.client = oc 512 }() 513 count := 0 514 s.regionRequestSender.client = &fnClient{func(ctx context.Context, addr string, req *tikvrpc.Request, timeout time.Duration) (response *tikvrpc.Response, err error) { 515 count++ 516 var resp *tikvrpc.Response 517 if count < 3 { 518 resp = &tikvrpc.Response{Resp: &kvrpcpb.PrewriteResponse{ 519 RegionError: &errorpb.Error{MaxTimestampNotSynced: &errorpb.MaxTimestampNotSynced{}}, 520 }} 521 } else { 522 resp = &tikvrpc.Response{Resp: &kvrpcpb.PrewriteResponse{}} 523 } 524 return resp, nil 525 }} 526 bo := retry.NewBackofferWithVars(context.Background(), 5, nil) 527 resp, err := s.regionRequestSender.SendReq(bo, req, region.Region, time.Second) 528 s.Nil(err) 529 s.NotNil(resp) 530 }() 531 } 532 533 func (s *testRegionRequestToSingleStoreSuite) TestGetRegionByIDFromCache() { 534 region, err := s.cache.LocateRegionByID(s.bo, s.region) 535 s.Nil(err) 536 s.NotNil(region) 537 538 // test kv epochNotMatch return empty regions 539 s.cache.OnRegionEpochNotMatch(s.bo, &RPCContext{Region: region.Region, Store: &Store{storeID: s.store}}, []*metapb.Region{}) 540 s.Nil(err) 541 r := s.cache.getRegionByIDFromCache(s.region) 542 s.Nil(r) 543 544 // refill cache 545 region, err = s.cache.LocateRegionByID(s.bo, s.region) 546 s.Nil(err) 547 s.NotNil(region) 548 549 // test kv load new region with new start-key and new epoch 550 v2 := region.Region.confVer + 1 551 r2 := metapb.Region{Id: region.Region.id, RegionEpoch: &metapb.RegionEpoch{Version: region.Region.ver, ConfVer: v2}, StartKey: []byte{1}} 552 st := &Store{storeID: s.store} 553 s.cache.insertRegionToCache(&Region{meta: &r2, store: unsafe.Pointer(st), lastAccess: time.Now().Unix()}) 554 region, err = s.cache.LocateRegionByID(s.bo, s.region) 555 s.Nil(err) 556 s.NotNil(region) 557 s.Equal(region.Region.confVer, v2) 558 s.Equal(region.Region.ver, region.Region.ver) 559 560 v3 := region.Region.confVer + 1 561 r3 := metapb.Region{Id: region.Region.id, RegionEpoch: &metapb.RegionEpoch{Version: v3, ConfVer: region.Region.confVer}, StartKey: []byte{2}} 562 st = &Store{storeID: s.store} 563 s.cache.insertRegionToCache(&Region{meta: &r3, store: unsafe.Pointer(st), lastAccess: time.Now().Unix()}) 564 region, err = s.cache.LocateRegionByID(s.bo, s.region) 565 s.Nil(err) 566 s.NotNil(region) 567 s.Equal(region.Region.confVer, region.Region.confVer) 568 s.Equal(region.Region.ver, v3) 569 }