Skip to content

Commit 0557634

Browse files
ti-chi-botlhy1024
andauthored
mcs: fix /config and /members tso forward logic (#9796) (#9804)
close #9797 Signed-off-by: ti-chi-bot <ti-community-prow-bot@tidb.io> Signed-off-by: lhy1024 <admin@liudos.us> Co-authored-by: lhy1024 <liuhanyang@pingcap.com> Co-authored-by: lhy1024 <admin@liudos.us>
1 parent 064b2ad commit 0557634

File tree

2 files changed

+64
-4
lines changed

2 files changed

+64
-4
lines changed

pkg/mcs/tso/server/apis/v1/api.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ func NewService(srv *tsoserver.Service) *Service {
8888
apiHandlerEngine.GET("status", utils.StatusHandler)
8989
pprof.Register(apiHandlerEngine)
9090
root := apiHandlerEngine.Group(APIPathPrefix)
91-
root.Use(multiservicesapi.ServiceRedirector())
9291
s := &Service{
9392
srv: srv,
9493
apiHandlerEngine: apiHandlerEngine,
@@ -106,7 +105,8 @@ func NewService(srv *tsoserver.Service) *Service {
106105
// RegisterAdminRouter registers the router of the TSO admin handler.
107106
func (s *Service) RegisterAdminRouter() {
108107
router := s.root.Group("admin")
109-
router.POST("/reset-ts", ResetTS)
108+
// reset-ts needs to be forwarded to the primary.
109+
router.POST("/reset-ts", multiservicesapi.ServiceRedirector(), ResetTS)
110110
router.PUT("/log", changeLogLevel)
111111
}
112112

@@ -131,7 +131,8 @@ func (s *Service) RegisterConfigRouter() {
131131
// RegisterPrimaryRouter registers the router of the primary handler.
132132
func (s *Service) RegisterPrimaryRouter() {
133133
router := s.root.Group("primary")
134-
router.POST("transfer", transferPrimary)
134+
// Transferring primary needs to be forwarded to the primary.
135+
router.POST("transfer", multiservicesapi.ServiceRedirector(), transferPrimary)
135136
}
136137

137138
func changeLogLevel(c *gin.Context) {

tests/integrations/mcs/tso/api_test.go

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func (suite *tsoAPITestSuite) SetupTest() {
6969
pdLeaderServer := suite.pdCluster.GetServer(leaderName)
7070
re.NoError(pdLeaderServer.BootstrapCluster())
7171
suite.backendEndpoints = pdLeaderServer.GetAddr()
72-
suite.tsoCluster, err = tests.NewTestTSOCluster(suite.ctx, 1, suite.backendEndpoints)
72+
suite.tsoCluster, err = tests.NewTestTSOCluster(suite.ctx, 2, suite.backendEndpoints)
7373
re.NoError(err)
7474
}
7575

@@ -280,3 +280,62 @@ func (suite *tsoAPITestSuite) TestConfig() {
280280
re.Equal(cfg.GetTSOUpdatePhysicalInterval(), primary.GetConfig().GetTSOUpdatePhysicalInterval())
281281
re.Equal(cfg.GetMaxResetTSGap(), primary.GetConfig().GetMaxResetTSGap())
282282
}
283+
284+
// TestForwardingBehavior specifically tests the API forwarding logic.
285+
func (suite *tsoAPITestSuite) TestForwardingBehavior() {
286+
re := suite.Require()
287+
288+
primary := suite.tsoCluster.WaitForDefaultPrimaryServing(re)
289+
re.NotNil(primary)
290+
var follower *tso.Server
291+
for _, srv := range suite.tsoCluster.GetServers() {
292+
if srv.Name() != primary.Name() {
293+
follower = srv
294+
break
295+
}
296+
}
297+
re.NotNil(follower)
298+
re.True(primary.IsServing())
299+
re.False(follower.IsServing())
300+
re.NotEqual(follower.GetConfig().GetListenAddr(), primary.GetConfig().GetListenAddr())
301+
302+
followerAddr := follower.GetAddr()
303+
followerURL := func(path string) string {
304+
return fmt.Sprintf("%s%s%s", followerAddr, apis.APIPathPrefix, path)
305+
}
306+
307+
// Test: PUT /admin/log should be handled by the follower locally.
308+
logURL := followerURL("/admin/log")
309+
level := "debug"
310+
logPayload, err := json.Marshal(level)
311+
re.NoError(err)
312+
req, _ := http.NewRequest(http.MethodPut, logURL, bytes.NewBuffer(logPayload))
313+
req.Header.Set("Content-Type", "application/json")
314+
resp, err := tests.TestDialClient.Do(req)
315+
re.NoError(err)
316+
defer resp.Body.Close()
317+
re.Equal(http.StatusOK, resp.StatusCode)
318+
319+
// Test: GET /config should be handled by the follower locally.
320+
configURL := followerURL("/config")
321+
var followerCfg tso.Config
322+
err = testutil.ReadGetJSON(re, tests.TestDialClient, configURL, &followerCfg)
323+
re.NoError(err)
324+
re.Equal(follower.GetConfig().GetListenAddr(), followerCfg.GetListenAddr())
325+
re.NotEqual(primary.GetConfig().GetListenAddr(), followerCfg.GetListenAddr())
326+
re.Equal(level, followerCfg.Log.Level)
327+
328+
// Test: GET /keyspace-groups/members should be handled by the follower locally.
329+
membersURL := followerURL("/keyspace-groups/members")
330+
var kgms map[uint32]*apis.KeyspaceGroupMember
331+
err = testutil.ReadGetJSON(re, tests.TestDialClient, membersURL, &kgms)
332+
re.NoError(err)
333+
re.Len(kgms, 1)
334+
kgm := kgms[constant.DefaultKeyspaceGroupID]
335+
re.NotNil(kgm)
336+
re.Len(kgm.Member.ListenUrls, 1)
337+
respListenURL := kgm.Member.ListenUrls[0]
338+
re.Equal(follower.GetConfig().GetListenAddr(), respListenURL)
339+
re.NotEqual(primary.GetConfig().GetListenAddr(), respListenURL)
340+
re.False(kgm.IsPrimary)
341+
}

0 commit comments

Comments
 (0)