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  }