dubbo.apache.org/dubbo-go/v3@v3.1.1/cluster/cluster/interceptor_invoker.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package cluster 19 20 import ( 21 "context" 22 "sync" 23 ) 24 25 import ( 26 "dubbo.apache.org/dubbo-go/v3/common" 27 "dubbo.apache.org/dubbo-go/v3/protocol" 28 ) 29 30 var ( 31 lock sync.RWMutex 32 interceptors = make(map[string]func() Interceptor) 33 ) 34 35 // SetClusterInterceptor sets cluster interceptor so that user has chance to inject extra logics before and after 36 // cluster invoker 37 func SetClusterInterceptor(name string, fun func() Interceptor) { 38 lock.Lock() 39 defer lock.Unlock() 40 interceptors[name] = fun 41 } 42 43 // GetClusterInterceptor returns the cluster interceptor instance with the given name 44 func GetClusterInterceptor(name string) Interceptor { 45 lock.RLock() 46 defer lock.RUnlock() 47 if interceptors[name] == nil { 48 panic("cluster_interceptor for " + name + " doesn't exist, make sure the corresponding package is imported") 49 } 50 return interceptors[name]() 51 } 52 53 // GetClusterInterceptors returns all instances of registered cluster interceptors 54 func GetClusterInterceptors() []Interceptor { 55 lock.RLock() 56 defer lock.RUnlock() 57 ret := make([]Interceptor, 0, len(interceptors)) 58 for _, f := range interceptors { 59 ret = append(ret, f()) 60 } 61 return ret 62 } 63 64 // InterceptorInvoker mocks cluster interceptor as an invoker 65 type InterceptorInvoker struct { 66 next protocol.Invoker 67 interceptor Interceptor 68 } 69 70 // GetURL is used to get url from InterceptorInvoker 71 func (i *InterceptorInvoker) GetURL() *common.URL { 72 return i.next.GetURL() 73 } 74 75 // IsAvailable is used to get available status 76 func (i *InterceptorInvoker) IsAvailable() bool { 77 return i.next.IsAvailable() 78 } 79 80 // Invoke is used to call service method by invocation 81 func (i *InterceptorInvoker) Invoke(ctx context.Context, invocation protocol.Invocation) protocol.Result { 82 return i.interceptor.Invoke(ctx, i.next, invocation) 83 } 84 85 // Destroy will destroy invoker 86 func (i *InterceptorInvoker) Destroy() { 87 i.next.Destroy() 88 } 89 90 func BuildInterceptorChain(invoker protocol.Invoker, builtins ...Interceptor) protocol.Invoker { 91 // The order of interceptors is from left to right, so loading from right to left 92 next := invoker 93 interceptors := GetClusterInterceptors() 94 if len(interceptors) != 0 { 95 for i := len(interceptors) - 1; i >= 0; i-- { 96 v := &InterceptorInvoker{next: next, interceptor: interceptors[i]} 97 next = v 98 } 99 } 100 101 if builtins != nil && len(builtins) > 0 { 102 for i := len(builtins) - 1; i >= 0; i-- { 103 v := &InterceptorInvoker{next: next, interceptor: builtins[i]} 104 next = v 105 } 106 } 107 108 return next 109 }