Skip to content

Commit f59aebd

Browse files
authored
mcs: fix /config and /members tso forward logic (#9796)
close #9797 Signed-off-by: lhy1024 <admin@liudos.us>
1 parent 471d023 commit f59aebd

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
@@ -92,7 +92,6 @@ func NewService(srv *tsoserver.Service) *Service {
9292
apiHandlerEngine.GET("health", getHealth)
9393
pprof.Register(apiHandlerEngine)
9494
root := apiHandlerEngine.Group(APIPathPrefix)
95-
root.Use(multiservicesapi.ServiceRedirector())
9695
s := &Service{
9796
srv: srv,
9897
apiHandlerEngine: apiHandlerEngine,
@@ -112,7 +111,8 @@ func NewService(srv *tsoserver.Service) *Service {
112111
// RegisterAdminRouter registers the router of the TSO admin handler.
113112
func (s *Service) RegisterAdminRouter() {
114113
router := s.root.Group("admin")
115-
router.POST("/reset-ts", resetTS)
114+
// reset-ts needs to be forwarded to the primary.
115+
router.POST("/reset-ts", multiservicesapi.ServiceRedirector(), resetTS)
116116
router.PUT("/log", changeLogLevel)
117117
}
118118

@@ -137,7 +137,8 @@ func (s *Service) RegisterConfigRouter() {
137137
// RegisterPrimaryRouter registers the router of the primary handler.
138138
func (s *Service) RegisterPrimaryRouter() {
139139
router := s.root.Group("primary")
140-
router.POST("transfer", transferPrimary)
140+
// Transferring primary needs to be forwarded to the primary.
141+
router.POST("transfer", multiservicesapi.ServiceRedirector(), transferPrimary)
141142
}
142143

143144
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
@@ -72,7 +72,7 @@ func (suite *tsoAPITestSuite) SetupTest() {
7272
pdLeaderServer := suite.pdCluster.GetServer(leaderName)
7373
re.NoError(pdLeaderServer.BootstrapCluster())
7474
suite.backendEndpoints = pdLeaderServer.GetAddr()
75-
suite.tsoCluster, err = tests.NewTestTSOCluster(suite.ctx, 1, suite.backendEndpoints)
75+
suite.tsoCluster, err = tests.NewTestTSOCluster(suite.ctx, 2, suite.backendEndpoints)
7676
re.NoError(err)
7777
}
7878

@@ -297,3 +297,62 @@ func (suite *tsoAPITestSuite) TestHealth() {
297297
defer resp.Body.Close()
298298
re.Equal(http.StatusOK, resp.StatusCode)
299299
}
300+
301+
// TestForwardingBehavior specifically tests the API forwarding logic.
302+
func (suite *tsoAPITestSuite) TestForwardingBehavior() {
303+
re := suite.Require()
304+
305+
primary := suite.tsoCluster.WaitForDefaultPrimaryServing(re)
306+
re.NotNil(primary)
307+
var follower *tso.Server
308+
for _, srv := range suite.tsoCluster.GetServers() {
309+
if srv.Name() != primary.Name() {
310+
follower = srv
311+
break
312+
}
313+
}
314+
re.NotNil(follower)
315+
re.True(primary.IsServing())
316+
re.False(follower.IsServing())
317+
re.NotEqual(follower.GetConfig().GetListenAddr(), primary.GetConfig().GetListenAddr())
318+
319+
followerAddr := follower.GetAddr()
320+
followerURL := func(path string) string {
321+
return fmt.Sprintf("%s%s%s", followerAddr, apis.APIPathPrefix, path)
322+
}
323+
324+
// Test: PUT /admin/log should be handled by the follower locally.
325+
logURL := followerURL("/admin/log")
326+
level := "debug"
327+
logPayload, err := json.Marshal(level)
328+
re.NoError(err)
329+
req, _ := http.NewRequest(http.MethodPut, logURL, bytes.NewBuffer(logPayload))
330+
req.Header.Set("Content-Type", "application/json")
331+
resp, err := tests.TestDialClient.Do(req)
332+
re.NoError(err)
333+
defer resp.Body.Close()
334+
re.Equal(http.StatusOK, resp.StatusCode)
335+
336+
// Test: GET /config should be handled by the follower locally.
337+
configURL := followerURL("/config")
338+
var followerCfg tso.Config
339+
err = testutil.ReadGetJSON(re, tests.TestDialClient, configURL, &followerCfg)
340+
re.NoError(err)
341+
re.Equal(follower.GetConfig().GetListenAddr(), followerCfg.GetListenAddr())
342+
re.NotEqual(primary.GetConfig().GetListenAddr(), followerCfg.GetListenAddr())
343+
re.Equal(level, followerCfg.Log.Level)
344+
345+
// Test: GET /keyspace-groups/members should be handled by the follower locally.
346+
membersURL := followerURL("/keyspace-groups/members")
347+
var kgms map[uint32]*apis.KeyspaceGroupMember
348+
err = testutil.ReadGetJSON(re, tests.TestDialClient, membersURL, &kgms)
349+
re.NoError(err)
350+
re.Len(kgms, 1)
351+
kgm := kgms[constant.DefaultKeyspaceGroupID]
352+
re.NotNil(kgm)
353+
re.Len(kgm.Member.ListenUrls, 1)
354+
respListenURL := kgm.Member.ListenUrls[0]
355+
re.Equal(follower.GetConfig().GetListenAddr(), respListenURL)
356+
re.NotEqual(primary.GetConfig().GetListenAddr(), respListenURL)
357+
re.False(kgm.IsPrimary)
358+
}

0 commit comments

Comments
 (0)