Skip to content

Commit 80845cb

Browse files
wxing1292dnr
authored andcommitted
Allow context disable frontend redirection (#4547)
* Add RPC header xdc-redirection, allowing disable DC redirection, default to redirect
1 parent 2a0bfcf commit 80845cb

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

service/frontend/redirection_interceptor.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ package frontend
2626

2727
import (
2828
"context"
29+
"strconv"
2930
"time"
3031

3132
"go.temporal.io/api/workflowservice/v1"
3233
"google.golang.org/grpc"
34+
"google.golang.org/grpc/metadata"
3335

3436
"go.temporal.io/server/client"
3537
"go.temporal.io/server/common/clock"
@@ -42,9 +44,13 @@ import (
4244
"go.temporal.io/server/common/rpc/interceptor"
4345
)
4446

45-
var (
47+
const (
48+
dcRedirectionContextHeaderName = "xdc-redirection"
49+
4650
dcRedirectionMetricsPrefix = "DCRedirection"
51+
)
4752

53+
var (
4854
localAPIResponses = map[string]responseConstructorFn{
4955
// Namespace APIs, namespace APIs does not require redirection
5056
"DeprecateNamespace": func() any { return &workflowservice.DeprecateNamespaceResponse{} },
@@ -173,6 +179,9 @@ func (i *RedirectionInterceptor) Intercept(
173179
if _, isWorkflowHandler := info.Server.(*WorkflowHandler); !isWorkflowHandler {
174180
return handler(ctx, req)
175181
}
182+
if !i.redirectionAllowed(ctx) {
183+
return handler(ctx, req)
184+
}
176185

177186
_, methodName := interceptor.SplitMethodName(info.FullMethod)
178187
if _, ok := localAPIResponses[methodName]; ok {
@@ -262,3 +271,22 @@ func (i *RedirectionInterceptor) afterCall(
262271
metricsHandler.Counter(metrics.ClientRedirectionFailures.GetMetricName()).Record(1)
263272
}
264273
}
274+
275+
func (i *RedirectionInterceptor) redirectionAllowed(
276+
ctx context.Context,
277+
) bool {
278+
// default to allow dc redirection
279+
md, ok := metadata.FromIncomingContext(ctx)
280+
if !ok {
281+
return true
282+
}
283+
values := md.Get(dcRedirectionContextHeaderName)
284+
if len(values) == 0 {
285+
return true
286+
}
287+
allowed, err := strconv.ParseBool(values[0])
288+
if err != nil {
289+
return true
290+
}
291+
return allowed
292+
}

service/frontend/redirection_interceptor_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"go.temporal.io/api/serviceerror"
3737
"go.temporal.io/api/workflowservice/v1"
3838
"google.golang.org/grpc"
39+
"google.golang.org/grpc/metadata"
3940

4041
persistencespb "go.temporal.io/server/api/persistence/v1"
4142
"go.temporal.io/server/client"
@@ -328,6 +329,36 @@ func (s *redirectionInterceptorSuite) TestHandleGlobalAPIInvocation_NamespaceNot
328329
s.IsType(&serviceerror.NamespaceNotFound{}, err)
329330
}
330331

332+
func (s *redirectionInterceptorSuite) TestRedirectionAllowed_Empty() {
333+
ctx := metadata.NewIncomingContext(context.Background(), metadata.New(map[string]string{}))
334+
allowed := s.redirector.redirectionAllowed(ctx)
335+
s.True(allowed)
336+
}
337+
338+
func (s *redirectionInterceptorSuite) TestRedirectionAllowed_Error() {
339+
ctx := metadata.NewIncomingContext(context.Background(), metadata.New(map[string]string{
340+
dcRedirectionContextHeaderName: "?",
341+
}))
342+
allowed := s.redirector.redirectionAllowed(ctx)
343+
s.True(allowed)
344+
}
345+
346+
func (s *redirectionInterceptorSuite) TestRedirectionAllowed_True() {
347+
ctx := metadata.NewIncomingContext(context.Background(), metadata.New(map[string]string{
348+
dcRedirectionContextHeaderName: "t",
349+
}))
350+
allowed := s.redirector.redirectionAllowed(ctx)
351+
s.True(allowed)
352+
}
353+
354+
func (s *redirectionInterceptorSuite) TestRedirectionAllowed_False() {
355+
ctx := metadata.NewIncomingContext(context.Background(), metadata.New(map[string]string{
356+
dcRedirectionContextHeaderName: "f",
357+
}))
358+
allowed := s.redirector.redirectionAllowed(ctx)
359+
s.False(allowed)
360+
}
361+
331362
type (
332363
mockClientConnInterface struct {
333364
*suite.Suite

0 commit comments

Comments
 (0)