From 3b0a512a9db79ffd8aad4f6090c94e3baed4bc8c Mon Sep 17 00:00:00 2001
From: Lucas <nkcs_lykx@hotmail.com>
Date: Thu, 9 Feb 2023 09:09:59 +0800
Subject: [PATCH] ReplicaReadMode: introduce new replica_read mode
 `PreferLeader`. (#40906)

close pingcap/tidb#40905
---
 kv/option.go                    | 2 ++
 sessionctx/variable/sysvar.go   | 4 +++-
 store/driver/options/options.go | 2 ++
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/kv/option.go b/kv/option.go
index d779ff61ac215..631e69da7613d 100644
--- a/kv/option.go
+++ b/kv/option.go
@@ -117,6 +117,8 @@ const (
 	ReplicaReadClosestAdaptive
 	// ReplicaReadLearner stands for 'read from learner'.
 	ReplicaReadLearner
+	// ReplicaReadPreferLeader stands for 'read from leader and auto-turn to followers if leader is abnormal'.
+	ReplicaReadPreferLeader
 )
 
 // IsFollowerRead checks if follower is going to be used to read data.
diff --git a/sessionctx/variable/sysvar.go b/sessionctx/variable/sysvar.go
index 3da39a2ef80e9..068152b3601aa 100644
--- a/sessionctx/variable/sysvar.go
+++ b/sessionctx/variable/sysvar.go
@@ -1801,7 +1801,7 @@ var defaultSysVars = []*SysVar{
 		s.NoopFuncsMode = TiDBOptOnOffWarn(val)
 		return nil
 	}},
-	{Scope: ScopeGlobal | ScopeSession, Name: TiDBReplicaRead, Value: "leader", Type: TypeEnum, PossibleValues: []string{"leader", "follower", "leader-and-follower", "closest-replicas", "closest-adaptive", "learner"}, SetSession: func(s *SessionVars, val string) error {
+	{Scope: ScopeGlobal | ScopeSession, Name: TiDBReplicaRead, Value: "leader", Type: TypeEnum, PossibleValues: []string{"leader", "prefer-leader", "follower", "leader-and-follower", "closest-replicas", "closest-adaptive", "learner"}, SetSession: func(s *SessionVars, val string) error {
 		if strings.EqualFold(val, "follower") {
 			s.SetReplicaRead(kv.ReplicaReadFollower)
 		} else if strings.EqualFold(val, "leader-and-follower") {
@@ -1814,6 +1814,8 @@ var defaultSysVars = []*SysVar{
 			s.SetReplicaRead(kv.ReplicaReadClosestAdaptive)
 		} else if strings.EqualFold(val, "learner") {
 			s.SetReplicaRead(kv.ReplicaReadLearner)
+		} else if strings.EqualFold(val, "prefer-leader") {
+			s.SetReplicaRead(kv.ReplicaReadPreferLeader)
 		}
 		return nil
 	}},
diff --git a/store/driver/options/options.go b/store/driver/options/options.go
index f3d5471aa440f..c2b3b52e177b8 100644
--- a/store/driver/options/options.go
+++ b/store/driver/options/options.go
@@ -34,6 +34,8 @@ func GetTiKVReplicaReadType(t kv.ReplicaReadType) storekv.ReplicaReadType {
 		return storekv.ReplicaReadMixed
 	case kv.ReplicaReadLearner:
 		return storekv.ReplicaReadLearner
+	case kv.ReplicaReadPreferLeader:
+		return storekv.ReplicaReadPreferLeader
 	}
 	return 0
 }