Repository: tikv/client-go
Pull request #606 (2022-10-14 09:32:28)

Introduce the FlashbackNotPrepared error
Signed-off-by: JmPotato <ghzpotato@gmail.com>

JmPotato: /cc @Defined2014 @sticnarf @Connor1996 
disksing: It looks there is somethong wrong with integration test. Could you check why it is failing?
Connor1996: > Signed-off-by: JmPotato [ghzpotato@gmail.com](mailto:ghzpotato@gmail.com)
> 
> Since the flashback state check is before other checks like EpochNotMatch, so we need to invalidate the region cache also.

Why not move the order of the check after `EpochNotMatch`?
JmPotato: > It looks there is somethong wrong with integration test. Could you check why it is failing?

I think it's the same problem as https://github.com/tikv/client-go/issues/449.

Patch:
diff --git a/error/error.go b/error/error.go
index 3d7272d..82a8c3d 100644
--- a/error/error.go
+++ b/error/error.go
@@ -91,6 +91,8 @@ var (
 	ErrRegionRecoveryInProgress = errors.New("region is being online unsafe recovered")
 	// ErrRegionFlashbackInProgress is the error when a region in the flashback progress receive any other request.
 	ErrRegionFlashbackInProgress = errors.New("region is in the flashback progress")
+	// ErrRegionFlashbackNotPrepared is the error when a region is not prepared for the flashback first.
+	ErrRegionFlashbackNotPrepared = errors.New("region is not prepared for the flashback")
 	// ErrUnknown is the unknow error.
 	ErrUnknown = errors.New("unknow")
 	// ErrResultUndetermined is the error when execution result is unknown.
diff --git a/go.mod b/go.mod
index f6d0c53..6991a55 100644
--- a/go.mod
+++ b/go.mod
@@ -13,7 +13,7 @@ require (
 	github.com/opentracing/opentracing-go v1.2.0
 	github.com/pingcap/failpoint v0.0.0-20210918120811-547c13e3eb00
 	github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989
-	github.com/pingcap/kvproto v0.0.0-20220929075948-06e08d5ed64c
+	github.com/pingcap/kvproto v0.0.0-20221014081430-26e28e6a281a
 	github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee
 	github.com/pkg/errors v0.9.1
 	github.com/prometheus/client_golang v1.11.0
diff --git a/go.sum b/go.sum
index c975e11..4ab2846 100644
--- a/go.sum
+++ b/go.sum
@@ -157,6 +157,8 @@ github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989/go.mod h1:O17Xtb
 github.com/pingcap/kvproto v0.0.0-20220510035547-0e2f26c0a46a/go.mod h1:OYtxs0786qojVTmkVeufx93xe+jUgm56GUYRIKnmaGI=
 github.com/pingcap/kvproto v0.0.0-20220929075948-06e08d5ed64c h1:ceg4xjEEXNgPsScTQ5dtidiltLF4h17Y/jUqfyLAy9E=
 github.com/pingcap/kvproto v0.0.0-20220929075948-06e08d5ed64c/go.mod h1:OYtxs0786qojVTmkVeufx93xe+jUgm56GUYRIKnmaGI=
+github.com/pingcap/kvproto v0.0.0-20221014081430-26e28e6a281a h1:McYxPhA8SHqfUtLfQHHN0fQl4dy93IkhlX4Pp2MKIFA=
+github.com/pingcap/kvproto v0.0.0-20221014081430-26e28e6a281a/go.mod h1:OYtxs0786qojVTmkVeufx93xe+jUgm56GUYRIKnmaGI=
 github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee h1:VO2t6IBpfvW34TdtD/G10VvnGqjLic1jzOuHjUb5VqM=
 github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
diff --git a/internal/locate/region_request.go b/internal/locate/region_request.go
index 2b640cd..8a1cc19 100644
--- a/internal/locate/region_request.go
+++ b/internal/locate/region_request.go
@@ -1391,6 +1391,8 @@ func regionErrorToLabel(e *errorpb.Error) string {
 		return "recovery_in_progress"
 	} else if e.GetFlashbackInProgress() != nil {
 		return "flashback_in_progress"
+	} else if e.GetFlashbackNotPrepared() != nil {
+		return "flashback_not_prepared"
 	}
 	return "unknown"
 }
@@ -1455,6 +1457,13 @@ func (s *RegionRequestSender) onRegionError(bo *retry.Backoffer, ctx *RPCContext
 		logutil.BgLogger().Debug("tikv reports `FlashbackInProgress`", zap.Stringer("req", req), zap.Stringer("ctx", ctx))
 		return false, errors.Errorf("region %d is in flashback progress", regionErr.GetFlashbackInProgress().GetRegionId())
 	}
+	// This error means a second-phase flashback request is sent to a region that is not
+	// prepared for the flashback before, it should stop retrying immediately to avoid
+	// unnecessary backoff.
+	if regionErr.GetFlashbackNotPrepared() != nil {
+		logutil.BgLogger().Debug("tikv reports `FlashbackNotPrepared`", zap.Stringer("req", req), zap.Stringer("ctx", ctx))
+		return false, errors.Errorf("region %d is not prepared for the flashback", regionErr.GetFlashbackNotPrepared().GetRegionId())
+	}
 
 	// This peer is removed from the region. Invalidate the region since it's too stale.
 	if regionErr.GetRegionNotFound() != nil {


Test patch:
diff --git a/integration_tests/go.mod b/integration_tests/go.mod
index 1bddb8b..cd9768a 100644
--- a/integration_tests/go.mod
+++ b/integration_tests/go.mod
@@ -6,7 +6,7 @@ require (
 	github.com/ninedraft/israce v0.0.3
 	github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c
 	github.com/pingcap/failpoint v0.0.0-20220423142525-ae43b7f4e5c3
-	github.com/pingcap/kvproto v0.0.0-20220929075948-06e08d5ed64c
+	github.com/pingcap/kvproto v0.0.0-20221014081430-26e28e6a281a
 	github.com/pingcap/tidb v1.1.0-beta.0.20220902042024-0482b2e83ed2
 	github.com/pkg/errors v0.9.1
 	github.com/stretchr/testify v1.8.0
diff --git a/integration_tests/go.sum b/integration_tests/go.sum
index 733a8b6..6366cb1 100644
--- a/integration_tests/go.sum
+++ b/integration_tests/go.sum
@@ -301,8 +301,8 @@ github.com/pingcap/fn v0.0.0-20200306044125-d5540d389059 h1:Pe2LbxRmbTfAoKJ65bZL
 github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989 h1:surzm05a8C9dN8dIUmo4Be2+pMRb6f55i+UIYrluu2E=
 github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw=
 github.com/pingcap/kvproto v0.0.0-20220510035547-0e2f26c0a46a/go.mod h1:OYtxs0786qojVTmkVeufx93xe+jUgm56GUYRIKnmaGI=
-github.com/pingcap/kvproto v0.0.0-20220929075948-06e08d5ed64c h1:ceg4xjEEXNgPsScTQ5dtidiltLF4h17Y/jUqfyLAy9E=
-github.com/pingcap/kvproto v0.0.0-20220929075948-06e08d5ed64c/go.mod h1:OYtxs0786qojVTmkVeufx93xe+jUgm56GUYRIKnmaGI=
+github.com/pingcap/kvproto v0.0.0-20221014081430-26e28e6a281a h1:McYxPhA8SHqfUtLfQHHN0fQl4dy93IkhlX4Pp2MKIFA=
+github.com/pingcap/kvproto v0.0.0-20221014081430-26e28e6a281a/go.mod h1:OYtxs0786qojVTmkVeufx93xe+jUgm56GUYRIKnmaGI=
 github.com/pingcap/log v0.0.0-20200511115504-543df19646ad/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8=
 github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4=
 github.com/pingcap/log v1.1.0 h1:ELiPxACz7vdo1qAvvaWJg1NrYFoY6gqAh/+Uo6aXdD8=
diff --git a/internal/locate/region_cache_test.go b/internal/locate/region_cache_test.go
index 342e07d..3e92ac9 100644
--- a/internal/locate/region_cache_test.go
+++ b/internal/locate/region_cache_test.go
@@ -1593,7 +1593,7 @@ func (s *testRegionCacheSuite) TestRemoveIntersectingRegions() {
 	s.checkCache(1)
 }
 
-func (s *testRegionCacheSuite) TestShouldNotRetryFlashbackInProgress() {
+func (s *testRegionCacheSuite) TestShouldNotRetryFlashback() {
 	loc, err := s.cache.LocateKey(s.bo, []byte("a"))
 	s.NotNil(loc)
 	s.NoError(err)
@@ -1604,4 +1604,7 @@ func (s *testRegionCacheSuite) TestShouldNotRetryFlashbackInProgress() {
 	shouldRetry, err := reqSend.onRegionError(s.bo, ctx, nil, &errorpb.Error{FlashbackInProgress: &errorpb.FlashbackInProgress{}})
 	s.Error(err)
 	s.False(shouldRetry)
+	shouldRetry, err = reqSend.onRegionError(s.bo, ctx, nil, &errorpb.Error{FlashbackNotPrepared: &errorpb.FlashbackNotPrepared{}})
+	s.Error(err)
+	s.False(shouldRetry)
 }