Skip to content

Commit 030e361

Browse files
authored
Merge pull request #19280 from gojoy/readyz-learner_3.5
add learner check to readyz
2 parents de0fb18 + 62a5010 commit 030e361

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

server/etcdserver/api/etcdhttp/health.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ type ServerHealth interface {
5353
Range(context.Context, *pb.RangeRequest) (*pb.RangeResponse, error)
5454
Config() config.ServerConfig
5555
AuthStore() auth.AuthStore
56+
IsLearner() bool
5657
}
5758

5859
type serverHealthV2V3 interface {
@@ -288,6 +289,8 @@ func installReadyzEndpoints(lg *zap.Logger, mux *http.ServeMux, server ServerHea
288289
reg.Register("serializable_read", readCheck(server, true))
289290
// linearizable_read check would be replaced by read_index check in 3.6
290291
reg.Register("linearizable_read", readCheck(server, false))
292+
// check if local is learner
293+
reg.Register("non_learner", learnerCheck(server))
291294
reg.InstallHttpEndpoints(lg, mux)
292295
}
293296

@@ -458,3 +461,12 @@ func readCheck(srv ServerHealth, serializable bool) func(ctx context.Context) er
458461
return err
459462
}
460463
}
464+
465+
func learnerCheck(srv ServerHealth) func(ctx context.Context) error {
466+
return func(ctx context.Context) error {
467+
if srv.IsLearner() {
468+
return fmt.Errorf("not supported for learner")
469+
}
470+
return nil
471+
}
472+
}

server/etcdserver/api/etcdhttp/health_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type fakeHealthServer struct {
2727
linearizableReadError error
2828
missingLeader bool
2929
authStore auth.AuthStore
30+
isLearner bool
3031
}
3132

3233
func (s *fakeHealthServer) Range(_ context.Context, req *pb.RangeRequest) (*pb.RangeResponse, error) {
@@ -36,6 +37,10 @@ func (s *fakeHealthServer) Range(_ context.Context, req *pb.RangeRequest) (*pb.R
3637
return nil, s.linearizableReadError
3738
}
3839

40+
func (s *fakeHealthServer) IsLearner() bool {
41+
return s.isLearner
42+
}
43+
3944
func (s *fakeHealthServer) Config() config.ServerConfig {
4045
return config.ServerConfig{}
4146
}
@@ -61,6 +66,7 @@ type healthTestCase struct {
6166
alarms []*pb.AlarmMember
6267
apiError error
6368
missingLeader bool
69+
isLearner bool
6470
}
6571

6672
func TestHealthHandler(t *testing.T) {
@@ -165,6 +171,11 @@ func TestHttpSubPath(t *testing.T) {
165171
expectStatusCode: http.StatusServiceUnavailable,
166172
notInResult: []string{"data_corruption"},
167173
},
174+
{
175+
name: "/readyz/learner ok",
176+
healthCheckURL: "/readyz/non_learner",
177+
expectStatusCode: http.StatusOK,
178+
},
168179
{
169180
name: "/readyz/non_exist 404",
170181
healthCheckURL: "/readyz/non_exist",
@@ -328,6 +339,42 @@ func TestLinearizableReadCheck(t *testing.T) {
328339
}
329340
}
330341

342+
func TestLearnerReadyCheck(t *testing.T) {
343+
be, _ := betesting.NewDefaultTmpBackend(t)
344+
defer betesting.Close(t, be)
345+
tests := []healthTestCase{
346+
{
347+
name: "readyz normal",
348+
healthCheckURL: "/readyz",
349+
expectStatusCode: http.StatusOK,
350+
isLearner: false,
351+
},
352+
{
353+
name: "not ready because member is learner",
354+
healthCheckURL: "/readyz",
355+
expectStatusCode: http.StatusServiceUnavailable,
356+
isLearner: true,
357+
},
358+
}
359+
360+
for _, tt := range tests {
361+
t.Run(tt.name, func(t *testing.T) {
362+
mux := http.NewServeMux()
363+
logger := zaptest.NewLogger(t)
364+
s := &fakeHealthServer{
365+
linearizableReadError: tt.apiError,
366+
authStore: auth.NewAuthStore(logger, be, nil, 0),
367+
}
368+
s.isLearner = tt.isLearner
369+
HandleHealth(logger, mux, s)
370+
ts := httptest.NewServer(mux)
371+
defer ts.Close()
372+
checkHttpResponse(t, ts, tt.healthCheckURL, tt.expectStatusCode, tt.inResult, tt.notInResult)
373+
checkMetrics(t, tt.healthCheckURL, "linearizable_read", tt.expectStatusCode)
374+
})
375+
}
376+
}
377+
331378
func checkHttpResponse(t *testing.T, ts *httptest.Server, url string, expectStatusCode int, inResult []string, notInResult []string) {
332379
res, err := ts.Client().Do(&http.Request{Method: http.MethodGet, URL: testutil.MustNewURL(t, ts.URL+url)})
333380

0 commit comments

Comments
 (0)