dubbo.apache.org/dubbo-go/v3@v3.1.1/proxy/proxy_factory/pass_through.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 proxy_factory
    19  
    20  import (
    21  	"context"
    22  	"reflect"
    23  )
    24  
    25  import (
    26  	"github.com/dubbogo/gost/log/logger"
    27  
    28  	perrors "github.com/pkg/errors"
    29  )
    30  
    31  import (
    32  	"dubbo.apache.org/dubbo-go/v3/common"
    33  	"dubbo.apache.org/dubbo-go/v3/common/constant"
    34  	"dubbo.apache.org/dubbo-go/v3/common/extension"
    35  	"dubbo.apache.org/dubbo-go/v3/protocol"
    36  	"dubbo.apache.org/dubbo-go/v3/proxy"
    37  )
    38  
    39  func init() {
    40  	extension.SetProxyFactory(constant.PassThroughProxyFactoryKey, NewPassThroughProxyFactory)
    41  }
    42  
    43  // PassThroughProxyFactory is the factory of PassThroughProxyInvoker
    44  type PassThroughProxyFactory struct {
    45  }
    46  
    47  // NewPassThroughProxyFactory returns a proxy factory instance
    48  func NewPassThroughProxyFactory(_ ...proxy.Option) proxy.ProxyFactory {
    49  	return &PassThroughProxyFactory{}
    50  }
    51  
    52  // GetProxy gets a proxy
    53  func (factory *PassThroughProxyFactory) GetProxy(invoker protocol.Invoker, url *common.URL) *proxy.Proxy {
    54  	return factory.GetAsyncProxy(invoker, nil, url)
    55  }
    56  
    57  // GetAsyncProxy gets a async proxy
    58  func (factory *PassThroughProxyFactory) GetAsyncProxy(invoker protocol.Invoker, callBack interface{}, url *common.URL) *proxy.Proxy {
    59  	//create proxy
    60  	attachments := map[string]string{}
    61  	attachments[constant.AsyncKey] = url.GetParam(constant.AsyncKey, "false")
    62  	return proxy.NewProxy(invoker, callBack, attachments)
    63  }
    64  
    65  // GetInvoker gets a invoker
    66  func (factory *PassThroughProxyFactory) GetInvoker(url *common.URL) protocol.Invoker {
    67  	return &PassThroughProxyInvoker{
    68  		ProxyInvoker: &ProxyInvoker{
    69  			BaseInvoker: *protocol.NewBaseInvoker(url),
    70  		},
    71  	}
    72  }
    73  
    74  // PassThroughProxyInvoker is a invoker struct, it calls service with specific method 'Serivce' and params:
    75  // Service(method string, argsTypes []string, args [][]byte, attachment map[string]interface{})
    76  // PassThroughProxyInvoker pass through raw invocation data and method name to service, which will deal with them.
    77  type PassThroughProxyInvoker struct {
    78  	*ProxyInvoker
    79  }
    80  
    81  // Invoke is used to call service method by invocation
    82  func (pi *PassThroughProxyInvoker) Invoke(ctx context.Context, invocation protocol.Invocation) protocol.Result {
    83  	result := &protocol.RPCResult{}
    84  	result.SetAttachments(invocation.Attachments())
    85  	url := getProviderURL(pi.GetURL())
    86  
    87  	arguments := invocation.Arguments()
    88  	srv := common.ServiceMap.GetServiceByServiceKey(url.Protocol, url.ServiceKey())
    89  
    90  	var args [][]byte
    91  	if len(arguments) > 0 {
    92  		args = make([][]byte, 0, len(arguments))
    93  		for _, arg := range arguments {
    94  			if v, ok := arg.([]byte); ok {
    95  				args = append(args, v)
    96  			} else {
    97  				result.Err = perrors.New("the param type is not []byte")
    98  				return result
    99  			}
   100  		}
   101  	}
   102  	method := srv.Method()["Service"]
   103  
   104  	in := make([]reflect.Value, 5)
   105  	in = append(in, srv.Rcvr())
   106  	in = append(in, reflect.ValueOf(invocation.MethodName()))
   107  	in = append(in, reflect.ValueOf(invocation.GetAttachmentInterface(constant.ParamsTypeKey)))
   108  	in = append(in, reflect.ValueOf(args))
   109  	in = append(in, reflect.ValueOf(invocation.Attachments()))
   110  
   111  	var replyv reflect.Value
   112  	var retErr interface{}
   113  
   114  	returnValues, callErr := callLocalMethod(method.Method(), in)
   115  
   116  	if callErr != nil {
   117  		logger.Errorf("Invoke function error: %+v, service: %#v", callErr, url)
   118  		result.SetError(callErr)
   119  		return result
   120  	}
   121  
   122  	replyv = returnValues[0]
   123  	retErr = returnValues[1].Interface()
   124  
   125  	if retErr != nil {
   126  		result.SetError(retErr.(error))
   127  		return result
   128  	}
   129  	if replyv.IsValid() && (replyv.Kind() != reflect.Ptr || replyv.Kind() == reflect.Ptr && replyv.Elem().IsValid()) {
   130  		result.SetResult(replyv.Interface())
   131  	}
   132  
   133  	return result
   134  }