You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2023/08/11 00:54:48 UTC
[dubbo-go] branch feature-triple updated: Triple adaptation and refactor demo (#2368)
This is an automated email from the ASF dual-hosted git repository.
liujun pushed a commit to branch feature-triple
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git
The following commit(s) were added to refs/heads/feature-triple by this push:
new a97ceeaf5 Triple adaptation and refactor demo (#2368)
a97ceeaf5 is described below
commit a97ceeaf5375af8ac903e2c4be5f932c69aee628
Author: Scout Wang <33...@users.noreply.github.com>
AuthorDate: Fri Aug 11 08:54:42 2023 +0800
Triple adaptation and refactor demo (#2368)
---
client/client.go | 112 +
client/method_config.go | 115 +
client/options.go | 208 ++
{config => client}/reference_config.go | 344 ++-
.../config/application.go | 67 +-
common/config/utils.go | 105 +
common/constant/key.go | 5 +
config/application_config.go | 51 +-
config/consumer_config.go | 68 +-
config/reference_config.go | 388 +---
config/registry_config.go | 290 +--
config/registry_config_test.go | 142 +-
config/root_config.go | 46 +-
config/root_config_test.go | 5 +-
config/service.go | 30 +-
go.mod | 69 +-
go.sum | 661 +-----
imports/imports.go | 1 +
metrics/bus_test.go | 5 +-
metrics/prometheus/reporter.go | 1 +
metrics/prometheus/util.go | 1 +
metrics/util/aggregate/quantile_test.go | 4 +-
protocol/invocation.go | 2 +
protocol/invocation/rpcinvocation.go | 22 +-
protocol/triple/client.go | 230 ++
protocol/triple/codec.go | 77 +
protocol/triple/common.go | 127 ++
protocol/triple/internal/client/cmd/dubbogo.yml | 11 +
protocol/triple/internal/client/cmd/main.go | 122 +
protocol/triple/internal/proto/greet.pb.go | 621 +++++
protocol/triple/internal/proto/greet.proto | 44 +
.../internal/proto/greettriple/greet.triple.go | 388 ++++
protocol/triple/internal/server/cmd/dubbogo.yml | 16 +
protocol/triple/internal/server/cmd/main.go | 75 +
protocol/triple/protoc-gen-triple/main.go | 838 +++++++
protocol/triple/server.go | 251 ++
protocol/triple/triple.go | 124 +
protocol/triple/triple_exporter.go | 54 +
protocol/triple/triple_invoker.go | 151 ++
protocol/triple/triple_protocol/Makefile | 94 +
protocol/triple/triple_protocol/assert/assert.go | 212 ++
.../triple/triple_protocol/assert/assert_test.go | 96 +
protocol/triple/triple_protocol/bench_test.go | 176 ++
protocol/triple/triple_protocol/buffer_pool.go | 54 +
protocol/triple/triple_protocol/client.go | 265 +++
.../triple/triple_protocol/client_example_test.go | 57 +
protocol/triple/triple_protocol/client_ext_test.go | 181 ++
.../triple_protocol/client_get_fallback_test.go | 62 +
protocol/triple/triple_protocol/client_stream.go | 272 +++
.../triple/triple_protocol/client_stream_test.go | 106 +
protocol/triple/triple_protocol/code.go | 226 ++
protocol/triple/triple_protocol/code_test.go | 58 +
protocol/triple/triple_protocol/codec.go | 226 ++
protocol/triple/triple_protocol/codec_test.go | 112 +
protocol/triple/triple_protocol/compression.go | 215 ++
.../triple/triple_protocol/compression_test.go | 163 ++
.../triple/triple_protocol/connect_ext_test.go | 2392 ++++++++++++++++++++
.../triple/triple_protocol/duplex_http_call.go | 311 +++
protocol/triple/triple_protocol/envelope.go | 279 +++
protocol/triple/triple_protocol/error.go | 371 +++
.../triple/triple_protocol/error_example_test.go | 37 +
protocol/triple/triple_protocol/error_test.go | 115 +
protocol/triple/triple_protocol/error_writer.go | 159 ++
.../triple_protocol/error_writer_example_test.go | 71 +
.../triple/triple_protocol/example_init_test.go | 144 ++
protocol/triple/triple_protocol/handler.go | 343 +++
.../triple/triple_protocol/handler_example_test.go | 68 +
.../triple/triple_protocol/handler_ext_test.go | 200 ++
protocol/triple/triple_protocol/handler_stream.go | 189 ++
.../triple/triple_protocol/handler_stream_test.go | 44 +
protocol/triple/triple_protocol/header.go | 87 +
protocol/triple/triple_protocol/header_test.go | 60 +
.../triple/triple_protocol/idempotency_level.go | 70 +
protocol/triple/triple_protocol/interceptor.go | 124 +
.../triple_protocol/interceptor_example_test.go | 97 +
.../triple/triple_protocol/interceptor_ext_test.go | 270 +++
protocol/triple/triple_protocol/maxbytes.go | 32 +
protocol/triple/triple_protocol/option.go | 553 +++++
protocol/triple/triple_protocol/proto/buf.yaml | 12 +
.../proto/connectext/grpc/status/v1/status.pb.go | 202 ++
.../proto/connectext/grpc/status/v1/status.proto | 32 +
protocol/triple/triple_protocol/protobuf_util.go | 42 +
.../triple/triple_protocol/protobuf_util_test.go | 63 +
protocol/triple/triple_protocol/protocol.go | 368 +++
protocol/triple/triple_protocol/protocol_grpc.go | 922 ++++++++
.../triple/triple_protocol/protocol_grpc_test.go | 201 ++
protocol/triple/triple_protocol/protocol_test.go | 67 +
protocol/triple/triple_protocol/protocol_triple.go | 766 +++++++
.../triple/triple_protocol/protocol_triple_test.go | 56 +
protocol/triple/triple_protocol/recover.go | 80 +
.../triple/triple_protocol/recover_ext_test.go | 108 +
.../triple/triple_protocol/testdata/server.crt | 16 +
.../triple/triple_protocol/testdata/server.key | 10 +
protocol/triple/triple_protocol/triple.go | 345 +++
provider/options.go | 6 +
provider/provider.go | 38 +
{config => registry}/registry_config.go | 247 +-
{config => registry}/registry_config_test.go | 64 +-
98 files changed, 16056 insertions(+), 2051 deletions(-)
diff --git a/client/client.go b/client/client.go
new file mode 100644
index 000000000..9619321ce
--- /dev/null
+++ b/client/client.go
@@ -0,0 +1,112 @@
+package client
+
+import (
+ "context"
+)
+
+import (
+ "github.com/pkg/errors"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+ "dubbo.apache.org/dubbo-go/v3/protocol"
+ invocation_impl "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
+)
+
+type Client struct {
+ invoker protocol.Invoker
+ info *ClientInfo
+ cfg *ReferenceConfig
+}
+
+type ClientInfo struct {
+ InterfaceName string
+ MethodNames []string
+ ClientInjectFunc func(dubboCliRaw interface{}, cli *Client)
+ Meta map[string]interface{}
+}
+
+func (cli *Client) call(ctx context.Context, paramsRawVals []interface{}, interfaceName, methodName, callType string, opts ...CallOption) (protocol.Result, error) {
+ // get a default CallOptions
+ // apply CallOption
+ options := newDefaultCallOptions()
+ for _, opt := range opts {
+ opt(options)
+ }
+
+ inv, err := generateInvocation(methodName, paramsRawVals, callType, options)
+ if err != nil {
+ return nil, err
+ }
+ // todo: move timeout into context or invocation
+ return cli.invoker.Invoke(ctx, inv), nil
+
+}
+
+func (cli *Client) CallUnary(ctx context.Context, req, resp interface{}, interfaceName, methodName string, opts ...CallOption) error {
+ res, err := cli.call(ctx, []interface{}{req, resp}, interfaceName, methodName, constant.CallUnary, opts...)
+ if err != nil {
+ return err
+ }
+ return res.Error()
+}
+
+func (cli *Client) CallClientStream(ctx context.Context, interfaceName, methodName string, opts ...CallOption) (interface{}, error) {
+ res, err := cli.call(ctx, nil, interfaceName, methodName, constant.CallClientStream, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return res.Result(), res.Error()
+}
+
+func (cli *Client) CallServerStream(ctx context.Context, req interface{}, interfaceName, methodName string, opts ...CallOption) (interface{}, error) {
+ res, err := cli.call(ctx, []interface{}{req}, interfaceName, methodName, constant.CallServerStream, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return res.Result(), res.Error()
+}
+
+func (cli *Client) CallBidiStream(ctx context.Context, interfaceName, methodName string, opts ...CallOption) (interface{}, error) {
+ res, err := cli.call(ctx, nil, interfaceName, methodName, constant.CallBidiStream, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return res.Result(), res.Error()
+}
+
+func (cli *Client) Init(info *ClientInfo) error {
+ if info == nil {
+ return errors.New("ClientInfo is nil")
+ }
+ cli.cfg.ReferWithInfo(info)
+ cli.invoker = cli.cfg.invoker
+
+ return nil
+}
+
+func generateInvocation(methodName string, paramsRawVals []interface{}, callType string, opts *CallOptions) (protocol.Invocation, error) {
+ inv := invocation_impl.NewRPCInvocationWithOptions(
+ invocation_impl.WithMethodName(methodName),
+ // todo: process opts
+ invocation_impl.WithParameterRawValues(paramsRawVals),
+ )
+ inv.SetAttribute(constant.CallTypeKey, callType)
+
+ return inv, nil
+}
+
+func NewClient(opts ...ReferenceOption) (*Client, error) {
+ // get default RootConfigs
+ //rootCfg := config.NewRootConfigBuilder().Build()
+ //rootCfg.Init()
+ // todo: create a default ReferenceConfig
+ newRefCfg := &ReferenceConfig{}
+ if err := newRefCfg.Init(opts...); err != nil {
+ return nil, err
+ }
+ return &Client{
+ cfg: newRefCfg,
+ }, nil
+}
diff --git a/client/method_config.go b/client/method_config.go
new file mode 100644
index 000000000..ffe83970c
--- /dev/null
+++ b/client/method_config.go
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package client
+
+import (
+ "fmt"
+ "strconv"
+)
+
+import (
+ "github.com/creasty/defaults"
+)
+
+import (
+ commonCfg "dubbo.apache.org/dubbo-go/v3/common/config"
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+ "dubbo.apache.org/dubbo-go/v3/common/extension"
+)
+
+// MethodConfig defines method config
+type MethodConfig struct {
+ InterfaceId string
+ InterfaceName string
+ Name string `yaml:"name" json:"name,omitempty" property:"name"`
+ Retries string `yaml:"retries" json:"retries,omitempty" property:"retries"`
+ LoadBalance string `yaml:"loadbalance" json:"loadbalance,omitempty" property:"loadbalance"`
+ Weight int64 `yaml:"weight" json:"weight,omitempty" property:"weight"`
+ TpsLimitInterval string `yaml:"tps.limit.interval" json:"tps.limit.interval,omitempty" property:"tps.limit.interval"`
+ TpsLimitRate string `yaml:"tps.limit.rate" json:"tps.limit.rate,omitempty" property:"tps.limit.rate"`
+ TpsLimitStrategy string `yaml:"tps.limit.strategy" json:"tps.limit.strategy,omitempty" property:"tps.limit.strategy"`
+ ExecuteLimit string `yaml:"execute.limit" json:"execute.limit,omitempty" property:"execute.limit"`
+ ExecuteLimitRejectedHandler string `yaml:"execute.limit.rejected.handler" json:"execute.limit.rejected.handler,omitempty" property:"execute.limit.rejected.handler"`
+ Sticky bool `yaml:"sticky" json:"sticky,omitempty" property:"sticky"`
+ RequestTimeout string `yaml:"timeout" json:"timeout,omitempty" property:"timeout"`
+}
+
+// nolint
+func (m *MethodConfig) Prefix() string {
+ if len(m.InterfaceId) != 0 {
+ return constant.Dubbo + "." + m.InterfaceName + "." + m.InterfaceId + "." + m.Name + "."
+ }
+
+ return constant.Dubbo + "." + m.InterfaceName + "." + m.Name + "."
+}
+
+func (m *MethodConfig) Init() error {
+ return m.check()
+}
+
+//func initProviderMethodConfig(sc *ServiceConfig) error {
+// methods := sc.Methods
+// if methods == nil {
+// return nil
+// }
+// for _, method := range methods {
+// if err := method.check(); err != nil {
+// return err
+// }
+// }
+// sc.Methods = methods
+// return nil
+//}
+
+// check set default value and verify
+func (m *MethodConfig) check() error {
+ qualifieldMethodName := m.InterfaceName + "#" + m.Name
+ if m.TpsLimitStrategy != "" {
+ _, err := extension.GetTpsLimitStrategyCreator(m.TpsLimitStrategy)
+ if err != nil {
+ panic(err)
+ }
+ }
+
+ if m.TpsLimitInterval != "" {
+ tpsLimitInterval, err := strconv.ParseInt(m.TpsLimitInterval, 0, 0)
+ if err != nil {
+ return fmt.Errorf("[MethodConfig] Cannot parse the configuration tps.limit.interval for method %s, please check your configuration", qualifieldMethodName)
+ }
+ if tpsLimitInterval < 0 {
+ return fmt.Errorf("[MethodConfig] The configuration tps.limit.interval for %s must be positive, please check your configuration", qualifieldMethodName)
+ }
+ }
+
+ if m.TpsLimitRate != "" {
+ tpsLimitRate, err := strconv.ParseInt(m.TpsLimitRate, 0, 0)
+ if err != nil {
+ return fmt.Errorf("[MethodConfig] Cannot parse the configuration tps.limit.rate for method %s, please check your configuration", qualifieldMethodName)
+ }
+ if tpsLimitRate < 0 {
+ return fmt.Errorf("[MethodConfig] The configuration tps.limit.rate for method %s must be positive, please check your configuration", qualifieldMethodName)
+ }
+ }
+
+ if err := defaults.Set(m); err != nil {
+ return err
+ }
+ return commonCfg.Verify(m)
+}
+
+type MethodOption func(*MethodConfig)
diff --git a/client/options.go b/client/options.go
new file mode 100644
index 000000000..cea2e48c4
--- /dev/null
+++ b/client/options.go
@@ -0,0 +1,208 @@
+package client
+
+import (
+ "strconv"
+)
+
+import (
+ commonCfg "dubbo.apache.org/dubbo-go/v3/common/config"
+ "dubbo.apache.org/dubbo-go/v3/registry"
+)
+
+// todo: need to be consistent with MethodConfig
+type CallOptions struct {
+ RequestTimeout string
+ Retries string
+}
+
+type CallOption func(*CallOptions)
+
+func newDefaultCallOptions() *CallOptions {
+ return &CallOptions{
+ RequestTimeout: "",
+ Retries: "",
+ }
+}
+
+func WithCallRequestTimeout(timeout string) CallOption {
+ return func(opts *CallOptions) {
+ opts.RequestTimeout = timeout
+ }
+}
+
+func WithCallRetries(retries string) CallOption {
+ return func(opts *CallOptions) {
+ opts.Retries = retries
+ }
+}
+
+// ----------ReferenceOption----------
+
+// For ReferenceOption that needs to check whether configuration field is empty(eg. WithCheck), it means this
+// ReferenceOption maybe used by ConsumerConfig to act as default value.
+
+func WithCheck(check bool) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ if cfg.Check == nil {
+ cfg.Check = &check
+ }
+ }
+}
+
+func WithURL(url string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.URL = url
+ }
+}
+
+func WithFilter(filter string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ if cfg.Filter == "" {
+ cfg.Filter = filter
+ }
+ }
+}
+
+func WithProtocol(protocol string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ if cfg.Protocol == "" {
+ cfg.Protocol = protocol
+ }
+ }
+}
+
+func WithRegistryIDs(registryIDs []string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ if len(registryIDs) <= 0 {
+ cfg.RegistryIDs = registryIDs
+ }
+ }
+}
+
+func WithCluster(cluster string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.Cluster = cluster
+ }
+}
+
+func WithLoadBalance(loadBalance string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.Loadbalance = loadBalance
+ }
+}
+
+func WithRetries(retries int) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.Retries = strconv.Itoa(retries)
+ }
+}
+
+func WithGroup(group string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.Group = group
+ }
+}
+
+func WithVersion(version string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.Version = version
+ }
+}
+
+func WithSerialization(serialization string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.Serialization = serialization
+ }
+}
+
+func WithProviderBy(providedBy string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.ProvidedBy = providedBy
+ }
+}
+
+func WithAsync(async bool) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.Async = async
+ }
+}
+
+func WithParams(params map[string]string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.Params = params
+ }
+}
+
+func WithGeneric(generic string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.Generic = generic
+ }
+}
+
+func WithSticky(sticky bool) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.Sticky = sticky
+ }
+}
+
+func WithRequestTimeout(timeout string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.RequestTimeout = timeout
+ }
+}
+
+func WithForce(force bool) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.ForceTag = force
+ }
+}
+
+func WithTracingKey(tracingKey string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ if cfg.TracingKey == "" {
+ cfg.TracingKey = tracingKey
+ }
+ }
+}
+
+func WithMeshProviderPort(port int) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.MeshProviderPort = port
+ }
+}
+
+// ----------From ApplicationConfig----------
+
+func WithApplication(application *commonCfg.ApplicationConfig) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.application = application
+ }
+}
+
+// ----------From ConsumerConfig----------
+
+func WithMeshEnabled(meshEnabled bool) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.meshEnabled = meshEnabled
+ }
+}
+
+func WithAdaptiveService(adaptiveService bool) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.adaptiveService = adaptiveService
+ }
+}
+
+func WithProxyFactory(proxyFactory string) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.proxyFactory = proxyFactory
+ }
+}
+
+// ----------From RegistryConfig----------
+
+func WithRegistries(registries map[string]*registry.RegistryConfig) ReferenceOption {
+ return func(cfg *ReferenceConfig) {
+ cfg.registries = registries
+ }
+}
diff --git a/config/reference_config.go b/client/reference_config.go
similarity index 54%
copy from config/reference_config.go
copy to client/reference_config.go
index 06797a8ec..f4257063a 100644
--- a/config/reference_config.go
+++ b/client/reference_config.go
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package config
+package client
import (
"fmt"
@@ -37,51 +37,64 @@ import (
import (
"dubbo.apache.org/dubbo-go/v3/cluster/directory/static"
"dubbo.apache.org/dubbo-go/v3/common"
+ commonCfg "dubbo.apache.org/dubbo-go/v3/common/config"
"dubbo.apache.org/dubbo-go/v3/common/constant"
"dubbo.apache.org/dubbo-go/v3/common/extension"
- "dubbo.apache.org/dubbo-go/v3/config/generic"
+ "dubbo.apache.org/dubbo-go/v3/config"
"dubbo.apache.org/dubbo-go/v3/protocol"
"dubbo.apache.org/dubbo-go/v3/protocol/protocolwrapper"
"dubbo.apache.org/dubbo-go/v3/proxy"
+ "dubbo.apache.org/dubbo-go/v3/registry"
)
// ReferenceConfig is the configuration of service consumer
type ReferenceConfig struct {
- pxy *proxy.Proxy
- id string
- InterfaceName string `yaml:"interface" json:"interface,omitempty" property:"interface"`
- Check *bool `yaml:"check" json:"check,omitempty" property:"check"`
- URL string `yaml:"url" json:"url,omitempty" property:"url"`
- Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"`
- Protocol string `yaml:"protocol" json:"protocol,omitempty" property:"protocol"`
- RegistryIDs []string `yaml:"registry-ids" json:"registry-ids,omitempty" property:"registry-ids"`
- Cluster string `yaml:"cluster" json:"cluster,omitempty" property:"cluster"`
- Loadbalance string `yaml:"loadbalance" json:"loadbalance,omitempty" property:"loadbalance"`
- Retries string `yaml:"retries" json:"retries,omitempty" property:"retries"`
- Group string `yaml:"group" json:"group,omitempty" property:"group"`
- Version string `yaml:"version" json:"version,omitempty" property:"version"`
- Serialization string `yaml:"serialization" json:"serialization" property:"serialization"`
- ProvidedBy string `yaml:"provided_by" json:"provided_by,omitempty" property:"provided_by"`
- Methods []*MethodConfig `yaml:"methods" json:"methods,omitempty" property:"methods"`
- Async bool `yaml:"async" json:"async,omitempty" property:"async"`
- Params map[string]string `yaml:"params" json:"params,omitempty" property:"params"`
- invoker protocol.Invoker
- urls []*common.URL
- Generic string `yaml:"generic" json:"generic,omitempty" property:"generic"`
- Sticky bool `yaml:"sticky" json:"sticky,omitempty" property:"sticky"`
- RequestTimeout string `yaml:"timeout" json:"timeout,omitempty" property:"timeout"`
- ForceTag bool `yaml:"force.tag" json:"force.tag,omitempty" property:"force.tag"`
- TracingKey string `yaml:"tracing-key" json:"tracing-key,omitempty" propertiy:"tracing-key"`
- rootConfig *RootConfig
+ pxy *proxy.Proxy
+ id string
+ InterfaceName string `yaml:"interface" json:"interface,omitempty" property:"interface"`
+ Check *bool `yaml:"check" json:"check,omitempty" property:"check"`
+ URL string `yaml:"url" json:"url,omitempty" property:"url"`
+ Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"`
+ Protocol string `yaml:"protocol" json:"protocol,omitempty" property:"protocol"`
+ RegistryIDs []string `yaml:"registry-ids" json:"registry-ids,omitempty" property:"registry-ids"`
+ Cluster string `yaml:"cluster" json:"cluster,omitempty" property:"cluster"`
+ Loadbalance string `yaml:"loadbalance" json:"loadbalance,omitempty" property:"loadbalance"`
+ Retries string `yaml:"retries" json:"retries,omitempty" property:"retries"`
+ Group string `yaml:"group" json:"group,omitempty" property:"group"`
+ Version string `yaml:"version" json:"version,omitempty" property:"version"`
+ Serialization string `yaml:"serialization" json:"serialization" property:"serialization"`
+ ProvidedBy string `yaml:"provided_by" json:"provided_by,omitempty" property:"provided_by"`
+ Methods []*MethodConfig `yaml:"methods" json:"methods,omitempty" property:"methods"`
+ Async bool `yaml:"async" json:"async,omitempty" property:"async"`
+ Params map[string]string `yaml:"params" json:"params,omitempty" property:"params"`
+ invoker protocol.Invoker
+ urls []*common.URL
+ Generic string `yaml:"generic" json:"generic,omitempty" property:"generic"`
+ Sticky bool `yaml:"sticky" json:"sticky,omitempty" property:"sticky"`
+ RequestTimeout string `yaml:"timeout" json:"timeout,omitempty" property:"timeout"`
+ ForceTag bool `yaml:"force.tag" json:"force.tag,omitempty" property:"force.tag"`
+ TracingKey string `yaml:"tracing-key" json:"tracing-key,omitempty" propertiy:"tracing-key"`
+ //rootConfig *config.RootConfig
metaDataType string
MeshProviderPort int `yaml:"mesh-provider-port" json:"mesh-provider-port,omitempty" propertiy:"mesh-provider-port"`
+
+ info *ClientInfo
+
+ // configuration from ConsumerConfig
+ meshEnabled bool
+ adaptiveService bool
+ proxyFactory string
+
+ application *commonCfg.ApplicationConfig
+
+ registries map[string]*registry.RegistryConfig
}
func (rc *ReferenceConfig) Prefix() string {
return constant.ReferenceConfigPrefix + rc.InterfaceName + "."
}
-func (rc *ReferenceConfig) Init(root *RootConfig) error {
+func (rc *ReferenceConfig) Init(opts ...ReferenceOption) error {
for _, method := range rc.Methods {
if err := method.Init(); err != nil {
return err
@@ -90,38 +103,25 @@ func (rc *ReferenceConfig) Init(root *RootConfig) error {
if err := defaults.Set(rc); err != nil {
return err
}
- rc.rootConfig = root
- if root.Application != nil {
- rc.metaDataType = root.Application.MetadataType
+ for _, opt := range opts {
+ opt(rc)
+ }
+ if rc.application != nil {
+ rc.metaDataType = rc.application.MetadataType
if rc.Group == "" {
- rc.Group = root.Application.Group
+ rc.Group = rc.application.Group
}
if rc.Version == "" {
- rc.Version = root.Application.Version
+ rc.Version = rc.application.Version
}
}
- if rc.Filter == "" {
- rc.Filter = root.Consumer.Filter
- }
if rc.Cluster == "" {
rc.Cluster = "failover"
}
- rc.RegistryIDs = translateIds(rc.RegistryIDs)
- if len(rc.RegistryIDs) <= 0 {
- rc.RegistryIDs = root.Consumer.RegistryIDs
- }
-
- if rc.Protocol == "" {
- rc.Protocol = root.Consumer.Protocol
- }
+ // todo: move to registry package
+ rc.RegistryIDs = commonCfg.TranslateIds(rc.RegistryIDs)
- if rc.TracingKey == "" {
- rc.TracingKey = root.Consumer.TracingKey
- }
- if rc.Check == nil {
- rc.Check = &root.Consumer.Check
- }
- return verify(rc)
+ return commonCfg.Verify(rc)
}
func getEnv(key, fallback string) string {
@@ -136,7 +136,7 @@ func updateOrCreateMeshURL(rc *ReferenceConfig) {
logger.Infof("URL specified explicitly %v", rc.URL)
}
- if !rc.rootConfig.Consumer.MeshEnabled {
+ if !rc.meshEnabled {
return
}
if rc.Protocol != constant2.TRIPLE {
@@ -161,9 +161,26 @@ func updateOrCreateMeshURL(rc *ReferenceConfig) {
// Refer retrieves invokers from urls.
func (rc *ReferenceConfig) Refer(srv interface{}) {
+ rc.refer(nil, srv)
+}
+
+func (rc *ReferenceConfig) ReferWithInfo(info *ClientInfo) {
+ rc.refer(info, nil)
+}
+
+func (rc *ReferenceConfig) refer(info *ClientInfo, srv interface{}) {
+ var methods []string
+ if info != nil {
+ rc.InterfaceName = info.InterfaceName
+ methods = info.MethodNames
+ rc.id = info.InterfaceName
+ rc.info = info
+ } else {
+ rc.id = common.GetReference(srv)
+ }
// If adaptive service is enabled,
// the cluster and load balance should be overridden to "adaptivesvc" and "p2c" respectively.
- if rc.rootConfig.Consumer.AdaptiveService {
+ if rc.adaptiveService {
rc.Cluster = constant.ClusterKeyAdaptiveService
rc.Loadbalance = constant.LoadBalanceKeyP2C
}
@@ -172,12 +189,15 @@ func (rc *ReferenceConfig) Refer(srv interface{}) {
cfgURL := common.NewURLWithOptions(
common.WithPath(rc.InterfaceName),
common.WithProtocol(rc.Protocol),
+ common.WithMethods(methods),
common.WithParams(rc.getURLMap()),
common.WithParamsValue(constant.BeanNameKey, rc.id),
common.WithParamsValue(constant.MetadataTypeKey, rc.metaDataType),
)
- SetConsumerServiceByInterfaceName(rc.InterfaceName, srv)
+ if info == nil {
+ config.SetConsumerServiceByInterfaceName(rc.InterfaceName, srv)
+ }
if rc.ForceTag {
cfgURL.AddParam(constant.ForceUseTag, "true")
}
@@ -220,7 +240,7 @@ func (rc *ReferenceConfig) Refer(srv interface{}) {
}
}
} else { // use registry configs
- rc.urls = loadRegistries(rc.RegistryIDs, rc.rootConfig.Registries, common.CONSUMER)
+ rc.urls = registry.LoadRegistries(rc.RegistryIDs, rc.registries, common.CONSUMER)
// set url to regURLs
for _, regURL := range rc.urls {
regURL.SubURL = cfgURL
@@ -288,18 +308,39 @@ func (rc *ReferenceConfig) Refer(srv interface{}) {
// publish consumer's metadata
publishServiceDefinition(cfgURL)
// create proxy
- if rc.Async {
- callback := GetCallback(rc.id)
- rc.pxy = extension.GetProxyFactory(rc.rootConfig.Consumer.ProxyFactory).GetAsyncProxy(rc.invoker, callback, cfgURL)
- } else {
- rc.pxy = extension.GetProxyFactory(rc.rootConfig.Consumer.ProxyFactory).GetProxy(rc.invoker, cfgURL)
+ if info == nil {
+ if rc.Async {
+ callback := config.GetCallback(rc.id)
+ rc.pxy = extension.GetProxyFactory(rc.proxyFactory).GetAsyncProxy(rc.invoker, callback, cfgURL)
+ } else {
+ rc.pxy = extension.GetProxyFactory(rc.proxyFactory).GetProxy(rc.invoker, cfgURL)
+ }
+ rc.pxy.Implement(srv)
}
}
+func (rc *ReferenceConfig) CheckAvailable() bool {
+ if rc.invoker == nil {
+ logger.Warnf("The interface %s invoker not exist, may you should check your interface config.", rc.InterfaceName)
+ return false
+ }
+ if !rc.invoker.IsAvailable() {
+ return false
+ }
+ return true
+}
+
// Implement
// @v is service provider implemented RPCService
func (rc *ReferenceConfig) Implement(v common.RPCService) {
- rc.pxy.Implement(v)
+ if rc.pxy != nil {
+ rc.pxy.Implement(v)
+ } else if rc.info != nil {
+ rc.info.ClientInjectFunc(v, &Client{
+ invoker: rc.invoker,
+ info: rc.info,
+ })
+ }
}
// GetRPCService gets RPCService from proxy
@@ -342,20 +383,22 @@ func (rc *ReferenceConfig) getURLMap() url.Values {
urlMap.Set(constant.StickyKey, strconv.FormatBool(rc.Sticky))
// applicationConfig info
- urlMap.Set(constant.ApplicationKey, rc.rootConfig.Application.Name)
- urlMap.Set(constant.OrganizationKey, rc.rootConfig.Application.Organization)
- urlMap.Set(constant.NameKey, rc.rootConfig.Application.Name)
- urlMap.Set(constant.ModuleKey, rc.rootConfig.Application.Module)
- urlMap.Set(constant.AppVersionKey, rc.rootConfig.Application.Version)
- urlMap.Set(constant.OwnerKey, rc.rootConfig.Application.Owner)
- urlMap.Set(constant.EnvironmentKey, rc.rootConfig.Application.Environment)
+ if rc.application != nil {
+ urlMap.Set(constant.ApplicationKey, rc.application.Name)
+ urlMap.Set(constant.OrganizationKey, rc.application.Organization)
+ urlMap.Set(constant.NameKey, rc.application.Name)
+ urlMap.Set(constant.ModuleKey, rc.application.Module)
+ urlMap.Set(constant.AppVersionKey, rc.application.Version)
+ urlMap.Set(constant.OwnerKey, rc.application.Owner)
+ urlMap.Set(constant.EnvironmentKey, rc.application.Environment)
+ }
// filter
defaultReferenceFilter := constant.DefaultReferenceFilters
if rc.Generic != "" {
defaultReferenceFilter = constant.GenericFilterKey + "," + defaultReferenceFilter
}
- urlMap.Set(constant.ReferenceFilterKey, mergeValue(rc.Filter, "", defaultReferenceFilter))
+ urlMap.Set(constant.ReferenceFilterKey, commonCfg.MergeValue(rc.Filter, "", defaultReferenceFilter))
for _, v := range rc.Methods {
urlMap.Set("methods."+v.Name+"."+constant.LoadbalanceKey, v.LoadBalance)
@@ -369,154 +412,41 @@ func (rc *ReferenceConfig) getURLMap() url.Values {
return urlMap
}
-// GenericLoad ...
-func (rc *ReferenceConfig) GenericLoad(id string) {
- genericService := generic.NewGenericService(rc.id)
- SetConsumerService(genericService)
- rc.id = id
- rc.Refer(genericService)
- rc.Implement(genericService)
-}
+// todo: figure this out
+//// GenericLoad ...
+//func (rc *ReferenceConfig) GenericLoad(id string) {
+// genericService := generic.NewGenericService(rc.id)
+// config.SetConsumerService(genericService)
+// rc.id = id
+// rc.Refer(genericService)
+// rc.Implement(genericService)
+//}
-// GetInvoker get invoker from ReferenceConfig
+// GetInvoker get invoker from ReferenceConfigs
func (rc *ReferenceConfig) GetInvoker() protocol.Invoker {
return rc.invoker
}
-// postProcessConfig asks registered ConfigPostProcessor to post-process the current ReferenceConfig.
+// postProcessConfig asks registered ConfigPostProcessor to post-process the current ReferenceConfigs.
func (rc *ReferenceConfig) postProcessConfig(url *common.URL) {
for _, p := range extension.GetConfigPostProcessors() {
p.PostProcessReferenceConfig(url)
}
}
-//////////////////////////////////// reference config api
-
-// newEmptyReferenceConfig returns empty ReferenceConfig
-func newEmptyReferenceConfig() *ReferenceConfig {
- newReferenceConfig := &ReferenceConfig{}
- newReferenceConfig.Methods = make([]*MethodConfig, 0, 8)
- newReferenceConfig.Params = make(map[string]string, 8)
- return newReferenceConfig
-}
-
-type ReferenceConfigBuilder struct {
- referenceConfig *ReferenceConfig
-}
-
-func NewReferenceConfigBuilder() *ReferenceConfigBuilder {
- return &ReferenceConfigBuilder{referenceConfig: newEmptyReferenceConfig()}
-}
-
-func (pcb *ReferenceConfigBuilder) SetInterface(interfaceName string) *ReferenceConfigBuilder {
- pcb.referenceConfig.InterfaceName = interfaceName
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetRegistryIDs(registryIDs ...string) *ReferenceConfigBuilder {
- pcb.referenceConfig.RegistryIDs = registryIDs
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetGeneric(generic bool) *ReferenceConfigBuilder {
- if generic {
- pcb.referenceConfig.Generic = "true"
- } else {
- pcb.referenceConfig.Generic = "false"
+func publishServiceDefinition(url *common.URL) {
+ localService, err := extension.GetLocalMetadataService(constant.DefaultKey)
+ if err != nil {
+ logger.Warnf("get local metadata service failed, please check if you have imported _ \"dubbo.apache.org/dubbo-go/v3/metadata/service/local\"")
+ return
+ }
+ localService.PublishServiceDefinition(url)
+ if url.GetParam(constant.MetadataTypeKey, "") != constant.RemoteMetadataStorageType {
+ return
+ }
+ if remoteMetadataService, err := extension.GetRemoteMetadataService(); err == nil && remoteMetadataService != nil {
+ remoteMetadataService.PublishServiceDefinition(url)
}
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetCluster(cluster string) *ReferenceConfigBuilder {
- pcb.referenceConfig.Cluster = cluster
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetSerialization(serialization string) *ReferenceConfigBuilder {
- pcb.referenceConfig.Serialization = serialization
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetProtocol(protocol string) *ReferenceConfigBuilder {
- pcb.referenceConfig.Protocol = protocol
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetURL(url string) *ReferenceConfigBuilder {
- pcb.referenceConfig.URL = url
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetFilter(filter string) *ReferenceConfigBuilder {
- pcb.referenceConfig.Filter = filter
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetLoadbalance(loadbalance string) *ReferenceConfigBuilder {
- pcb.referenceConfig.Loadbalance = loadbalance
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetRetries(retries string) *ReferenceConfigBuilder {
- pcb.referenceConfig.Retries = retries
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetGroup(group string) *ReferenceConfigBuilder {
- pcb.referenceConfig.Group = group
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetVersion(version string) *ReferenceConfigBuilder {
- pcb.referenceConfig.Version = version
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetProvidedBy(providedBy string) *ReferenceConfigBuilder {
- pcb.referenceConfig.ProvidedBy = providedBy
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetMethodConfig(methodConfigs []*MethodConfig) *ReferenceConfigBuilder {
- pcb.referenceConfig.Methods = methodConfigs
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) AddMethodConfig(methodConfig *MethodConfig) *ReferenceConfigBuilder {
- pcb.referenceConfig.Methods = append(pcb.referenceConfig.Methods, methodConfig)
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetAsync(async bool) *ReferenceConfigBuilder {
- pcb.referenceConfig.Async = async
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetParams(params map[string]string) *ReferenceConfigBuilder {
- pcb.referenceConfig.Params = params
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetSticky(sticky bool) *ReferenceConfigBuilder {
- pcb.referenceConfig.Sticky = sticky
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetRequestTimeout(requestTimeout string) *ReferenceConfigBuilder {
- pcb.referenceConfig.RequestTimeout = requestTimeout
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetForceTag(forceTag bool) *ReferenceConfigBuilder {
- pcb.referenceConfig.ForceTag = forceTag
- return pcb
-}
-
-func (pcb *ReferenceConfigBuilder) SetTracingKey(tracingKey string) *ReferenceConfigBuilder {
- pcb.referenceConfig.TracingKey = tracingKey
- return pcb
}
-func (pcb *ReferenceConfigBuilder) Build() *ReferenceConfig {
- return pcb.referenceConfig
-}
+type ReferenceOption func(*ReferenceConfig)
diff --git a/config/application_config.go b/common/config/application.go
similarity index 65%
copy from config/application_config.go
copy to common/config/application.go
index 60ea32f1f..246346b0a 100644
--- a/config/application_config.go
+++ b/common/config/application.go
@@ -61,52 +61,61 @@ func (ac *ApplicationConfig) check() error {
if err := defaults.Set(ac); err != nil {
return err
}
- return verify(ac)
+ return Verify(ac)
}
-func NewApplicationConfigBuilder() *ApplicationConfigBuilder {
- return &ApplicationConfigBuilder{application: &ApplicationConfig{}}
-}
+type ApplicationOption func(*ApplicationConfig)
-type ApplicationConfigBuilder struct {
- application *ApplicationConfig
+func WithOrganization(organization string) ApplicationOption {
+ return func(cfg *ApplicationConfig) {
+ cfg.Organization = organization
+ }
}
-func (acb *ApplicationConfigBuilder) SetOrganization(organization string) *ApplicationConfigBuilder {
- acb.application.Organization = organization
- return acb
+func WithName(name string) ApplicationOption {
+ return func(cfg *ApplicationConfig) {
+ cfg.Name = name
+ }
}
-func (acb *ApplicationConfigBuilder) SetName(name string) *ApplicationConfigBuilder {
- acb.application.Name = name
- return acb
+func WithModule(module string) ApplicationOption {
+ return func(cfg *ApplicationConfig) {
+ cfg.Module = module
+ }
}
-func (acb *ApplicationConfigBuilder) SetModule(module string) *ApplicationConfigBuilder {
- acb.application.Module = module
- return acb
+func WithGroup(group string) ApplicationOption {
+ return func(cfg *ApplicationConfig) {
+ cfg.Group = group
+ }
}
-func (acb *ApplicationConfigBuilder) SetVersion(version string) *ApplicationConfigBuilder {
- acb.application.Version = version
- return acb
+func WithVersion(version string) ApplicationOption {
+ return func(cfg *ApplicationConfig) {
+ cfg.Version = version
+ }
}
-func (acb *ApplicationConfigBuilder) SetOwner(owner string) *ApplicationConfigBuilder {
- acb.application.Owner = owner
- return acb
+func WithOwner(owner string) ApplicationOption {
+ return func(cfg *ApplicationConfig) {
+ cfg.Owner = owner
+ }
}
-func (acb *ApplicationConfigBuilder) SetEnvironment(environment string) *ApplicationConfigBuilder {
- acb.application.Environment = environment
- return acb
+func WithEnvironment(environment string) ApplicationOption {
+ return func(cfg *ApplicationConfig) {
+ cfg.Environment = environment
+ }
}
-func (acb *ApplicationConfigBuilder) SetMetadataType(metadataType string) *ApplicationConfigBuilder {
- acb.application.MetadataType = metadataType
- return acb
+func WithMetadataType(metadataType string) ApplicationOption {
+ return func(cfg *ApplicationConfig) {
+ cfg.MetadataType = metadataType
+ }
}
-func (acb *ApplicationConfigBuilder) Build() *ApplicationConfig {
- return acb.application
+func WithTag(tag string) ApplicationOption {
+ return func(cfg *ApplicationConfig) {
+ cfg.Tag = tag
+ }
}
diff --git a/common/config/utils.go b/common/config/utils.go
new file mode 100644
index 000000000..ffe900013
--- /dev/null
+++ b/common/config/utils.go
@@ -0,0 +1,105 @@
+package config
+
+import (
+ "fmt"
+ "regexp"
+ "strings"
+)
+
+import (
+ "github.com/go-playground/validator/v10"
+
+ perrors "github.com/pkg/errors"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+ "dubbo.apache.org/dubbo-go/v3/common/extension"
+)
+
+var validate *validator.Validate
+
+func init() {
+ validate = validator.New()
+}
+
+// TranslateIds string "nacos,zk" => ["nacos","zk"]
+func TranslateIds(registryIds []string) []string {
+ ids := make([]string, 0)
+ for _, id := range registryIds {
+
+ ids = append(ids, strings.Split(id, ",")...)
+ }
+ return removeDuplicateElement(ids)
+}
+
+// removeDuplicateElement remove duplicate element
+func removeDuplicateElement(items []string) []string {
+ result := make([]string, 0, len(items))
+ temp := map[string]struct{}{}
+ for _, item := range items {
+ if _, ok := temp[item]; !ok && item != "" {
+ temp[item] = struct{}{}
+ result = append(result, item)
+ }
+ }
+ return result
+}
+
+func Verify(s interface{}) error {
+ if err := validate.Struct(s); err != nil {
+ errs := err.(validator.ValidationErrors)
+ var slice []string
+ for _, msg := range errs {
+ slice = append(slice, msg.Error())
+ }
+ return perrors.New(strings.Join(slice, ","))
+ }
+ return nil
+}
+
+func MergeValue(str1, str2, def string) string {
+ if str1 == "" && str2 == "" {
+ return def
+ }
+ s1 := strings.Split(str1, ",")
+ s2 := strings.Split(str2, ",")
+ str := "," + strings.Join(append(s1, s2...), ",")
+ defKey := strings.Contains(str, ","+constant.DefaultKey)
+ if !defKey {
+ str = "," + constant.DefaultKey + str
+ }
+ str = strings.TrimPrefix(strings.Replace(str, ","+constant.DefaultKey, ","+def, -1), ",")
+ return removeMinus(strings.Split(str, ","))
+}
+
+func removeMinus(strArr []string) string {
+ if len(strArr) == 0 {
+ return ""
+ }
+ var normalStr string
+ var minusStrArr []string
+ for _, v := range strArr {
+ if strings.HasPrefix(v, "-") {
+ minusStrArr = append(minusStrArr, v[1:])
+ } else {
+ normalStr += fmt.Sprintf(",%s", v)
+ }
+ }
+ normalStr = strings.Trim(normalStr, ",")
+ for _, v := range minusStrArr {
+ normalStr = strings.Replace(normalStr, v, "", 1)
+ }
+ reg := regexp.MustCompile("[,]+")
+ normalStr = reg.ReplaceAllString(strings.Trim(normalStr, ","), ",")
+ return normalStr
+}
+
+// ClientNameID unique identifier id for client
+func ClientNameID(config extension.Config, protocol, address string) string {
+ return strings.Join([]string{config.Prefix(), protocol, address}, "-")
+}
+
+func IsValid(addr string) bool {
+ return addr != "" && addr != constant.NotAvailable
+}
diff --git a/common/constant/key.go b/common/constant/key.go
index b786b9951..1ca2e6567 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -136,6 +136,11 @@ const (
RetryTimesKey = "retry.times"
CycleReportKey = "cycle.report"
DefaultBlackListRecoverBlock = 16
+ CallTypeKey = "call-type"
+ CallUnary = "unary"
+ CallClientStream = "client-stream"
+ CallServerStream = "server-stream"
+ CallBidiStream = "bidi-stream"
)
const (
diff --git a/config/application_config.go b/config/application_config.go
index 60ea32f1f..88a42c90e 100644
--- a/config/application_config.go
+++ b/config/application_config.go
@@ -18,58 +18,15 @@
package config
import (
- "github.com/creasty/defaults"
-
- "github.com/pkg/errors"
-)
-
-import (
- "dubbo.apache.org/dubbo-go/v3/common/constant"
+ commonCfg "dubbo.apache.org/dubbo-go/v3/common/config"
)
-// ApplicationConfig is a configuration for current applicationConfig, whether the applicationConfig is a provider or a consumer
-type ApplicationConfig struct {
- Organization string `default:"dubbo-go" yaml:"organization" json:"organization,omitempty" property:"organization"`
- Name string `default:"dubbo.io" yaml:"name" json:"name,omitempty" property:"name"`
- Module string `default:"sample" yaml:"module" json:"module,omitempty" property:"module"`
- Group string `yaml:"group" json:"group,omitempty" property:"module"`
- Version string `yaml:"version" json:"version,omitempty" property:"version"`
- Owner string `default:"dubbo-go" yaml:"owner" json:"owner,omitempty" property:"owner"`
- Environment string `yaml:"environment" json:"environment,omitempty" property:"environment"`
- // the metadata type. remote or local
- MetadataType string `default:"local" yaml:"metadata-type" json:"metadataType,omitempty" property:"metadataType"`
- Tag string `yaml:"tag" json:"tag,omitempty" property:"tag"`
-}
-
-// Prefix dubbo.application
-func (ac *ApplicationConfig) Prefix() string {
- return constant.ApplicationConfigPrefix
-}
-
-// Init application config and set default value
-func (ac *ApplicationConfig) Init() error {
- if ac == nil {
- return errors.New("application is null")
- }
- if err := ac.check(); err != nil {
- return err
- }
- return nil
-}
-
-func (ac *ApplicationConfig) check() error {
- if err := defaults.Set(ac); err != nil {
- return err
- }
- return verify(ac)
-}
-
func NewApplicationConfigBuilder() *ApplicationConfigBuilder {
- return &ApplicationConfigBuilder{application: &ApplicationConfig{}}
+ return &ApplicationConfigBuilder{application: &commonCfg.ApplicationConfig{}}
}
type ApplicationConfigBuilder struct {
- application *ApplicationConfig
+ application *commonCfg.ApplicationConfig
}
func (acb *ApplicationConfigBuilder) SetOrganization(organization string) *ApplicationConfigBuilder {
@@ -107,6 +64,6 @@ func (acb *ApplicationConfigBuilder) SetMetadataType(metadataType string) *Appli
return acb
}
-func (acb *ApplicationConfigBuilder) Build() *ApplicationConfig {
+func (acb *ApplicationConfigBuilder) Build() *commonCfg.ApplicationConfig {
return acb.application
}
diff --git a/config/consumer_config.go b/config/consumer_config.go
index c49811f6a..89170a3be 100644
--- a/config/consumer_config.go
+++ b/config/consumer_config.go
@@ -32,6 +32,7 @@ import (
)
import (
+ "dubbo.apache.org/dubbo-go/v3/client"
"dubbo.apache.org/dubbo-go/v3/common"
"dubbo.apache.org/dubbo-go/v3/common/constant"
)
@@ -42,19 +43,21 @@ const (
// ConsumerConfig is Consumer default configuration
type ConsumerConfig struct {
- Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"`
- RegistryIDs []string `yaml:"registry-ids" json:"registry-ids,omitempty" property:"registry-ids"`
- Protocol string `yaml:"protocol" json:"protocol,omitempty" property:"protocol"`
- RequestTimeout string `default:"3s" yaml:"request-timeout" json:"request-timeout,omitempty" property:"request-timeout"`
- ProxyFactory string `default:"default" yaml:"proxy" json:"proxy,omitempty" property:"proxy"`
- Check bool `yaml:"check" json:"check,omitempty" property:"check"`
- AdaptiveService bool `default:"false" yaml:"adaptive-service" json:"adaptive-service" property:"adaptive-service"`
- References map[string]*ReferenceConfig `yaml:"references" json:"references,omitempty" property:"references"`
- TracingKey string `yaml:"tracing-key" json:"tracing-key" property:"tracing-key"`
- FilterConf interface{} `yaml:"filter-conf" json:"filter-conf,omitempty" property:"filter-conf"`
- MaxWaitTimeForServiceDiscovery string `default:"3s" yaml:"max-wait-time-for-service-discovery" json:"max-wait-time-for-service-discovery,omitempty" property:"max-wait-time-for-service-discovery"`
- MeshEnabled bool `yaml:"mesh-enabled" json:"mesh-enabled,omitempty" property:"mesh-enabled"`
+ Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"`
+ RegistryIDs []string `yaml:"registry-ids" json:"registry-ids,omitempty" property:"registry-ids"`
+ Protocol string `yaml:"protocol" json:"protocol,omitempty" property:"protocol"`
+ RequestTimeout string `default:"3s" yaml:"request-timeout" json:"request-timeout,omitempty" property:"request-timeout"`
+ ProxyFactory string `default:"default" yaml:"proxy" json:"proxy,omitempty" property:"proxy"`
+ Check bool `yaml:"check" json:"check,omitempty" property:"check"`
+ AdaptiveService bool `default:"false" yaml:"adaptive-service" json:"adaptive-service" property:"adaptive-service"`
+ References map[string]*client.ReferenceConfig `yaml:"references" json:"references,omitempty" property:"references"`
+ TracingKey string `yaml:"tracing-key" json:"tracing-key" property:"tracing-key"`
+ FilterConf interface{} `yaml:"filter-conf" json:"filter-conf,omitempty" property:"filter-conf"`
+ MaxWaitTimeForServiceDiscovery string `default:"3s" yaml:"max-wait-time-for-service-discovery" json:"max-wait-time-for-service-discovery,omitempty" property:"max-wait-time-for-service-discovery"`
+ MeshEnabled bool `yaml:"mesh-enabled" json:"mesh-enabled,omitempty" property:"mesh-enabled"`
rootConfig *RootConfig
+
+ refOpts []client.ReferenceOption
}
// Prefix dubbo.consumer
@@ -89,6 +92,20 @@ func (cc *ConsumerConfig) Init(rc *RootConfig) error {
break
}
}
+
+ cc.refOpts = []client.ReferenceOption{
+ client.WithFilter(cc.Filter),
+ client.WithRegistryIDs(cc.RegistryIDs),
+ client.WithProtocol(cc.Protocol),
+ client.WithTracingKey(cc.TracingKey),
+ client.WithCheck(cc.Check),
+ client.WithMeshEnabled(cc.MeshEnabled),
+ client.WithAdaptiveService(cc.AdaptiveService),
+ client.WithProxyFactory(cc.ProxyFactory),
+ client.WithApplication(rc.Application),
+ client.WithRegistries(rc.Registries),
+ }
+
for key, referenceConfig := range cc.References {
if referenceConfig.InterfaceName == "" {
reference := GetConsumerService(key)
@@ -105,10 +122,11 @@ func (cc *ConsumerConfig) Init(rc *RootConfig) error {
referenceConfig.InterfaceName = triplePBService.XXX_InterfaceName()
}
}
- if err := referenceConfig.Init(rc); err != nil {
+ if err := referenceConfig.Init(cc.refOpts...); err != nil {
return err
}
}
+ // todo: maybe defaults.Set function should be moved to upper place?
if err := defaults.Set(cc); err != nil {
return err
}
@@ -137,16 +155,25 @@ func (cc *ConsumerConfig) Load() {
// use interface name defined by pb
refConfig.InterfaceName = triplePBService.XXX_InterfaceName()
}
- if err := refConfig.Init(rootConfig); err != nil {
+ if err := refConfig.Init(cc.refOpts...); err != nil {
logger.Errorf(fmt.Sprintf("reference with registeredTypeName = %s init failed! err: %#v", registeredTypeName, err))
continue
}
}
- refConfig.id = registeredTypeName
refConfig.Refer(refRPCService)
refConfig.Implement(refRPCService)
}
+ for info, refRPCService := range GetClientInfoServicesMap() {
+ refConfig, ok := cc.References[info.InterfaceName]
+ if !ok {
+ logger.Errorf("Dubbo-go can not find %s Reference in References config, please check your configuration file", info.InterfaceName)
+ continue
+ }
+ refConfig.ReferWithInfo(info)
+ refConfig.Implement(refRPCService)
+ }
+
var maxWait int
if maxWaitDuration, err := time.ParseDuration(cc.MaxWaitTimeForServiceDiscovery); err != nil {
@@ -165,7 +192,7 @@ func (cc *ConsumerConfig) Load() {
(ref.Check == nil && cc.Check && GetProviderService(key) == nil) ||
(ref.Check == nil && GetProviderService(key) == nil) { // default to true
- if ref.invoker != nil && !ref.invoker.IsAvailable() {
+ if !ref.CheckAvailable() {
checkok = false
count++
if count > maxWait {
@@ -176,9 +203,6 @@ func (cc *ConsumerConfig) Load() {
time.Sleep(time.Second * 1)
break
}
- if ref.invoker == nil {
- logger.Warnf("The interface %s invoker not exist, may you should check your interface config.", ref.InterfaceName)
- }
}
}
if checkok {
@@ -194,7 +218,7 @@ func SetConsumerConfig(c ConsumerConfig) {
func newEmptyConsumerConfig() *ConsumerConfig {
newConsumerConfig := &ConsumerConfig{
- References: make(map[string]*ReferenceConfig, 8),
+ References: make(map[string]*client.ReferenceConfig, 8),
RequestTimeout: "3s",
Check: true,
}
@@ -239,12 +263,12 @@ func (ccb *ConsumerConfigBuilder) SetCheck(check bool) *ConsumerConfigBuilder {
return ccb
}
-func (ccb *ConsumerConfigBuilder) AddReference(referenceKey string, referenceConfig *ReferenceConfig) *ConsumerConfigBuilder {
+func (ccb *ConsumerConfigBuilder) AddReference(referenceKey string, referenceConfig *client.ReferenceConfig) *ConsumerConfigBuilder {
ccb.consumerConfig.References[referenceKey] = referenceConfig
return ccb
}
-func (ccb *ConsumerConfigBuilder) SetReferences(references map[string]*ReferenceConfig) *ConsumerConfigBuilder {
+func (ccb *ConsumerConfigBuilder) SetReferences(references map[string]*client.ReferenceConfig) *ConsumerConfigBuilder {
ccb.consumerConfig.References = references
return ccb
}
diff --git a/config/reference_config.go b/config/reference_config.go
index 06797a8ec..824f315f4 100644
--- a/config/reference_config.go
+++ b/config/reference_config.go
@@ -18,390 +18,20 @@
package config
import (
- "fmt"
- "net/url"
- "os"
- "strconv"
- "time"
+ "dubbo.apache.org/dubbo-go/v3/client"
)
-import (
- "github.com/creasty/defaults"
-
- "github.com/dubbogo/gost/log/logger"
- gxstrings "github.com/dubbogo/gost/strings"
-
- constant2 "github.com/dubbogo/triple/pkg/common/constant"
-)
-
-import (
- "dubbo.apache.org/dubbo-go/v3/cluster/directory/static"
- "dubbo.apache.org/dubbo-go/v3/common"
- "dubbo.apache.org/dubbo-go/v3/common/constant"
- "dubbo.apache.org/dubbo-go/v3/common/extension"
- "dubbo.apache.org/dubbo-go/v3/config/generic"
- "dubbo.apache.org/dubbo-go/v3/protocol"
- "dubbo.apache.org/dubbo-go/v3/protocol/protocolwrapper"
- "dubbo.apache.org/dubbo-go/v3/proxy"
-)
-
-// ReferenceConfig is the configuration of service consumer
-type ReferenceConfig struct {
- pxy *proxy.Proxy
- id string
- InterfaceName string `yaml:"interface" json:"interface,omitempty" property:"interface"`
- Check *bool `yaml:"check" json:"check,omitempty" property:"check"`
- URL string `yaml:"url" json:"url,omitempty" property:"url"`
- Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"`
- Protocol string `yaml:"protocol" json:"protocol,omitempty" property:"protocol"`
- RegistryIDs []string `yaml:"registry-ids" json:"registry-ids,omitempty" property:"registry-ids"`
- Cluster string `yaml:"cluster" json:"cluster,omitempty" property:"cluster"`
- Loadbalance string `yaml:"loadbalance" json:"loadbalance,omitempty" property:"loadbalance"`
- Retries string `yaml:"retries" json:"retries,omitempty" property:"retries"`
- Group string `yaml:"group" json:"group,omitempty" property:"group"`
- Version string `yaml:"version" json:"version,omitempty" property:"version"`
- Serialization string `yaml:"serialization" json:"serialization" property:"serialization"`
- ProvidedBy string `yaml:"provided_by" json:"provided_by,omitempty" property:"provided_by"`
- Methods []*MethodConfig `yaml:"methods" json:"methods,omitempty" property:"methods"`
- Async bool `yaml:"async" json:"async,omitempty" property:"async"`
- Params map[string]string `yaml:"params" json:"params,omitempty" property:"params"`
- invoker protocol.Invoker
- urls []*common.URL
- Generic string `yaml:"generic" json:"generic,omitempty" property:"generic"`
- Sticky bool `yaml:"sticky" json:"sticky,omitempty" property:"sticky"`
- RequestTimeout string `yaml:"timeout" json:"timeout,omitempty" property:"timeout"`
- ForceTag bool `yaml:"force.tag" json:"force.tag,omitempty" property:"force.tag"`
- TracingKey string `yaml:"tracing-key" json:"tracing-key,omitempty" propertiy:"tracing-key"`
- rootConfig *RootConfig
- metaDataType string
- MeshProviderPort int `yaml:"mesh-provider-port" json:"mesh-provider-port,omitempty" propertiy:"mesh-provider-port"`
-}
-
-func (rc *ReferenceConfig) Prefix() string {
- return constant.ReferenceConfigPrefix + rc.InterfaceName + "."
-}
-
-func (rc *ReferenceConfig) Init(root *RootConfig) error {
- for _, method := range rc.Methods {
- if err := method.Init(); err != nil {
- return err
- }
- }
- if err := defaults.Set(rc); err != nil {
- return err
- }
- rc.rootConfig = root
- if root.Application != nil {
- rc.metaDataType = root.Application.MetadataType
- if rc.Group == "" {
- rc.Group = root.Application.Group
- }
- if rc.Version == "" {
- rc.Version = root.Application.Version
- }
- }
- if rc.Filter == "" {
- rc.Filter = root.Consumer.Filter
- }
- if rc.Cluster == "" {
- rc.Cluster = "failover"
- }
- rc.RegistryIDs = translateIds(rc.RegistryIDs)
- if len(rc.RegistryIDs) <= 0 {
- rc.RegistryIDs = root.Consumer.RegistryIDs
- }
-
- if rc.Protocol == "" {
- rc.Protocol = root.Consumer.Protocol
- }
-
- if rc.TracingKey == "" {
- rc.TracingKey = root.Consumer.TracingKey
- }
- if rc.Check == nil {
- rc.Check = &root.Consumer.Check
- }
- return verify(rc)
-}
-
-func getEnv(key, fallback string) string {
- if value, ok := os.LookupEnv(key); ok {
- return value
- }
- return fallback
-}
-
-func updateOrCreateMeshURL(rc *ReferenceConfig) {
- if rc.URL != "" {
- logger.Infof("URL specified explicitly %v", rc.URL)
- }
-
- if !rc.rootConfig.Consumer.MeshEnabled {
- return
- }
- if rc.Protocol != constant2.TRIPLE {
- panic(fmt.Sprintf("Mesh mode enabled, Triple protocol expected but %v protocol found!", rc.Protocol))
- }
- if rc.ProvidedBy == "" {
- panic("Mesh mode enabled, provided-by should not be empty!")
- }
-
- podNamespace := getEnv(constant.PodNamespaceEnvKey, constant.DefaultNamespace)
- clusterDomain := getEnv(constant.ClusterDomainKey, constant.DefaultClusterDomain)
-
- var meshPort int
- if rc.MeshProviderPort > 0 {
- meshPort = rc.MeshProviderPort
- } else {
- meshPort = constant.DefaultMeshPort
- }
-
- rc.URL = "tri://" + rc.ProvidedBy + "." + podNamespace + constant.SVC + clusterDomain + ":" + strconv.Itoa(meshPort)
-}
-
-// Refer retrieves invokers from urls.
-func (rc *ReferenceConfig) Refer(srv interface{}) {
- // If adaptive service is enabled,
- // the cluster and load balance should be overridden to "adaptivesvc" and "p2c" respectively.
- if rc.rootConfig.Consumer.AdaptiveService {
- rc.Cluster = constant.ClusterKeyAdaptiveService
- rc.Loadbalance = constant.LoadBalanceKeyP2C
- }
-
- // cfgURL is an interface-level invoker url, in the other words, it represents an interface.
- cfgURL := common.NewURLWithOptions(
- common.WithPath(rc.InterfaceName),
- common.WithProtocol(rc.Protocol),
- common.WithParams(rc.getURLMap()),
- common.WithParamsValue(constant.BeanNameKey, rc.id),
- common.WithParamsValue(constant.MetadataTypeKey, rc.metaDataType),
- )
-
- SetConsumerServiceByInterfaceName(rc.InterfaceName, srv)
- if rc.ForceTag {
- cfgURL.AddParam(constant.ForceUseTag, "true")
- }
- rc.postProcessConfig(cfgURL)
-
- // if mesh-enabled is set
- updateOrCreateMeshURL(rc)
-
- // retrieving urls from config, and appending the urls to rc.urls
- if rc.URL != "" { // use user-specific urls
- /*
- Two types of URL are allowed for rc.URL:
- 1. direct url: server IP, that is, no need for a registry anymore
- 2. registry url
- They will be handled in different ways:
- For example, we have a direct url and a registry url:
- 1. "tri://localhost:10000" is a direct url
- 2. "registry://localhost:2181" is a registry url.
- Then, rc.URL looks like a string separated by semicolon: "tri://localhost:10000;registry://localhost:2181".
- The result of urlStrings is a string array: []string{"tri://localhost:10000", "registry://localhost:2181"}.
- */
- urlStrings := gxstrings.RegSplit(rc.URL, "\\s*[;]+\\s*")
- for _, urlStr := range urlStrings {
- serviceURL, err := common.NewURL(urlStr)
- if err != nil {
- panic(fmt.Sprintf("url configuration error, please check your configuration, user specified URL %v refer error, error message is %v ", urlStr, err.Error()))
- }
- if serviceURL.Protocol == constant.RegistryProtocol { // serviceURL in this branch is a registry protocol
- serviceURL.SubURL = cfgURL
- rc.urls = append(rc.urls, serviceURL)
- } else { // serviceURL in this branch is the target endpoint IP address
- if serviceURL.Path == "" {
- serviceURL.Path = "/" + rc.InterfaceName
- }
- // replace params of serviceURL with params of cfgUrl
- // other stuff, e.g. IP, port, etc., are same as serviceURL
- newURL := common.MergeURL(serviceURL, cfgURL)
- newURL.AddParam("peer", "true")
- rc.urls = append(rc.urls, newURL)
- }
- }
- } else { // use registry configs
- rc.urls = loadRegistries(rc.RegistryIDs, rc.rootConfig.Registries, common.CONSUMER)
- // set url to regURLs
- for _, regURL := range rc.urls {
- regURL.SubURL = cfgURL
- }
- }
-
- // Get invokers according to rc.urls
- var (
- invoker protocol.Invoker
- regURL *common.URL
- )
- invokers := make([]protocol.Invoker, len(rc.urls))
- for i, u := range rc.urls {
- if u.Protocol == constant.ServiceRegistryProtocol {
- invoker = extension.GetProtocol(constant.RegistryProtocol).Refer(u)
- } else {
- invoker = extension.GetProtocol(u.Protocol).Refer(u)
- }
-
- if rc.URL != "" {
- invoker = protocolwrapper.BuildInvokerChain(invoker, constant.ReferenceFilterKey)
- }
-
- invokers[i] = invoker
- if u.Protocol == constant.RegistryProtocol {
- regURL = u
- }
- }
-
- // TODO(hxmhlt): decouple from directory, config should not depend on directory module
- if len(invokers) == 1 {
- rc.invoker = invokers[0]
- if rc.URL != "" {
- hitClu := constant.ClusterKeyFailover
- if u := rc.invoker.GetURL(); u != nil {
- hitClu = u.GetParam(constant.ClusterKey, constant.ClusterKeyZoneAware)
- }
- cluster, err := extension.GetCluster(hitClu)
- if err != nil {
- panic(err)
- } else {
- rc.invoker = cluster.Join(static.NewDirectory(invokers))
- }
- }
- } else {
- var hitClu string
- if regURL != nil {
- // for multi-subscription scenario, use 'zone-aware' policy by default
- hitClu = constant.ClusterKeyZoneAware
- } else {
- // not a registry url, must be direct invoke.
- hitClu = constant.ClusterKeyFailover
- if u := invokers[0].GetURL(); u != nil {
- hitClu = u.GetParam(constant.ClusterKey, constant.ClusterKeyZoneAware)
- }
- }
- cluster, err := extension.GetCluster(hitClu)
- if err != nil {
- panic(err)
- } else {
- rc.invoker = cluster.Join(static.NewDirectory(invokers))
- }
- }
-
- // publish consumer's metadata
- publishServiceDefinition(cfgURL)
- // create proxy
- if rc.Async {
- callback := GetCallback(rc.id)
- rc.pxy = extension.GetProxyFactory(rc.rootConfig.Consumer.ProxyFactory).GetAsyncProxy(rc.invoker, callback, cfgURL)
- } else {
- rc.pxy = extension.GetProxyFactory(rc.rootConfig.Consumer.ProxyFactory).GetProxy(rc.invoker, cfgURL)
- }
-}
-
-// Implement
-// @v is service provider implemented RPCService
-func (rc *ReferenceConfig) Implement(v common.RPCService) {
- rc.pxy.Implement(v)
-}
-
-// GetRPCService gets RPCService from proxy
-func (rc *ReferenceConfig) GetRPCService() common.RPCService {
- return rc.pxy.Get()
-}
-
-// GetProxy gets proxy
-func (rc *ReferenceConfig) GetProxy() *proxy.Proxy {
- return rc.pxy
-}
-
-func (rc *ReferenceConfig) getURLMap() url.Values {
- urlMap := url.Values{}
- // first set user params
- for k, v := range rc.Params {
- urlMap.Set(k, v)
- }
- urlMap.Set(constant.InterfaceKey, rc.InterfaceName)
- urlMap.Set(constant.TimestampKey, strconv.FormatInt(time.Now().Unix(), 10))
- urlMap.Set(constant.ClusterKey, rc.Cluster)
- urlMap.Set(constant.LoadbalanceKey, rc.Loadbalance)
- urlMap.Set(constant.RetriesKey, rc.Retries)
- urlMap.Set(constant.GroupKey, rc.Group)
- urlMap.Set(constant.VersionKey, rc.Version)
- urlMap.Set(constant.GenericKey, rc.Generic)
- urlMap.Set(constant.RegistryRoleKey, strconv.Itoa(common.CONSUMER))
- urlMap.Set(constant.ProvidedBy, rc.ProvidedBy)
- urlMap.Set(constant.SerializationKey, rc.Serialization)
- urlMap.Set(constant.TracingConfigKey, rc.TracingKey)
-
- urlMap.Set(constant.ReleaseKey, "dubbo-golang-"+constant.Version)
- urlMap.Set(constant.SideKey, (common.RoleType(common.CONSUMER)).Role())
-
- if len(rc.RequestTimeout) != 0 {
- urlMap.Set(constant.TimeoutKey, rc.RequestTimeout)
- }
- // getty invoke async or sync
- urlMap.Set(constant.AsyncKey, strconv.FormatBool(rc.Async))
- urlMap.Set(constant.StickyKey, strconv.FormatBool(rc.Sticky))
-
- // applicationConfig info
- urlMap.Set(constant.ApplicationKey, rc.rootConfig.Application.Name)
- urlMap.Set(constant.OrganizationKey, rc.rootConfig.Application.Organization)
- urlMap.Set(constant.NameKey, rc.rootConfig.Application.Name)
- urlMap.Set(constant.ModuleKey, rc.rootConfig.Application.Module)
- urlMap.Set(constant.AppVersionKey, rc.rootConfig.Application.Version)
- urlMap.Set(constant.OwnerKey, rc.rootConfig.Application.Owner)
- urlMap.Set(constant.EnvironmentKey, rc.rootConfig.Application.Environment)
-
- // filter
- defaultReferenceFilter := constant.DefaultReferenceFilters
- if rc.Generic != "" {
- defaultReferenceFilter = constant.GenericFilterKey + "," + defaultReferenceFilter
- }
- urlMap.Set(constant.ReferenceFilterKey, mergeValue(rc.Filter, "", defaultReferenceFilter))
-
- for _, v := range rc.Methods {
- urlMap.Set("methods."+v.Name+"."+constant.LoadbalanceKey, v.LoadBalance)
- urlMap.Set("methods."+v.Name+"."+constant.RetriesKey, v.Retries)
- urlMap.Set("methods."+v.Name+"."+constant.StickyKey, strconv.FormatBool(v.Sticky))
- if len(v.RequestTimeout) != 0 {
- urlMap.Set("methods."+v.Name+"."+constant.TimeoutKey, v.RequestTimeout)
- }
- }
-
- return urlMap
-}
-
-// GenericLoad ...
-func (rc *ReferenceConfig) GenericLoad(id string) {
- genericService := generic.NewGenericService(rc.id)
- SetConsumerService(genericService)
- rc.id = id
- rc.Refer(genericService)
- rc.Implement(genericService)
-}
-
-// GetInvoker get invoker from ReferenceConfig
-func (rc *ReferenceConfig) GetInvoker() protocol.Invoker {
- return rc.invoker
-}
-
-// postProcessConfig asks registered ConfigPostProcessor to post-process the current ReferenceConfig.
-func (rc *ReferenceConfig) postProcessConfig(url *common.URL) {
- for _, p := range extension.GetConfigPostProcessors() {
- p.PostProcessReferenceConfig(url)
- }
-}
-
//////////////////////////////////// reference config api
-
// newEmptyReferenceConfig returns empty ReferenceConfig
-func newEmptyReferenceConfig() *ReferenceConfig {
- newReferenceConfig := &ReferenceConfig{}
- newReferenceConfig.Methods = make([]*MethodConfig, 0, 8)
+func newEmptyReferenceConfig() *client.ReferenceConfig {
+ newReferenceConfig := &client.ReferenceConfig{}
+ newReferenceConfig.Methods = make([]*client.MethodConfig, 0, 8)
newReferenceConfig.Params = make(map[string]string, 8)
return newReferenceConfig
}
type ReferenceConfigBuilder struct {
- referenceConfig *ReferenceConfig
+ referenceConfig *client.ReferenceConfig
}
func NewReferenceConfigBuilder() *ReferenceConfigBuilder {
@@ -477,13 +107,13 @@ func (pcb *ReferenceConfigBuilder) SetProvidedBy(providedBy string) *ReferenceCo
return pcb
}
-func (pcb *ReferenceConfigBuilder) SetMethodConfig(methodConfigs []*MethodConfig) *ReferenceConfigBuilder {
+func (pcb *ReferenceConfigBuilder) SetMethodConfig(methodConfigs []*client.MethodConfig) *ReferenceConfigBuilder {
pcb.referenceConfig.Methods = methodConfigs
return pcb
}
-func (pcb *ReferenceConfigBuilder) AddMethodConfig(methodConfig *MethodConfig) *ReferenceConfigBuilder {
- pcb.referenceConfig.Methods = append(pcb.referenceConfig.Methods, methodConfig)
+func (pcb *ReferenceConfigBuilder) AddMethodConfig(methodConfigs *client.MethodConfig) *ReferenceConfigBuilder {
+ pcb.referenceConfig.Methods = append(pcb.referenceConfig.Methods, methodConfigs)
return pcb
}
@@ -517,6 +147,6 @@ func (pcb *ReferenceConfigBuilder) SetTracingKey(tracingKey string) *ReferenceCo
return pcb
}
-func (pcb *ReferenceConfigBuilder) Build() *ReferenceConfig {
+func (pcb *ReferenceConfigBuilder) Build() *client.ReferenceConfig {
return pcb.referenceConfig
}
diff --git a/config/registry_config.go b/config/registry_config.go
index 894832416..2f196fe05 100644
--- a/config/registry_config.go
+++ b/config/registry_config.go
@@ -18,281 +18,44 @@
package config
import (
- "net/url"
- "strconv"
- "strings"
-)
-
-import (
- "github.com/creasty/defaults"
-
- "github.com/dubbogo/gost/log/logger"
-
- perrors "github.com/pkg/errors"
-)
-
-import (
- "dubbo.apache.org/dubbo-go/v3/common"
- "dubbo.apache.org/dubbo-go/v3/common/constant"
- "dubbo.apache.org/dubbo-go/v3/common/extension"
- "dubbo.apache.org/dubbo-go/v3/config/instance"
"dubbo.apache.org/dubbo-go/v3/registry"
)
-// RegistryConfig is the configuration of the registry center
-type RegistryConfig struct {
- Protocol string `validate:"required" yaml:"protocol" json:"protocol,omitempty" property:"protocol"`
- Timeout string `default:"5s" validate:"required" yaml:"timeout" json:"timeout,omitempty" property:"timeout"` // unit: second
- Group string `yaml:"group" json:"group,omitempty" property:"group"`
- Namespace string `yaml:"namespace" json:"namespace,omitempty" property:"namespace"`
- TTL string `default:"15m" yaml:"ttl" json:"ttl,omitempty" property:"ttl"` // unit: minute
- Address string `validate:"required" yaml:"address" json:"address,omitempty" property:"address"`
- Username string `yaml:"username" json:"username,omitempty" property:"username"`
- Password string `yaml:"password" json:"password,omitempty" property:"password"`
- Simplified bool `yaml:"simplified" json:"simplified,omitempty" property:"simplified"`
- Preferred bool `yaml:"preferred" json:"preferred,omitempty" property:"preferred"` // Always use this registry first if set to true, useful when subscribe to multiple registriesConfig
- Zone string `yaml:"zone" json:"zone,omitempty" property:"zone"` // The region where the registry belongs, usually used to isolate traffics
- Weight int64 `yaml:"weight" json:"weight,omitempty" property:"weight"` // Affects traffic distribution among registriesConfig, useful when subscribe to multiple registriesConfig Take effect only when no preferred registry is specified.
- Params map[string]string `yaml:"params" json:"params,omitempty" property:"params"`
- RegistryType string `yaml:"registry-type"`
- UseAsMetaReport bool `default:"true" yaml:"use-as-meta-report" json:"use-as-meta-report,omitempty" property:"use-as-meta-report"`
- UseAsConfigCenter bool `default:"true" yaml:"use-as-config-center" json:"use-as-config-center,omitempty" property:"use-as-config-center"`
-}
-
-// Prefix dubbo.registries
-func (RegistryConfig) Prefix() string {
- return constant.RegistryConfigPrefix
-}
-
-func (c *RegistryConfig) Init() error {
- if err := defaults.Set(c); err != nil {
- return err
- }
- return c.startRegistryConfig()
-}
-
-func (c *RegistryConfig) getUrlMap(roleType common.RoleType) url.Values {
- urlMap := url.Values{}
- urlMap.Set(constant.RegistryGroupKey, c.Group)
- urlMap.Set(constant.RegistryRoleKey, strconv.Itoa(int(roleType)))
- urlMap.Set(constant.RegistryKey, c.Protocol)
- urlMap.Set(constant.RegistryTimeoutKey, c.Timeout)
- // multi registry invoker weight label for load balance
- urlMap.Set(constant.RegistryKey+"."+constant.RegistryLabelKey, strconv.FormatBool(true))
- urlMap.Set(constant.RegistryKey+"."+constant.PreferredKey, strconv.FormatBool(c.Preferred))
- urlMap.Set(constant.RegistryKey+"."+constant.RegistryZoneKey, c.Zone)
- urlMap.Set(constant.RegistryKey+"."+constant.WeightKey, strconv.FormatInt(c.Weight, 10))
- urlMap.Set(constant.RegistryTTLKey, c.TTL)
- urlMap.Set(constant.ClientNameKey, clientNameID(c, c.Protocol, c.Address))
-
- for k, v := range c.Params {
- urlMap.Set(k, v)
- }
- return urlMap
-}
-
-func (c *RegistryConfig) startRegistryConfig() error {
- c.translateRegistryAddress()
- if c.UseAsMetaReport && isValid(c.Address) {
- if tmpUrl, err := c.toMetadataReportUrl(); err == nil {
- instance.SetMetadataReportInstanceByReg(tmpUrl)
- } else {
- return perrors.Wrap(err, "Start RegistryConfig failed.")
- }
- }
- return verify(c)
-}
-
-// toMetadataReportUrl translate the registry configuration to the metadata reporting url
-func (c *RegistryConfig) toMetadataReportUrl() (*common.URL, error) {
- res, err := common.NewURL(c.Address,
- common.WithLocation(c.Address),
- common.WithProtocol(c.Protocol),
- common.WithUsername(c.Username),
- common.WithPassword(c.Password),
- common.WithParamsValue(constant.TimeoutKey, c.Timeout),
- common.WithParamsValue(constant.ClientNameKey, clientNameID(c, c.Protocol, c.Address)),
- common.WithParamsValue(constant.MetadataReportGroupKey, c.Group),
- common.WithParamsValue(constant.MetadataReportNamespaceKey, c.Namespace),
- )
- if err != nil || len(res.Protocol) == 0 {
- return nil, perrors.New("Invalid Registry Config.")
- }
- return res, nil
-}
-
-// translateRegistryAddress translate registry address
-//
-// eg:address=nacos://127.0.0.1:8848 will return 127.0.0.1:8848 and protocol will set nacos
-func (c *RegistryConfig) translateRegistryAddress() string {
- if strings.Contains(c.Address, "://") {
- u, err := url.Parse(c.Address)
- if err != nil {
- logger.Errorf("The registry url is invalid, error: %#v", err)
- panic(err)
- }
- c.Protocol = u.Scheme
- c.Address = strings.Join([]string{u.Host, u.Path}, "")
- }
- return c.Address
-}
-
-func (c *RegistryConfig) GetInstance(roleType common.RoleType) (registry.Registry, error) {
- u, err := c.toURL(roleType)
- if err != nil {
- return nil, err
- }
- // if the protocol == registry, set protocol the registry value in url.params
- if u.Protocol == constant.RegistryProtocol {
- u.Protocol = u.GetParam(constant.RegistryKey, "")
- }
- return extension.GetRegistry(u.Protocol, u)
-}
-
-func (c *RegistryConfig) toURL(roleType common.RoleType) (*common.URL, error) {
- address := c.translateRegistryAddress()
- var registryURLProtocol string
- if c.RegistryType == constant.RegistryTypeService {
- // service discovery protocol
- registryURLProtocol = constant.ServiceRegistryProtocol
- } else if c.RegistryType == constant.RegistryTypeInterface {
- registryURLProtocol = constant.RegistryProtocol
- } else {
- registryURLProtocol = constant.ServiceRegistryProtocol
- }
- return common.NewURL(registryURLProtocol+"://"+address,
- common.WithParams(c.getUrlMap(roleType)),
- common.WithParamsValue(constant.RegistrySimplifiedKey, strconv.FormatBool(c.Simplified)),
- common.WithParamsValue(constant.RegistryKey, c.Protocol),
- common.WithParamsValue(constant.RegistryNamespaceKey, c.Namespace),
- common.WithParamsValue(constant.RegistryTimeoutKey, c.Timeout),
- common.WithUsername(c.Username),
- common.WithPassword(c.Password),
- common.WithLocation(c.Address),
- )
-}
-
-func (c *RegistryConfig) toURLs(roleType common.RoleType) ([]*common.URL, error) {
- address := c.translateRegistryAddress()
- var urls []*common.URL
- var err error
- var registryURL *common.URL
-
- if !isValid(c.Address) {
- logger.Infof("Empty or N/A registry address found, the process will work with no registry enabled " +
- "which means that the address of this instance will not be registered and not able to be found by other consumer instances.")
- return urls, nil
- }
-
- if c.RegistryType == constant.RegistryTypeService {
- // service discovery protocol
- if registryURL, err = c.createNewURL(constant.ServiceRegistryProtocol, address, roleType); err == nil {
- urls = append(urls, registryURL)
- }
- } else if c.RegistryType == constant.RegistryTypeInterface {
- if registryURL, err = c.createNewURL(constant.RegistryProtocol, address, roleType); err == nil {
- urls = append(urls, registryURL)
- }
- } else if c.RegistryType == constant.RegistryTypeAll {
- if registryURL, err = c.createNewURL(constant.ServiceRegistryProtocol, address, roleType); err == nil {
- urls = append(urls, registryURL)
- }
- if registryURL, err = c.createNewURL(constant.RegistryProtocol, address, roleType); err == nil {
- urls = append(urls, registryURL)
- }
- } else {
- if registryURL, err = c.createNewURL(constant.ServiceRegistryProtocol, address, roleType); err == nil {
- urls = append(urls, registryURL)
- }
- }
- return urls, err
-}
-
-func loadRegistries(registryIds []string, registries map[string]*RegistryConfig, roleType common.RoleType) []*common.URL {
- var registryURLs []*common.URL
- //trSlice := strings.Split(targetRegistries, ",")
-
- for k, registryConf := range registries {
- target := false
-
- // if user not config targetRegistries, default load all
- // Notice: in func "func Split(s, sep string) []string" comment:
- // if s does not contain sep and sep is not empty, SplitAfter returns
- // a slice of length 1 whose only element is s. So we have to add the
- // condition when targetRegistries string is not set (it will be "" when not set)
- if len(registryIds) == 0 || (len(registryIds) == 1 && registryIds[0] == "") {
- target = true
- } else {
- // else if user config targetRegistries
- for _, tr := range registryIds {
- if tr == k {
- target = true
- break
- }
- }
- }
-
- if target {
- if urls, err := registryConf.toURLs(roleType); err != nil {
- logger.Errorf("The registry id: %s url is invalid, error: %#v", k, err)
- panic(err)
- } else {
- registryURLs = append(registryURLs, urls...)
- }
- }
- }
-
- return registryURLs
-}
-
-func (c *RegistryConfig) createNewURL(protocol string, address string, roleType common.RoleType) (*common.URL, error) {
- return common.NewURL(protocol+"://"+address,
- common.WithParams(c.getUrlMap(roleType)),
- common.WithParamsValue(constant.RegistrySimplifiedKey, strconv.FormatBool(c.Simplified)),
- common.WithParamsValue(constant.RegistryKey, c.Protocol),
- common.WithParamsValue(constant.RegistryNamespaceKey, c.Namespace),
- common.WithParamsValue(constant.RegistryTimeoutKey, c.Timeout),
- common.WithUsername(c.Username),
- common.WithPassword(c.Password),
- common.WithLocation(c.Address),
- )
-}
-
const (
defaultZKAddr = "127.0.0.1:2181" // default registry address of zookeeper
defaultNacosAddr = "127.0.0.1:8848" // the default registry address of nacos
defaultRegistryTimeout = "3s" // the default registry timeout
)
-type RegistryConfigOpt func(config *RegistryConfig) *RegistryConfig
+type RegistryConfigOpt func(config *registry.RegistryConfig) *registry.RegistryConfig
// NewRegistryConfigWithProtocolDefaultPort New default registry config
// the input @protocol can only be:
// "zookeeper" with default addr "127.0.0.1:2181"
// "nacos" with default addr "127.0.0.1:8848"
-func NewRegistryConfigWithProtocolDefaultPort(protocol string) *RegistryConfig {
+func NewRegistryConfigWithProtocolDefaultPort(protocol string) *registry.RegistryConfig {
switch protocol {
case "zookeeper":
- return &RegistryConfig{
+ return ®istry.RegistryConfig{
Protocol: protocol,
Address: defaultZKAddr,
Timeout: defaultRegistryTimeout,
}
case "nacos":
- return &RegistryConfig{
+ return ®istry.RegistryConfig{
Protocol: protocol,
Address: defaultNacosAddr,
Timeout: defaultRegistryTimeout,
}
default:
- return &RegistryConfig{
+ return ®istry.RegistryConfig{
Protocol: protocol,
}
}
}
-// NewRegistryConfig creates New RegistryConfig with @opts
-func NewRegistryConfig(opts ...RegistryConfigOpt) *RegistryConfig {
+// NewRegistryConfig creates New registry.RegistryConfig with @opts
+func NewRegistryConfig(opts ...RegistryConfigOpt) *registry.RegistryConfig {
newRegistryConfig := NewRegistryConfigWithProtocolDefaultPort("")
for _, v := range opts {
newRegistryConfig = v(newRegistryConfig)
@@ -302,7 +65,7 @@ func NewRegistryConfig(opts ...RegistryConfigOpt) *RegistryConfig {
// WithRegistryProtocol returns RegistryConfigOpt with given @regProtocol name
func WithRegistryProtocol(regProtocol string) RegistryConfigOpt {
- return func(config *RegistryConfig) *RegistryConfig {
+ return func(config *registry.RegistryConfig) *registry.RegistryConfig {
config.Protocol = regProtocol
return config
}
@@ -310,7 +73,7 @@ func WithRegistryProtocol(regProtocol string) RegistryConfigOpt {
// WithRegistryAddress returns RegistryConfigOpt with given @addr registry address
func WithRegistryAddress(addr string) RegistryConfigOpt {
- return func(config *RegistryConfig) *RegistryConfig {
+ return func(config *registry.RegistryConfig) *registry.RegistryConfig {
config.Address = addr
return config
}
@@ -318,7 +81,7 @@ func WithRegistryAddress(addr string) RegistryConfigOpt {
// WithRegistryTimeOut returns RegistryConfigOpt with given @timeout registry config
func WithRegistryTimeOut(timeout string) RegistryConfigOpt {
- return func(config *RegistryConfig) *RegistryConfig {
+ return func(config *registry.RegistryConfig) *registry.RegistryConfig {
config.Timeout = timeout
return config
}
@@ -326,7 +89,7 @@ func WithRegistryTimeOut(timeout string) RegistryConfigOpt {
// WithRegistryGroup returns RegistryConfigOpt with given @group registry group
func WithRegistryGroup(group string) RegistryConfigOpt {
- return func(config *RegistryConfig) *RegistryConfig {
+ return func(config *registry.RegistryConfig) *registry.RegistryConfig {
config.Group = group
return config
}
@@ -334,7 +97,7 @@ func WithRegistryGroup(group string) RegistryConfigOpt {
// WithRegistryTTL returns RegistryConfigOpt with given @ttl registry ttl
func WithRegistryTTL(ttl string) RegistryConfigOpt {
- return func(config *RegistryConfig) *RegistryConfig {
+ return func(config *registry.RegistryConfig) *registry.RegistryConfig {
config.TTL = ttl
return config
}
@@ -342,7 +105,7 @@ func WithRegistryTTL(ttl string) RegistryConfigOpt {
// WithRegistryUserName returns RegistryConfigOpt with given @userName registry userName
func WithRegistryUserName(userName string) RegistryConfigOpt {
- return func(config *RegistryConfig) *RegistryConfig {
+ return func(config *registry.RegistryConfig) *registry.RegistryConfig {
config.Username = userName
return config
}
@@ -350,7 +113,7 @@ func WithRegistryUserName(userName string) RegistryConfigOpt {
// WithRegistryPassword returns RegistryConfigOpt with given @psw registry password
func WithRegistryPassword(psw string) RegistryConfigOpt {
- return func(config *RegistryConfig) *RegistryConfig {
+ return func(config *registry.RegistryConfig) *registry.RegistryConfig {
config.Password = psw
return config
}
@@ -358,15 +121,15 @@ func WithRegistryPassword(psw string) RegistryConfigOpt {
// WithRegistrySimplified returns RegistryConfigOpt with given @simplified registry simplified flag
func WithRegistrySimplified(simplified bool) RegistryConfigOpt {
- return func(config *RegistryConfig) *RegistryConfig {
+ return func(config *registry.RegistryConfig) *registry.RegistryConfig {
config.Simplified = simplified
return config
}
}
-// WithRegistryPreferred returns RegistryConfig with given @preferred registry preferred flag
+// WithRegistryPreferred returns registry.RegistryConfig with given @preferred registry preferred flag
func WithRegistryPreferred(preferred bool) RegistryConfigOpt {
- return func(config *RegistryConfig) *RegistryConfig {
+ return func(config *registry.RegistryConfig) *registry.RegistryConfig {
config.Preferred = preferred
return config
}
@@ -374,7 +137,7 @@ func WithRegistryPreferred(preferred bool) RegistryConfigOpt {
// WithRegistryWeight returns RegistryConfigOpt with given @weight registry weight flag
func WithRegistryWeight(weight int64) RegistryConfigOpt {
- return func(config *RegistryConfig) *RegistryConfig {
+ return func(config *registry.RegistryConfig) *registry.RegistryConfig {
config.Weight = weight
return config
}
@@ -382,7 +145,7 @@ func WithRegistryWeight(weight int64) RegistryConfigOpt {
// WithRegistryParams returns RegistryConfigOpt with given registry @params
func WithRegistryParams(params map[string]string) RegistryConfigOpt {
- return func(config *RegistryConfig) *RegistryConfig {
+ return func(config *registry.RegistryConfig) *registry.RegistryConfig {
config.Params = params
return config
}
@@ -390,12 +153,12 @@ func WithRegistryParams(params map[string]string) RegistryConfigOpt {
func NewRegistryConfigBuilder() *RegistryConfigBuilder {
return &RegistryConfigBuilder{
- registryConfig: &RegistryConfig{},
+ registryConfig: ®istry.RegistryConfig{},
}
}
type RegistryConfigBuilder struct {
- registryConfig *RegistryConfig
+ registryConfig *registry.RegistryConfig
}
func (rcb *RegistryConfigBuilder) SetProtocol(protocol string) *RegistryConfigBuilder {
@@ -476,18 +239,9 @@ func (rcb *RegistryConfigBuilder) SetRegistryType(registryType string) *Registry
return rcb
}
-func (rcb *RegistryConfigBuilder) Build() *RegistryConfig {
+func (rcb *RegistryConfigBuilder) Build() *registry.RegistryConfig {
if err := rcb.registryConfig.Init(); err != nil {
panic(err)
}
return rcb.registryConfig
}
-
-// DynamicUpdateProperties update registry
-func (c *RegistryConfig) DynamicUpdateProperties(updateRegistryConfig *RegistryConfig) {
- // if nacos's registry timeout not equal local root config's registry timeout , update.
- if updateRegistryConfig != nil && updateRegistryConfig.Timeout != c.Timeout {
- c.Timeout = updateRegistryConfig.Timeout
- logger.Infof("RegistryConfigs Timeout was dynamically updated, new value:%v", c.Timeout)
- }
-}
diff --git a/config/registry_config_test.go b/config/registry_config_test.go
index cf9ff61d0..e4caa8200 100644
--- a/config/registry_config_test.go
+++ b/config/registry_config_test.go
@@ -25,109 +25,45 @@ import (
"github.com/stretchr/testify/assert"
)
-import (
- "dubbo.apache.org/dubbo-go/v3/common"
- "dubbo.apache.org/dubbo-go/v3/common/constant"
-)
-
-func TestLoadRegistries(t *testing.T) {
- target := []string{"shanghai1"}
- regs := map[string]*RegistryConfig{
-
- "shanghai1": {
- Protocol: "mock",
- Timeout: "2s",
- Group: "shanghai_idc",
- Address: "127.0.0.2:2181,128.0.0.1:2181",
- Username: "user1",
- Password: "pwd1",
- },
- }
- urls := loadRegistries(target, regs, common.CONSUMER)
- t.Logf("loadRegistries() = urls:%v", urls)
- assert.Equal(t, "127.0.0.2:2181,128.0.0.1:2181", urls[0].Location)
-}
-
-func TestLoadRegistries1(t *testing.T) {
- target := []string{"shanghai1"}
- regs := map[string]*RegistryConfig{
-
- "shanghai1": {
- Protocol: "mock",
- Timeout: "2s",
- Group: "shanghai_idc",
- Address: "127.0.0.2:2181",
- Username: "user1",
- Password: "pwd1",
- },
- }
- urls := loadRegistries(target, regs, common.CONSUMER)
- t.Logf("loadRegistries() = urls:%v", urls)
- assert.Equal(t, "127.0.0.2:2181", urls[0].Location)
-}
-
-func TestRegistryTypeAll(t *testing.T) {
- target := []string{"test"}
- regs := map[string]*RegistryConfig{
- "test": {
- Protocol: "mock",
- Address: "127.0.0.2:2181",
- RegistryType: constant.RegistryTypeAll,
- },
- }
- urls := loadRegistries(target, regs, common.PROVIDER)
- assert.Equal(t, 2, len(urls))
-}
-
-func TestTranslateRegistryAddress(t *testing.T) {
- reg := new(RegistryConfig)
- reg.Address = "nacos://127.0.0.1:8848"
-
- reg.translateRegistryAddress()
-
- assert.Equal(t, "nacos", reg.Protocol)
- assert.Equal(t, "127.0.0.1:8848", reg.Address)
-}
-
-func TestNewRegistryConfigBuilder(t *testing.T) {
-
- config := NewRegistryConfigBuilder().
- SetProtocol("nacos").
- SetTimeout("10s").
- SetGroup("group").
- SetNamespace("public").
- SetTTL("10s").
- SetAddress("127.0.0.1:8848").
- SetUsername("nacos").
- SetPassword("123456").
- SetSimplified(true).
- SetPreferred(true).
- SetZone("zone").
- SetWeight(100).
- SetParams(map[string]string{"timeout": "3s"}).
- AddParam("timeout", "15s").
- SetRegistryType("local").
- Build()
-
- config.DynamicUpdateProperties(config)
-
- assert.Equal(t, config.Prefix(), constant.RegistryConfigPrefix)
-
- values := config.getUrlMap(common.PROVIDER)
- assert.Equal(t, values.Get("timeout"), "15s")
-
- url, err := config.toMetadataReportUrl()
- assert.NoError(t, err)
- assert.Equal(t, url.GetParam("timeout", "3s"), "10s")
-
- url, err = config.toURL(common.PROVIDER)
- assert.NoError(t, err)
- assert.Equal(t, url.GetParam("timeout", "3s"), "15s")
-
- address := config.translateRegistryAddress()
- assert.Equal(t, address, "127.0.0.1:8848")
-}
-
+// todo: think about how to expose functions of RegistryConfig
+//func TestNewRegistryConfigBuilder(t *testing.T) {
+//
+// config := NewRegistryConfigBuilder().
+// SetProtocol("nacos").
+// SetTimeout("10s").
+// SetGroup("group").
+// SetNamespace("public").
+// SetTTL("10s").
+// SetAddress("127.0.0.1:8848").
+// SetUsername("nacos").
+// SetPassword("123456").
+// SetSimplified(true).
+// SetPreferred(true).
+// SetZone("zone").
+// SetWeight(100).
+// SetParams(map[string]string{"timeout": "3s"}).
+// AddParam("timeout", "15s").
+// SetRegistryType("local").
+// Build()
+//
+// config.DynamicUpdateProperties(config)
+//
+// assert.Equal(t, config.Prefix(), constant.RegistryConfigPrefix)
+//
+// values := config.getUrlMap(common.PROVIDER)
+// assert.Equal(t, values.Get("timeout"), "15s")
+//
+// url, err := config.toMetadataReportUrl()
+// assert.NoError(t, err)
+// assert.Equal(t, url.GetParam("timeout", "3s"), "10s")
+//
+// url, err = config.toURL(common.PROVIDER)
+// assert.NoError(t, err)
+// assert.Equal(t, url.GetParam("timeout", "3s"), "15s")
+//
+// address := config.translateRegistryAddress()
+// assert.Equal(t, address, "127.0.0.1:8848")
+//}
func TestNewRegistryConfig(t *testing.T) {
config := NewRegistryConfig(
WithRegistryProtocol("nacos"),
diff --git a/config/root_config.go b/config/root_config.go
index 751770244..95a16366e 100644
--- a/config/root_config.go
+++ b/config/root_config.go
@@ -35,10 +35,12 @@ import (
import (
"dubbo.apache.org/dubbo-go/v3/common"
+ commonCfg "dubbo.apache.org/dubbo-go/v3/common/config"
"dubbo.apache.org/dubbo-go/v3/common/constant"
"dubbo.apache.org/dubbo-go/v3/common/extension"
"dubbo.apache.org/dubbo-go/v3/config_center"
"dubbo.apache.org/dubbo-go/v3/metadata/service/exporter"
+ "dubbo.apache.org/dubbo-go/v3/registry"
)
var (
@@ -48,23 +50,23 @@ var (
// RootConfig is the root config
type RootConfig struct {
- Application *ApplicationConfig `validate:"required" yaml:"application" json:"application,omitempty" property:"application"`
- Protocols map[string]*ProtocolConfig `validate:"required" yaml:"protocols" json:"protocols" property:"protocols"`
- Registries map[string]*RegistryConfig `yaml:"registries" json:"registries" property:"registries"`
- ConfigCenter *CenterConfig `yaml:"config-center" json:"config-center,omitempty"`
- MetadataReport *MetadataReportConfig `yaml:"metadata-report" json:"metadata-report,omitempty" property:"metadata-report"`
- Provider *ProviderConfig `yaml:"provider" json:"provider" property:"provider"`
- Consumer *ConsumerConfig `yaml:"consumer" json:"consumer" property:"consumer"`
- Metric *MetricConfig `yaml:"metrics" json:"metrics,omitempty" property:"metrics"`
- Tracing map[string]*TracingConfig `yaml:"tracing" json:"tracing,omitempty" property:"tracing"`
- Logger *LoggerConfig `yaml:"logger" json:"logger,omitempty" property:"logger"`
- Shutdown *ShutdownConfig `yaml:"shutdown" json:"shutdown,omitempty" property:"shutdown"`
- Router []*RouterConfig `yaml:"router" json:"router,omitempty" property:"router"`
- EventDispatcherType string `default:"direct" yaml:"event-dispatcher-type" json:"event-dispatcher-type,omitempty"`
- CacheFile string `yaml:"cache_file" json:"cache_file,omitempty" property:"cache_file"`
- Custom *CustomConfig `yaml:"custom" json:"custom,omitempty" property:"custom"`
- Profiles *ProfilesConfig `yaml:"profiles" json:"profiles,omitempty" property:"profiles"`
- TLSConfig *TLSConfig `yaml:"tls_config" json:"tls_config,omitempty" property:"tls_config"`
+ Application *commonCfg.ApplicationConfig `validate:"required" yaml:"application" json:"application,omitempty" property:"application"`
+ Protocols map[string]*ProtocolConfig `validate:"required" yaml:"protocols" json:"protocols" property:"protocols"`
+ Registries map[string]*registry.RegistryConfig `yaml:"registries" json:"registries" property:"registries"`
+ ConfigCenter *CenterConfig `yaml:"config-center" json:"config-center,omitempty"`
+ MetadataReport *MetadataReportConfig `yaml:"metadata-report" json:"metadata-report,omitempty" property:"metadata-report"`
+ Provider *ProviderConfig `yaml:"provider" json:"provider" property:"provider"`
+ Consumer *ConsumerConfig `yaml:"consumer" json:"consumer" property:"consumer"`
+ Metric *MetricConfig `yaml:"metrics" json:"metrics,omitempty" property:"metrics"`
+ Tracing map[string]*TracingConfig `yaml:"tracing" json:"tracing,omitempty" property:"tracing"`
+ Logger *LoggerConfig `yaml:"logger" json:"logger,omitempty" property:"logger"`
+ Shutdown *ShutdownConfig `yaml:"shutdown" json:"shutdown,omitempty" property:"shutdown"`
+ Router []*RouterConfig `yaml:"router" json:"router,omitempty" property:"router"`
+ EventDispatcherType string `default:"direct" yaml:"event-dispatcher-type" json:"event-dispatcher-type,omitempty"`
+ CacheFile string `yaml:"cache_file" json:"cache_file,omitempty" property:"cache_file"`
+ Custom *CustomConfig `yaml:"custom" json:"custom,omitempty" property:"custom"`
+ Profiles *ProfilesConfig `yaml:"profiles" json:"profiles,omitempty" property:"profiles"`
+ TLSConfig *TLSConfig `yaml:"tls_config" json:"tls_config,omitempty" property:"tls_config"`
}
func SetRootConfig(r RootConfig) {
@@ -94,7 +96,7 @@ func GetConsumerConfig() *ConsumerConfig {
return NewConsumerConfigBuilder().Build()
}
-func GetApplicationConfig() *ApplicationConfig {
+func GetApplicationConfig() *commonCfg.ApplicationConfig {
return rootConfig.Application
}
@@ -222,7 +224,7 @@ func newEmptyRootConfig() *RootConfig {
ConfigCenter: NewConfigCenterConfigBuilder().Build(),
MetadataReport: NewMetadataReportConfigBuilder().Build(),
Application: NewApplicationConfigBuilder().Build(),
- Registries: make(map[string]*RegistryConfig),
+ Registries: make(map[string]*registry.RegistryConfig),
Protocols: make(map[string]*ProtocolConfig),
Tracing: make(map[string]*TracingConfig),
Provider: NewProviderConfigBuilder().Build(),
@@ -244,7 +246,7 @@ type RootConfigBuilder struct {
rootConfig *RootConfig
}
-func (rb *RootConfigBuilder) SetApplication(application *ApplicationConfig) *RootConfigBuilder {
+func (rb *RootConfigBuilder) SetApplication(application *commonCfg.ApplicationConfig) *RootConfigBuilder {
rb.rootConfig.Application = application
return rb
}
@@ -254,7 +256,7 @@ func (rb *RootConfigBuilder) AddProtocol(protocolID string, protocolConfig *Prot
return rb
}
-func (rb *RootConfigBuilder) AddRegistry(registryID string, registryConfig *RegistryConfig) *RootConfigBuilder {
+func (rb *RootConfigBuilder) AddRegistry(registryID string, registryConfig *registry.RegistryConfig) *RootConfigBuilder {
rb.rootConfig.Registries[registryID] = registryConfig
return rb
}
@@ -264,7 +266,7 @@ func (rb *RootConfigBuilder) SetProtocols(protocols map[string]*ProtocolConfig)
return rb
}
-func (rb *RootConfigBuilder) SetRegistries(registries map[string]*RegistryConfig) *RootConfigBuilder {
+func (rb *RootConfigBuilder) SetRegistries(registries map[string]*registry.RegistryConfig) *RootConfigBuilder {
rb.rootConfig.Registries = registries
return rb
}
diff --git a/config/root_config_test.go b/config/root_config_test.go
index e49e1456e..42e27f7df 100644
--- a/config/root_config_test.go
+++ b/config/root_config_test.go
@@ -30,11 +30,12 @@ import (
import (
"dubbo.apache.org/dubbo-go/v3/common/constant"
"dubbo.apache.org/dubbo-go/v3/config_center"
+ "dubbo.apache.org/dubbo-go/v3/registry"
)
func TestGoConfigProcess(t *testing.T) {
rc := &RootConfigBuilder{rootConfig: newEmptyRootConfig()}
- r := &RegistryConfig{Protocol: "zookeeper", Timeout: "10s", Address: "127.0.0.1:2181"}
+ r := ®istry.RegistryConfig{Protocol: "zookeeper", Timeout: "10s", Address: "127.0.0.1:2181"}
rc.AddRegistry("demoZK", r)
// test koan.UnmarshalWithConf error
@@ -64,7 +65,7 @@ func TestNewRootConfigBuilder(t *testing.T) {
AddProtocol("dubbo", protocolConfig).
AddRegistry("nacos", registryConfig).
SetProtocols(map[string]*ProtocolConfig{"dubbo": protocolConfig}).
- SetRegistries(map[string]*RegistryConfig{"nacos": registryConfig}).
+ SetRegistries(map[string]*registry.RegistryConfig{"nacos": registryConfig}).
SetProvider(NewProviderConfigBuilder().Build()).
SetConsumer(NewConsumerConfigBuilder().Build()).
SetMetric(NewMetricConfigBuilder().Build()).
diff --git a/config/service.go b/config/service.go
index 238d5549a..0621bc245 100644
--- a/config/service.go
+++ b/config/service.go
@@ -26,16 +26,19 @@ import (
)
import (
+ "dubbo.apache.org/dubbo-go/v3/client"
"dubbo.apache.org/dubbo-go/v3/common"
)
var (
- conServicesLock = sync.Mutex{} // used to guard conServices map.
- conServices = map[string]common.RPCService{} // service name -> service
- proServicesLock = sync.Mutex{} // used to guard proServices map
- proServices = map[string]common.RPCService{} // service name -> service
- interfaceNameConServicesLock = sync.Mutex{} // used to guard interfaceNameConServices map
- interfaceNameConServices = map[string]common.RPCService{} // interfaceName -> service
+ conServicesLock = sync.Mutex{} // used to guard conServices map.
+ conServices = map[string]common.RPCService{} // service name -> service
+ proServicesLock = sync.Mutex{} // used to guard proServices map
+ proServices = map[string]common.RPCService{} // service name -> service
+ interfaceNameConServicesLock = sync.Mutex{} // used to guard interfaceNameConServices map
+ interfaceNameConServices = map[string]common.RPCService{} // interfaceName -> service
+ clientInfoServicesLock = sync.Mutex{} // used to guard clientInfoServices map
+ clientInfoServices = map[*client.ClientInfo]common.RPCService{} // ClientInfo -> service
)
// SetConsumerService is called by init() of implement of RPCService
@@ -106,3 +109,18 @@ func GetCallback(name string) func(response common.CallbackResponse) {
}
return nil
}
+
+// SetClientInfoService set new info and service into clientInfosServices if new info and service are not nil
+func SetClientInfoService(info *client.ClientInfo, srv common.RPCService) {
+ if info == nil || info.ClientInjectFunc == nil || srv == nil {
+ return
+ }
+ clientInfoServicesLock.Lock()
+ defer clientInfoServicesLock.Unlock()
+ clientInfoServices[info] = srv
+}
+
+// GetClientInfoServicesMap returns clientInfoServices
+func GetClientInfoServicesMap() map[*client.ClientInfo]common.RPCService {
+ return clientInfoServices
+}
diff --git a/go.mod b/go.mod
index d66112570..0f39911fe 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module dubbo.apache.org/dubbo-go/v3
-go 1.15
+go 1.20
require (
github.com/RoaringBitmap/roaring v1.2.3
@@ -28,7 +28,6 @@ require (
github.com/golang/protobuf v1.5.2
github.com/google/go-cmp v0.5.9
github.com/google/uuid v1.3.0
- github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 // indirect
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645
github.com/hashicorp/vault/sdk v0.7.0
github.com/influxdata/tdigest v0.0.1
@@ -57,8 +56,8 @@ require (
go.opentelemetry.io/otel v1.11.0
go.opentelemetry.io/otel/trace v1.11.0
go.uber.org/atomic v1.10.0
- go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0
+ golang.org/x/net v0.8.0
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6
google.golang.org/grpc v1.52.0
google.golang.org/protobuf v1.30.0
@@ -66,3 +65,67 @@ require (
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v2 v2.4.0
)
+
+require (
+ cloud.google.com/go/compute v1.12.1 // indirect
+ cloud.google.com/go/compute/metadata v0.2.1 // indirect
+ github.com/aliyun/alibaba-cloud-sdk-go v1.61.1704 // indirect
+ github.com/beorn7/perks v1.0.1 // indirect
+ github.com/bits-and-blooms/bitset v1.2.0 // indirect
+ github.com/buger/jsonparser v1.1.1 // indirect
+ github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
+ github.com/coreos/go-semver v0.3.0 // indirect
+ github.com/coreos/go-systemd/v22 v22.3.2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/dlclark/regexp2 v1.7.0 // indirect
+ github.com/envoyproxy/protoc-gen-validate v0.9.1 // indirect
+ github.com/go-logr/logr v1.2.3 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
+ github.com/go-ole/go-ole v1.2.6 // indirect
+ github.com/go-playground/locales v0.14.1 // indirect
+ github.com/go-playground/universal-translator v0.18.1 // indirect
+ github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/golang/snappy v0.0.4 // indirect
+ github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 // indirect
+ github.com/gorilla/websocket v1.4.2 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/jmespath/go-jmespath v0.4.0 // indirect
+ github.com/json-iterator/go v1.1.12 // indirect
+ github.com/k0kubun/pp v3.0.1+incompatible // indirect
+ github.com/leodido/go-urn v1.2.2 // indirect
+ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
+ github.com/mattn/go-isatty v0.0.16 // indirect
+ github.com/mitchellh/copystructure v1.2.0 // indirect
+ github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/reflectwalk v1.0.2 // indirect
+ github.com/modern-go/reflect2 v1.0.2 // indirect
+ github.com/mschoch/smat v0.2.0 // indirect
+ github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
+ github.com/pierrec/lz4 v2.5.2+incompatible // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
+ github.com/prometheus/client_model v0.3.0 // indirect
+ github.com/prometheus/procfs v0.8.0 // indirect
+ github.com/robfig/cron/v3 v3.0.1 // indirect
+ github.com/shirou/gopsutil/v3 v3.22.2 // indirect
+ github.com/spaolacci/murmur3 v1.1.0 // indirect
+ github.com/stretchr/objx v0.5.0 // indirect
+ github.com/tklauser/go-sysconf v0.3.10 // indirect
+ github.com/tklauser/numcpus v0.4.0 // indirect
+ github.com/uber/jaeger-client-go v2.29.1+incompatible // indirect
+ github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
+ github.com/ugorji/go/codec v1.2.6 // indirect
+ github.com/yusufpapurcu/wmi v1.2.2 // indirect
+ go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect
+ go.uber.org/multierr v1.8.0 // indirect
+ golang.org/x/crypto v0.7.0 // indirect
+ golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
+ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
+ golang.org/x/sys v0.6.0 // indirect
+ golang.org/x/text v0.8.0 // indirect
+ golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
+ google.golang.org/appengine v1.6.7 // indirect
+ gopkg.in/ini.v1 v1.66.2 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/go.sum b/go.sum
index 5390019e4..ba0be7af7 100644
--- a/go.sum
+++ b/go.sum
@@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
-cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
@@ -14,363 +13,32 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
-cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
-cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
-cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
-cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
-cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
-cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
-cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
-cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
-cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
-cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
-cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
-cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
-cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
-cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
-cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
-cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
-cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU=
-cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA=
-cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=
-cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
-cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4=
-cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw=
-cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o=
-cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE=
-cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw=
-cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY=
-cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI=
-cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4=
-cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk=
-cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc=
-cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc=
-cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04=
-cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno=
-cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak=
-cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4=
-cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0=
-cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ=
-cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk=
-cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0=
-cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc=
-cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o=
-cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s=
-cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0=
-cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ=
-cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY=
-cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY=
-cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw=
-cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI=
-cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo=
-cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0=
-cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0=
-cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8=
-cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8=
-cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM=
-cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc=
-cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI=
-cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE=
-cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE=
-cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4=
-cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA=
-cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw=
-cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY=
-cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s=
-cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI=
-cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y=
-cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM=
-cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI=
-cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0=
-cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk=
-cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg=
-cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590=
-cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk=
-cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk=
-cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U=
-cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA=
-cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM=
-cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk=
-cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY=
-cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI=
-cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4=
-cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI=
-cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
-cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
-cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
-cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
-cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
-cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
-cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU=
-cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0=
cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
-cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU=
cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48=
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
-cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY=
-cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck=
-cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg=
-cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo=
-cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I=
-cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4=
-cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0=
-cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs=
-cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc=
-cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE=
-cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM=
-cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM=
-cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ=
-cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo=
-cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE=
-cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0=
-cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38=
-cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w=
-cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I=
-cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ=
-cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA=
-cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A=
-cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s=
-cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI=
-cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo=
-cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
-cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo=
-cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ=
-cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g=
-cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4=
-cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c=
-cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s=
-cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4=
-cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0=
-cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8=
-cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek=
-cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0=
-cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM=
-cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q=
-cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU=
-cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU=
-cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k=
-cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4=
-cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y=
-cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg=
-cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk=
-cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w=
-cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI=
-cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8=
-cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc=
-cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw=
-cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w=
-cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
-cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk=
-cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg=
-cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY=
-cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08=
-cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM=
-cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA=
-cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w=
-cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM=
-cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60=
-cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo=
-cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o=
-cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A=
-cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0=
-cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0=
-cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA=
-cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI=
-cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc=
-cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM=
-cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o=
-cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
-cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc=
-cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc=
-cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg=
-cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc=
-cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A=
-cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM=
-cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY=
-cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs=
-cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g=
-cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg=
-cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0=
-cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic=
-cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI=
-cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE=
-cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8=
-cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8=
-cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08=
-cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE=
-cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc=
-cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE=
-cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM=
-cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4=
-cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w=
-cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE=
-cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM=
-cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA=
-cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY=
-cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY=
-cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s=
-cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8=
-cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI=
-cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk=
-cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4=
-cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA=
-cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o=
-cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM=
-cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8=
-cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8=
-cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4=
-cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ=
-cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU=
-cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY=
-cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34=
-cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA=
-cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0=
-cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4=
-cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs=
-cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA=
-cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk=
-cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE=
-cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc=
-cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs=
-cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg=
-cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo=
-cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw=
-cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E=
-cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU=
-cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70=
-cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo=
-cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0=
-cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA=
-cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg=
-cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE=
-cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0=
-cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
-cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4=
-cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o=
-cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk=
-cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo=
-cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE=
-cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U=
-cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg=
-cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4=
-cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg=
-cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c=
-cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs=
-cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70=
-cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y=
-cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A=
-cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA=
-cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM=
-cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA=
-cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0=
-cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU=
-cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg=
-cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4=
-cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY=
-cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc=
-cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y=
-cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do=
-cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo=
-cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s=
-cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI=
-cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk=
-cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44=
-cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA=
-cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4=
-cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4=
-cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4=
-cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0=
-cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU=
-cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q=
-cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA=
-cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU=
-cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc=
-cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk=
-cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk=
-cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU=
-cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s=
-cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs=
-cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg=
-cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4=
-cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U=
-cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco=
-cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo=
-cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E=
-cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU=
-cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4=
-cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw=
-cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM=
-cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ=
-cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0=
-cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
-cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
-cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
-cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc=
-cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
-cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w=
-cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I=
-cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw=
-cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g=
-cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM=
-cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA=
-cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8=
-cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4=
-cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ=
-cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg=
-cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28=
-cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y=
-cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs=
-cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg=
-cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk=
-cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw=
-cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU=
-cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4=
-cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M=
-cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU=
-cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0=
-cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo=
-cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo=
-cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY=
-cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E=
-cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE=
-cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g=
-cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w=
-cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8=
-cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE=
-cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg=
-cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc=
-cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A=
-cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo=
-cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ=
-cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0=
-cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M=
-cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M=
-cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
-github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM=
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
@@ -409,7 +77,6 @@ github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
-github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
@@ -444,9 +111,7 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
-github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40 h1:xvUo53O5MRZhVMJAxWCJcS5HHrqAiAG9SJ1LpMu6aAI=
github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
-github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -455,28 +120,21 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
-github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
-github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc h1:PYXxkRUBGUMa5xgMVMDl62vEklZvKpVaxQeN9ie7Hfk=
github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
-github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E=
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
-github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcKDqs=
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
-github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY=
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
@@ -485,7 +143,6 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
@@ -537,11 +194,9 @@ github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4s
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
-github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
-github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.0/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
@@ -550,7 +205,6 @@ github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCw
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.9.1 h1:PS7VIOgmSVhWUEeZwTe7z7zouA22Cr590PzXKbZHOVY=
github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w=
-github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
@@ -562,15 +216,12 @@ github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/frankban/quicktest v1.10.0 h1:Gfh+GAJZOAoKZsIZeZbdn2JF10kN1XHNvjsvQK8gVkE=
-github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
-github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-co-op/gocron v1.9.0 h1:+V+DDenw3ryB7B+tK1bAIC5p0ruw4oX9IqAsdRnGIf0=
github.com/go-co-op/gocron v1.9.0/go.mod h1:DbJm9kdgr1sEvWpHCA7dFFs/PGHPMil9/97EXCRPr4k=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
@@ -583,7 +234,6 @@ github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgO
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
-github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
@@ -597,7 +247,6 @@ github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNI
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
-github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
@@ -609,7 +258,6 @@ github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSM
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
@@ -635,7 +283,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
-github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -653,12 +300,10 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc=
@@ -678,20 +323,15 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
-github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@@ -699,34 +339,14 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
-github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
-github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
-github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
-github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
-github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
-github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
-github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
-github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo=
-github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
-github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
-github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw=
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -747,8 +367,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w=
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU=
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
@@ -765,43 +383,27 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
-github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
-github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
-github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
-github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.0/go.mod h1:xvb32K2keAc+R8DSFG2IwDcydK9DBQE+fGA5fsw6hSk=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
-github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
-github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
-github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw=
-github.com/hashicorp/go-secure-stdlib/mlock v0.1.1/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I=
-github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8=
-github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8=
-github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo=
-github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U=
-github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4=
-github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.2/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
@@ -821,16 +423,12 @@ github.com/hjson/hjson-go/v4 v4.0.0 h1:wlm6IYYqHjOdXH1gHev4VoXCaW20HdQAGCxdOEEg2
github.com/hjson/hjson-go/v4 v4.0.0/go.mod h1:KaYt3bTw3zhBjYqnXkYywcYctk0A2nxeEFTse3rH13E=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
-github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/influxdata/tdigest v0.0.1 h1:XpFptwYmnEKUqmkcDjrzffswZ3nvNeevbUSLPP/ZzIY=
github.com/influxdata/tdigest v0.0.1/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y=
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag=
-github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
-github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -873,7 +471,6 @@ github.com/knadh/koanf v1.5.0/go.mod h1:Hgyjp4y8v44hpZtPzs7JZfRAW5AhN7KfZcwv1RYg
github.com/koding/multiconfig v0.0.0-20171124222453-69c27309b2d7/go.mod h1:Y2SaZf2Rzd0pXkLVhLlCiAXFCLSXAIbTKDivVgff/AM=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@@ -893,7 +490,6 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
-github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -934,7 +530,6 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
@@ -952,7 +547,6 @@ github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/nacos-group/nacos-sdk-go v1.0.8 h1:8pEm05Cdav9sQgJSv5kyvlgfz0SzFUUGI3pWX6SiSnM=
github.com/nacos-group/nacos-sdk-go v1.0.8/go.mod h1:hlAPn3UdzlxIlSILAyOXKxjFSvDJ9oLzTJ9hLAK1KzA=
github.com/nacos-group/nacos-sdk-go/v2 v2.1.2/go.mod h1:ys/1adWeKXXzbNWfRNbaFlX/t6HVLWdpsNDvmoWTw0g=
github.com/nacos-group/nacos-sdk-go/v2 v2.2.2 h1:FI+7vr1fvCA4jbgx36KezmP3zlU/WoP/7wAloaSd1Ew=
@@ -1007,8 +601,6 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
-github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
-github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/polarismesh/polaris-go v1.3.0 h1:KZKX//ow4OPPoS5+s7h07ptprg+2AcNVGrN6WakC9QM=
@@ -1022,7 +614,6 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
-github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU=
@@ -1081,7 +672,6 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
-github.com/shirou/gopsutil v3.20.11+incompatible h1:LJr4ZQK4mPpIV5gOa4jCOKOGb4ty4DZO54I4FGqIpto=
github.com/shirou/gopsutil v3.20.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil/v3 v3.21.6/go.mod h1:JfVbDpIBLVzT8oKbvMg9P3wEIMDDpVn+LwHTKj0ST88=
github.com/shirou/gopsutil/v3 v3.22.2 h1:wCrArWFkHYIdDxx/FSfF5RB4dpJYW6t7rcp3+zL8uks=
@@ -1105,8 +695,6 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
-github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
-github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
@@ -1132,7 +720,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
@@ -1151,12 +738,10 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3/go.mod h1:QDlpd3qS71vYtakd2hmdpqhJ9nwv6mD6A30bQ1BPBFE=
-github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/uber/jaeger-client-go v2.29.1+incompatible h1:R9ec3zO3sGpzs0abd43Y+fBZRJ9uiH6lXyR/+u6brW4=
github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
-github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
@@ -1169,7 +754,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@@ -1207,14 +791,11 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
-go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/otel v1.11.0 h1:kfToEGMDq6TrVrJ9Vht84Y8y9enykSZzDDZglV0kIEk=
go.opentelemetry.io/otel v1.11.0/go.mod h1:H2KtuEphyMvlhZ+F7tg9GRhAOe60moNx61Ex+WmiKkk=
go.opentelemetry.io/otel/trace v1.11.0 h1:20U/Vj42SX+mASlXLmSGBg6jpI1jQtv682lZtTAOVFI=
go.opentelemetry.io/otel/trace v1.11.0/go.mod h1:nyYjis9jy0gytE9LXGU+/m1sHTKbRY0fX0hulNNDP1U=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
-go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
@@ -1245,15 +826,10 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1284,8 +860,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@@ -1295,14 +869,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1341,35 +908,16 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
-golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211105192438-b53810dc28af/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
-golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
-golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
-golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
-golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1377,25 +925,9 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
-golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
-golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
-golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
-golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk=
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1409,11 +941,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1464,85 +993,45 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211106132015-ebca88c72f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
-golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
-golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
-golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1605,38 +1094,20 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201014170642-d1624618ad65/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
-golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
-golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
-golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
-golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.8.2 h1:CCXrcPKiGGotvnN6jfUsKk4rRqm7q09/YbKb5xCEvtM=
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
-gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
@@ -1656,40 +1127,6 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
-google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
-google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
-google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
-google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
-google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
-google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
-google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
-google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
-google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
-google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
-google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
-google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
-google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
-google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
-google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
-google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
-google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
-google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
-google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
-google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
-google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
-google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
-google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
-google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
-google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g=
-google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
-google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
-google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI=
-google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
-google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
-google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
-google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08=
-google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70=
-google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -1699,7 +1136,6 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -1734,87 +1170,12 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210106152847-07624b53cd92/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
-google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
-google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
-google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
-google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
-google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
-google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
-google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
-google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211104193956-4c6863e31247/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
-google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220504150022-98cd25cafc72/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
-google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
-google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
-google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
-google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
-google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE=
-google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
-google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
-google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
-google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
-google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
-google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
-google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
-google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
-google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
-google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
-google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
-google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw=
-google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI=
-google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI=
-google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U=
-google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
-google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
-google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
-google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
-google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo=
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c=
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
-google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -1834,35 +1195,16 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
-google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
-google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
-google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
-google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
-google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
-google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
-google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
-google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk=
google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
-google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -1877,7 +1219,6 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
diff --git a/imports/imports.go b/imports/imports.go
index 71dd06b24..2e0cef916 100644
--- a/imports/imports.go
+++ b/imports/imports.go
@@ -73,6 +73,7 @@ import (
_ "dubbo.apache.org/dubbo-go/v3/protocol/grpc"
_ "dubbo.apache.org/dubbo-go/v3/protocol/jsonrpc"
_ "dubbo.apache.org/dubbo-go/v3/protocol/rest"
+ _ "dubbo.apache.org/dubbo-go/v3/protocol/triple"
_ "dubbo.apache.org/dubbo-go/v3/proxy/proxy_factory"
_ "dubbo.apache.org/dubbo-go/v3/registry/etcdv3"
_ "dubbo.apache.org/dubbo-go/v3/registry/nacos"
diff --git a/metrics/bus_test.go b/metrics/bus_test.go
index 185f50896..4e4a68eec 100644
--- a/metrics/bus_test.go
+++ b/metrics/bus_test.go
@@ -18,10 +18,13 @@
package metrics
import (
- "github.com/stretchr/testify/assert"
"testing"
)
+import (
+ "github.com/stretchr/testify/assert"
+)
+
var mockChan = make(chan MetricsEvent, 16)
type MockEvent struct {
diff --git a/metrics/prometheus/reporter.go b/metrics/prometheus/reporter.go
index 715fd97ca..0e9fedc82 100644
--- a/metrics/prometheus/reporter.go
+++ b/metrics/prometheus/reporter.go
@@ -26,6 +26,7 @@ import (
import (
"github.com/dubbogo/gost/log/logger"
+
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
diff --git a/metrics/prometheus/util.go b/metrics/prometheus/util.go
index 4e1a9c8dc..29e5ebf3c 100644
--- a/metrics/prometheus/util.go
+++ b/metrics/prometheus/util.go
@@ -24,6 +24,7 @@ import (
import (
"github.com/dubbogo/gost/log/logger"
+
"github.com/prometheus/client_golang/prometheus"
)
diff --git a/metrics/util/aggregate/quantile_test.go b/metrics/util/aggregate/quantile_test.go
index 5e8243166..d90d09652 100644
--- a/metrics/util/aggregate/quantile_test.go
+++ b/metrics/util/aggregate/quantile_test.go
@@ -17,7 +17,9 @@
package aggregate
-import "testing"
+import (
+ "testing"
+)
func TestAddAndQuantile(t1 *testing.T) {
timeWindowQuantile := NewTimeWindowQuantile(100, 10, 1)
diff --git a/protocol/invocation.go b/protocol/invocation.go
index a97cf72a2..cb98df648 100644
--- a/protocol/invocation.go
+++ b/protocol/invocation.go
@@ -34,6 +34,8 @@ type Invocation interface {
ParameterTypes() []reflect.Type
// ParameterValues gets invocation parameter values.
ParameterValues() []reflect.Value
+ // ParameterRawValues gets raw invocation parameter values.
+ ParameterRawValues() []interface{}
// Arguments gets arguments.
Arguments() []interface{}
// Reply gets response of request
diff --git a/protocol/invocation/rpcinvocation.go b/protocol/invocation/rpcinvocation.go
index 5c821e676..10e1fa582 100644
--- a/protocol/invocation/rpcinvocation.go
+++ b/protocol/invocation/rpcinvocation.go
@@ -44,11 +44,12 @@ type RPCInvocation struct {
parameterTypeNames []string
parameterTypes []reflect.Type
- parameterValues []reflect.Value
- arguments []interface{}
- reply interface{}
- callBack interface{}
- attachments map[string]interface{}
+ parameterValues []reflect.Value
+ parameterRawValues []interface{}
+ arguments []interface{}
+ reply interface{}
+ callBack interface{}
+ attachments map[string]interface{}
// Refer to dubbo 2.7.6. It is different from attachment. It is used in internal process.
attributes map[string]interface{}
invoker protocol.Invoker
@@ -114,6 +115,10 @@ func (r *RPCInvocation) ParameterValues() []reflect.Value {
return r.parameterValues
}
+func (r *RPCInvocation) ParameterRawValues() []interface{} {
+ return r.parameterRawValues
+}
+
// Arguments gets RPC arguments.
func (r *RPCInvocation) Arguments() []interface{} {
return r.arguments
@@ -295,6 +300,13 @@ func WithParameterValues(parameterValues []reflect.Value) option {
}
}
+// WithParameterRawValues creates option with @parameterRawValues
+func WithParameterRawValues(parameterRawValues []interface{}) option {
+ return func(invo *RPCInvocation) {
+ invo.parameterRawValues = parameterRawValues
+ }
+}
+
// WithArguments creates option with @arguments function.
func WithArguments(arguments []interface{}) option {
return func(invo *RPCInvocation) {
diff --git a/protocol/triple/client.go b/protocol/triple/client.go
new file mode 100644
index 000000000..6cfe3482b
--- /dev/null
+++ b/protocol/triple/client.go
@@ -0,0 +1,230 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package triple
+
+import (
+ "context"
+ "crypto/tls"
+ "errors"
+ "net"
+ "net/http"
+ "path"
+ "strings"
+)
+
+import (
+ "github.com/dubbogo/gost/log/logger"
+
+ "github.com/dustin/go-humanize"
+
+ "golang.org/x/net/http2"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/common"
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+ "dubbo.apache.org/dubbo-go/v3/config"
+ tri "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+)
+
+const (
+ httpPrefix string = "http://"
+ httpsPrefix string = "https://"
+)
+
+// clientManager wraps triple clients and is responsible for find concrete triple client to invoke
+// callUnary, callClientStream, callServerStream, callBidiStream.
+// An Interface has a clientManager.
+type clientManager struct {
+ // triple_protocol clients, key is method name
+ triClients map[string]*tri.Client
+}
+
+func (cm *clientManager) getClient(method string) (*tri.Client, error) {
+ triClient, ok := cm.triClients[method]
+ if !ok {
+ return nil, errors.New("missing triple client")
+ }
+ return triClient, nil
+}
+
+func (cm *clientManager) callUnary(ctx context.Context, method string, req, resp interface{}) error {
+ triClient, err := cm.getClient(method)
+ if err != nil {
+ return err
+ }
+ // todo: compiler generate tri.Request and tri.Response
+ triReq := req.(*tri.Request)
+ triResp := resp.(*tri.Response)
+ if err := triClient.CallUnary(ctx, triReq, triResp); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cm *clientManager) callClientStream(ctx context.Context, method string) (interface{}, error) {
+ triClient, err := cm.getClient(method)
+ if err != nil {
+ return nil, err
+ }
+ stream, err := triClient.CallClientStream(ctx)
+ if err != nil {
+ return nil, err
+ }
+ return stream, nil
+}
+
+func (cm *clientManager) callServerStream(ctx context.Context, method string, req interface{}) (interface{}, error) {
+ triClient, err := cm.getClient(method)
+ if err != nil {
+ return nil, err
+ }
+ triReq := req.(*tri.Request)
+ stream, err := triClient.CallServerStream(ctx, triReq)
+ if err != nil {
+ return nil, err
+ }
+ return stream, nil
+}
+
+func (cm *clientManager) callBidiStream(ctx context.Context, method string) (interface{}, error) {
+ triClient, err := cm.getClient(method)
+ if err != nil {
+ return nil, err
+ }
+ stream, err := triClient.CallBidiStream(ctx)
+ if err != nil {
+ return nil, err
+ }
+ return stream, nil
+}
+
+func (cm *clientManager) close() {
+ // todo: close connection and release resources
+}
+
+// NewClient creates a new GRPC_NEW client.
+func newClientManager(url *common.URL) (*clientManager, error) {
+ // If global trace instance was set, it means trace function enabled.
+ // If not, will return NoopTracer.
+ // tracer := opentracing.GlobalTracer()
+ var triClientOpts []tri.ClientOption
+
+ // set max send and recv msg size
+ maxCallRecvMsgSize := constant.DefaultMaxCallRecvMsgSize
+ if recvMsgSize, err := humanize.ParseBytes(url.GetParam(constant.MaxCallRecvMsgSize, "")); err == nil && recvMsgSize > 0 {
+ maxCallRecvMsgSize = int(recvMsgSize)
+ }
+ triClientOpts = append(triClientOpts, tri.WithReadMaxBytes(maxCallRecvMsgSize))
+ maxCallSendMsgSize := constant.DefaultMaxCallSendMsgSize
+ if sendMsgSize, err := humanize.ParseBytes(url.GetParam(constant.MaxCallSendMsgSize, "")); err == nil && sendMsgSize > 0 {
+ maxCallSendMsgSize = int(sendMsgSize)
+ }
+ triClientOpts = append(triClientOpts, tri.WithSendMaxBytes(maxCallSendMsgSize))
+
+ // todo:// process timeout
+ // consumer config client connectTimeout
+ //connectTimeout := config.GetConsumerConfig().ConnectTimeout
+
+ // dialOpts = append(dialOpts,
+ //
+ // grpc.WithBlock(),
+ // // todo config network timeout
+ // grpc.WithTimeout(time.Second*3),
+ // grpc.WithUnaryInterceptor(otgrpc.OpenTracingClientInterceptor(tracer, otgrpc.LogPayloads())),
+ // grpc.WithStreamInterceptor(otgrpc.OpenTracingStreamClientInterceptor(tracer, otgrpc.LogPayloads())),
+ // grpc.WithDefaultCallOptions(
+ // grpc.CallContentSubtype(clientConf.ContentSubType),
+ // grpc.MaxCallRecvMsgSize(maxCallRecvMsgSize),
+ // grpc.MaxCallSendMsgSize(maxCallSendMsgSize),
+ // ),
+ //
+ // )
+ var cfg *tls.Config
+ var tlsFlag bool
+ var err error
+
+ // todo: move TLSConfig from root to consumer
+ if tlsConfig := config.GetRootConfig().TLSConfig; tlsConfig != nil {
+ cfg, err = config.GetClientTlsConfig(&config.TLSConfig{
+ CACertFile: tlsConfig.CACertFile,
+ TLSCertFile: tlsConfig.TLSCertFile,
+ TLSKeyFile: tlsConfig.TLSKeyFile,
+ TLSServerName: tlsConfig.TLSServerName,
+ })
+ if err != nil {
+ return nil, err
+ }
+ logger.Infof("TRIPLE clientManager initialized the TLSConfig configuration successfully")
+ tlsFlag = true
+ }
+
+ // todo: using option to represent whether using http1 or http2, and whether to use grpc
+
+ key := url.GetParam(constant.InterfaceKey, "")
+ conRefs := config.GetConsumerConfig().References
+ ref, ok := conRefs[key]
+ if !ok {
+ panic("no reference")
+ }
+ // todo: set timeout
+ var transport http.RoundTripper
+ switch ref.Protocol {
+ case "http1":
+ transport = &http.Transport{
+ TLSClientConfig: cfg,
+ }
+ triClientOpts = append(triClientOpts, tri.WithHTTPGet())
+ case TRIPLE:
+ if tlsFlag {
+ transport = &http2.Transport{
+ TLSClientConfig: cfg,
+ }
+ } else {
+ transport = &http2.Transport{
+ DialTLSContext: func(_ context.Context, network, addr string, _ *tls.Config) (net.Conn, error) {
+ return net.Dial(network, addr)
+ },
+ AllowHTTP: true,
+ }
+ }
+ triClientOpts = append(triClientOpts, tri.WithGRPC())
+ }
+ httpClient := &http.Client{
+ Transport: transport,
+ }
+
+ var baseTriUrl string
+ baseTriUrl = strings.TrimPrefix(url.Location, httpPrefix)
+ baseTriUrl = strings.TrimPrefix(url.Location, httpsPrefix)
+ if tlsFlag {
+ baseTriUrl = httpsPrefix + baseTriUrl
+ } else {
+ baseTriUrl = httpPrefix + baseTriUrl
+ }
+ triClients := make(map[string]*tri.Client)
+ for _, method := range url.Methods {
+ triUrl := path.Join(baseTriUrl, url.Interface(), method)
+ triClient := tri.NewClient(httpClient, triUrl, triClientOpts...)
+ triClients[method] = triClient
+ }
+
+ return &clientManager{
+ triClients: triClients,
+ }, nil
+}
diff --git a/protocol/triple/codec.go b/protocol/triple/codec.go
new file mode 100644
index 000000000..a0e1a75bf
--- /dev/null
+++ b/protocol/triple/codec.go
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package triple
+
+import (
+ "bytes"
+ "encoding/json"
+)
+
+import (
+ "github.com/golang/protobuf/jsonpb"
+ "github.com/golang/protobuf/proto"
+
+ "google.golang.org/grpc/encoding"
+)
+
+const (
+ codecJson = "json"
+ codecProto = "proto"
+)
+
+func init() {
+ encoding.RegisterCodec(grpcJson{
+ Marshaler: jsonpb.Marshaler{
+ EmitDefaults: true,
+ OrigName: true,
+ },
+ })
+}
+
+type grpcJson struct {
+ jsonpb.Marshaler
+ jsonpb.Unmarshaler
+}
+
+// Name implements grpc encoding package Codec interface method,
+// returns the name of the Codec implementation.
+func (_ grpcJson) Name() string {
+ return codecJson
+}
+
+// Marshal implements grpc encoding package Codec interface method,returns the wire format of v.
+func (j grpcJson) Marshal(v interface{}) (out []byte, err error) {
+ if pm, ok := v.(proto.Message); ok {
+ b := new(bytes.Buffer)
+ err := j.Marshaler.Marshal(b, pm)
+ if err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+ }
+ return json.Marshal(v)
+}
+
+// Unmarshal implements grpc encoding package Codec interface method,Unmarshal parses the wire format into v.
+func (j grpcJson) Unmarshal(data []byte, v interface{}) (err error) {
+ if pm, ok := v.(proto.Message); ok {
+ b := bytes.NewBuffer(data)
+ return j.Unmarshaler.Unmarshal(b, pm)
+ }
+ return json.Unmarshal(data, v)
+}
diff --git a/protocol/triple/common.go b/protocol/triple/common.go
new file mode 100644
index 000000000..08a9239ac
--- /dev/null
+++ b/protocol/triple/common.go
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package triple
+
+import (
+ "reflect"
+)
+
+import (
+ hessian "github.com/apache/dubbo-go-hessian2"
+
+ perrors "github.com/pkg/errors"
+)
+
+// ReflectResponse reflect return value
+func ReflectResponse(in interface{}, out interface{}) error {
+ if in == nil {
+ return perrors.Errorf("@in is nil")
+ }
+
+ if out == nil {
+ return perrors.Errorf("@out is nil")
+ }
+ if reflect.TypeOf(out).Kind() != reflect.Ptr {
+ return perrors.Errorf("@out should be a pointer")
+ }
+
+ inValue := hessian.EnsurePackValue(in)
+ outValue := hessian.EnsurePackValue(out)
+
+ outType := outValue.Type().String()
+ if outType == "interface {}" || outType == "*interface {}" {
+ hessian.SetValue(outValue, inValue)
+ return nil
+ }
+
+ switch inValue.Type().Kind() {
+ case reflect.Slice, reflect.Array:
+ return CopySlice(inValue, outValue)
+ case reflect.Map:
+ return CopyMap(inValue, outValue)
+ default:
+ hessian.SetValue(outValue, inValue)
+ }
+
+ return nil
+}
+
+// CopySlice copy from inSlice to outSlice
+func CopySlice(inSlice, outSlice reflect.Value) error {
+ if inSlice.IsNil() {
+ return perrors.New("@in is nil")
+ }
+ if inSlice.Kind() != reflect.Slice {
+ return perrors.Errorf("@in is not slice, but %v", inSlice.Kind())
+ }
+
+ for outSlice.Kind() == reflect.Ptr {
+ outSlice = outSlice.Elem()
+ }
+
+ size := inSlice.Len()
+ outSlice.Set(reflect.MakeSlice(outSlice.Type(), size, size))
+
+ for i := 0; i < size; i++ {
+ inSliceValue := inSlice.Index(i)
+ if !inSliceValue.Type().AssignableTo(outSlice.Index(i).Type()) {
+ return perrors.Errorf("in element type [%s] can not assign to out element type [%s]",
+ inSliceValue.Type().String(), outSlice.Type().String())
+ }
+ outSlice.Index(i).Set(inSliceValue)
+ }
+
+ return nil
+}
+
+// CopyMap copy from in map to out map
+func CopyMap(inMapValue, outMapValue reflect.Value) error {
+ if inMapValue.IsNil() {
+ return perrors.New("@in is nil")
+ }
+ if !inMapValue.CanInterface() {
+ return perrors.New("@in's Interface can not be used.")
+ }
+ if inMapValue.Kind() != reflect.Map {
+ return perrors.Errorf("@in is not map, but %v", inMapValue.Kind())
+ }
+
+ outMapType := hessian.UnpackPtrType(outMapValue.Type())
+ hessian.SetValue(outMapValue, reflect.MakeMap(outMapType))
+
+ outKeyType := outMapType.Key()
+
+ outMapValue = hessian.UnpackPtrValue(outMapValue)
+ outValueType := outMapValue.Type().Elem()
+
+ for _, inKey := range inMapValue.MapKeys() {
+ inValue := inMapValue.MapIndex(inKey)
+
+ if !inKey.Type().AssignableTo(outKeyType) {
+ return perrors.Errorf("in Key:{type:%s, value:%#v} can not assign to out Key:{type:%s} ",
+ inKey.Type().String(), inKey, outKeyType.String())
+ }
+ if !inValue.Type().AssignableTo(outValueType) {
+ return perrors.Errorf("in Value:{type:%s, value:%#v} can not assign to out value:{type:%s}",
+ inValue.Type().String(), inValue, outValueType.String())
+ }
+ outMapValue.SetMapIndex(inKey, inValue)
+ }
+
+ return nil
+}
diff --git a/protocol/triple/internal/client/cmd/dubbogo.yml b/protocol/triple/internal/client/cmd/dubbogo.yml
new file mode 100644
index 000000000..acf53b3a5
--- /dev/null
+++ b/protocol/triple/internal/client/cmd/dubbogo.yml
@@ -0,0 +1,11 @@
+dubbo:
+ registries:
+ demoZK:
+ protocol: zookeeper
+ timeout: 3s
+ address: 127.0.0.1:2181
+ consumer:
+ references:
+ greet.GreetService:
+ protocol: grpc_new
+ interface: greet.GreetService
\ No newline at end of file
diff --git a/protocol/triple/internal/client/cmd/main.go b/protocol/triple/internal/client/cmd/main.go
new file mode 100644
index 000000000..55ede08d4
--- /dev/null
+++ b/protocol/triple/internal/client/cmd/main.go
@@ -0,0 +1,122 @@
+package main
+
+import (
+ "context"
+)
+
+import (
+ "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/client"
+ _ "dubbo.apache.org/dubbo-go/v3/imports"
+ greet "dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto/greettriple"
+)
+
+func main() {
+ //client initialization
+ cli, err := client.NewClient(
+ client.WithURL("127.0.0.1:8080"),
+ )
+ svc, err := greettriple.NewGreetService(cli)
+ if err != nil {
+ panic(err)
+ }
+
+ // classic config initialization
+ //svc := new(greettriple.GreetServiceImpl)
+ //greettriple.SetConsumerService(dubboCli)
+ //config.Load() // need dubbogo.yml
+
+ if err := testUnary(svc); err != nil {
+ logger.Error(err)
+ return
+ }
+
+ if err := testBidiStream(svc); err != nil {
+ logger.Error(err)
+ return
+ }
+
+ if err := testClientStream(svc); err != nil {
+ logger.Error(err)
+ return
+ }
+
+ if err := testServerStream(svc); err != nil {
+ logger.Error(err)
+ return
+ }
+}
+
+func testUnary(svc greettriple.GreetService) error {
+ logger.Info("start to test TRIPLE unary call")
+ resp, err := svc.Greet(context.Background(), &greet.GreetRequest{Name: "triple"})
+ if err != nil {
+ return err
+ }
+ logger.Infof("TRIPLE unary call resp: %s", resp.Greeting)
+ return nil
+}
+
+func testBidiStream(svc greettriple.GreetService) error {
+ logger.Info("start to test TRIPLE bidi stream")
+ stream, err := svc.GreetStream(context.Background())
+ if err != nil {
+ return err
+ }
+ if err := stream.Send(&greet.GreetStreamRequest{Name: "triple"}); err != nil {
+ return err
+ }
+ resp, err := stream.Recv()
+ if err != nil {
+ return err
+ }
+ logger.Infof("TRIPLE bidi stream resp: %s", resp.Greeting)
+ if err := stream.CloseRequest(); err != nil {
+ return err
+ }
+ if err := stream.CloseResponse(); err != nil {
+ return err
+ }
+ return nil
+}
+
+func testClientStream(svc greettriple.GreetService) error {
+ logger.Info("start to test TRIPLE dubboClint stream")
+ stream, err := svc.GreetClientStream(context.Background())
+ if err != nil {
+ return err
+ }
+ for i := 0; i < 5; i++ {
+ if err := stream.Send(&greet.GreetClientStreamRequest{Name: "triple"}); err != nil {
+ return err
+ }
+ }
+ resp, err := stream.CloseAndRecv()
+ if err != nil {
+ return err
+ }
+ logger.Infof("TRIPLE dubboClint stream resp: %s", resp.Greeting)
+ return nil
+}
+
+func testServerStream(svc greettriple.GreetService) error {
+ logger.Info("start to test TRIPLE server stream")
+ stream, err := svc.GreetServerStream(context.Background(), &greet.GreetServerStreamRequest{Name: "triple"})
+ if err != nil {
+ return err
+ }
+ for stream.Recv() {
+ logger.Infof("TRIPLE server stream resp: %s", stream.Msg().Greeting)
+ }
+ if stream.Err() != nil {
+ return err
+ }
+ if err := stream.Close(); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/protocol/triple/internal/proto/greet.pb.go b/protocol/triple/internal/proto/greet.pb.go
new file mode 100644
index 000000000..2dbde2f2c
--- /dev/null
+++ b/protocol/triple/internal/proto/greet.pb.go
@@ -0,0 +1,621 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.17.3
+// source: protocol/triple/internal/proto/greet.proto
+
+package greet
+
+import (
+ reflect "reflect"
+ sync "sync"
+)
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type GreetRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+}
+
+func (x *GreetRequest) Reset() {
+ *x = GreetRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GreetRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GreetRequest) ProtoMessage() {}
+
+func (x *GreetRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GreetRequest.ProtoReflect.Descriptor instead.
+func (*GreetRequest) Descriptor() ([]byte, []int) {
+ return file_protocol_triple_internal_proto_greet_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *GreetRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+type GreetResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Greeting string `protobuf:"bytes,1,opt,name=greeting,proto3" json:"greeting,omitempty"`
+}
+
+func (x *GreetResponse) Reset() {
+ *x = GreetResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GreetResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GreetResponse) ProtoMessage() {}
+
+func (x *GreetResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GreetResponse.ProtoReflect.Descriptor instead.
+func (*GreetResponse) Descriptor() ([]byte, []int) {
+ return file_protocol_triple_internal_proto_greet_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *GreetResponse) GetGreeting() string {
+ if x != nil {
+ return x.Greeting
+ }
+ return ""
+}
+
+type GreetStreamRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+}
+
+func (x *GreetStreamRequest) Reset() {
+ *x = GreetStreamRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GreetStreamRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GreetStreamRequest) ProtoMessage() {}
+
+func (x *GreetStreamRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GreetStreamRequest.ProtoReflect.Descriptor instead.
+func (*GreetStreamRequest) Descriptor() ([]byte, []int) {
+ return file_protocol_triple_internal_proto_greet_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *GreetStreamRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+type GreetStreamResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Greeting string `protobuf:"bytes,1,opt,name=greeting,proto3" json:"greeting,omitempty"`
+}
+
+func (x *GreetStreamResponse) Reset() {
+ *x = GreetStreamResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GreetStreamResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GreetStreamResponse) ProtoMessage() {}
+
+func (x *GreetStreamResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GreetStreamResponse.ProtoReflect.Descriptor instead.
+func (*GreetStreamResponse) Descriptor() ([]byte, []int) {
+ return file_protocol_triple_internal_proto_greet_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *GreetStreamResponse) GetGreeting() string {
+ if x != nil {
+ return x.Greeting
+ }
+ return ""
+}
+
+type GreetClientStreamRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+}
+
+func (x *GreetClientStreamRequest) Reset() {
+ *x = GreetClientStreamRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GreetClientStreamRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GreetClientStreamRequest) ProtoMessage() {}
+
+func (x *GreetClientStreamRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GreetClientStreamRequest.ProtoReflect.Descriptor instead.
+func (*GreetClientStreamRequest) Descriptor() ([]byte, []int) {
+ return file_protocol_triple_internal_proto_greet_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *GreetClientStreamRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+type GreetClientStreamResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Greeting string `protobuf:"bytes,1,opt,name=greeting,proto3" json:"greeting,omitempty"`
+}
+
+func (x *GreetClientStreamResponse) Reset() {
+ *x = GreetClientStreamResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GreetClientStreamResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GreetClientStreamResponse) ProtoMessage() {}
+
+func (x *GreetClientStreamResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GreetClientStreamResponse.ProtoReflect.Descriptor instead.
+func (*GreetClientStreamResponse) Descriptor() ([]byte, []int) {
+ return file_protocol_triple_internal_proto_greet_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *GreetClientStreamResponse) GetGreeting() string {
+ if x != nil {
+ return x.Greeting
+ }
+ return ""
+}
+
+type GreetServerStreamRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+}
+
+func (x *GreetServerStreamRequest) Reset() {
+ *x = GreetServerStreamRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GreetServerStreamRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GreetServerStreamRequest) ProtoMessage() {}
+
+func (x *GreetServerStreamRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GreetServerStreamRequest.ProtoReflect.Descriptor instead.
+func (*GreetServerStreamRequest) Descriptor() ([]byte, []int) {
+ return file_protocol_triple_internal_proto_greet_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *GreetServerStreamRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+type GreetServerStreamResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Greeting string `protobuf:"bytes,1,opt,name=greeting,proto3" json:"greeting,omitempty"`
+}
+
+func (x *GreetServerStreamResponse) Reset() {
+ *x = GreetServerStreamResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GreetServerStreamResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GreetServerStreamResponse) ProtoMessage() {}
+
+func (x *GreetServerStreamResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_protocol_triple_internal_proto_greet_proto_msgTypes[7]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GreetServerStreamResponse.ProtoReflect.Descriptor instead.
+func (*GreetServerStreamResponse) Descriptor() ([]byte, []int) {
+ return file_protocol_triple_internal_proto_greet_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *GreetServerStreamResponse) GetGreeting() string {
+ if x != nil {
+ return x.Greeting
+ }
+ return ""
+}
+
+var File_protocol_triple_internal_proto_greet_proto protoreflect.FileDescriptor
+
+var file_protocol_triple_internal_proto_greet_proto_rawDesc = []byte{
+ 0x0a, 0x2a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x74, 0x72, 0x69, 0x70, 0x6c,
+ 0x65, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2f, 0x67, 0x72, 0x65, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x67, 0x72,
+ 0x65, 0x65, 0x74, 0x22, 0x22, 0x0a, 0x0c, 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2b, 0x0a, 0x0d, 0x47, 0x72, 0x65, 0x65, 0x74,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x72, 0x65, 0x65,
+ 0x74, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x65, 0x65,
+ 0x74, 0x69, 0x6e, 0x67, 0x22, 0x28, 0x0a, 0x12, 0x47, 0x72, 0x65, 0x65, 0x74, 0x53, 0x74, 0x72,
+ 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x31,
+ 0x0a, 0x13, 0x47, 0x72, 0x65, 0x65, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e,
+ 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e,
+ 0x67, 0x22, 0x2e, 0x0a, 0x18, 0x47, 0x72, 0x65, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+ 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x22, 0x37, 0x0a, 0x19, 0x47, 0x72, 0x65, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+ 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a,
+ 0x0a, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x2e, 0x0a, 0x18, 0x47, 0x72,
+ 0x65, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x37, 0x0a, 0x19, 0x47, 0x72,
+ 0x65, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74,
+ 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74,
+ 0x69, 0x6e, 0x67, 0x32, 0xc8, 0x02, 0x0a, 0x0c, 0x47, 0x72, 0x65, 0x65, 0x74, 0x53, 0x65, 0x72,
+ 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x47, 0x72, 0x65, 0x65, 0x74, 0x12, 0x13, 0x2e,
+ 0x67, 0x72, 0x65, 0x65, 0x74, 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x72, 0x65, 0x65, 0x74, 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x0b, 0x47, 0x72,
+ 0x65, 0x65, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x19, 0x2e, 0x67, 0x72, 0x65, 0x65,
+ 0x74, 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x72, 0x65, 0x65, 0x74, 0x2e, 0x47, 0x72, 0x65,
+ 0x65, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x5a, 0x0a, 0x11, 0x47, 0x72, 0x65, 0x65, 0x74, 0x43,
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1f, 0x2e, 0x67, 0x72,
+ 0x65, 0x65, 0x74, 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53,
+ 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67,
+ 0x72, 0x65, 0x65, 0x74, 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+ 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
+ 0x28, 0x01, 0x12, 0x5a, 0x0a, 0x11, 0x47, 0x72, 0x65, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65,
+ 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1f, 0x2e, 0x67, 0x72, 0x65, 0x65, 0x74, 0x2e,
+ 0x47, 0x72, 0x65, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61,
+ 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x72, 0x65, 0x65, 0x74,
+ 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65,
+ 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x42, 0x43,
+ 0x5a, 0x41, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x6f,
+ 0x72, 0x67, 0x2f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x74, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x2f, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x67, 0x72,
+ 0x65, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_protocol_triple_internal_proto_greet_proto_rawDescOnce sync.Once
+ file_protocol_triple_internal_proto_greet_proto_rawDescData = file_protocol_triple_internal_proto_greet_proto_rawDesc
+)
+
+func file_protocol_triple_internal_proto_greet_proto_rawDescGZIP() []byte {
+ file_protocol_triple_internal_proto_greet_proto_rawDescOnce.Do(func() {
+ file_protocol_triple_internal_proto_greet_proto_rawDescData = protoimpl.X.CompressGZIP(file_protocol_triple_internal_proto_greet_proto_rawDescData)
+ })
+ return file_protocol_triple_internal_proto_greet_proto_rawDescData
+}
+
+var file_protocol_triple_internal_proto_greet_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
+var file_protocol_triple_internal_proto_greet_proto_goTypes = []interface{}{
+ (*GreetRequest)(nil), // 0: greet.GreetRequest
+ (*GreetResponse)(nil), // 1: greet.GreetResponse
+ (*GreetStreamRequest)(nil), // 2: greet.GreetStreamRequest
+ (*GreetStreamResponse)(nil), // 3: greet.GreetStreamResponse
+ (*GreetClientStreamRequest)(nil), // 4: greet.GreetClientStreamRequest
+ (*GreetClientStreamResponse)(nil), // 5: greet.GreetClientStreamResponse
+ (*GreetServerStreamRequest)(nil), // 6: greet.GreetServerStreamRequest
+ (*GreetServerStreamResponse)(nil), // 7: greet.GreetServerStreamResponse
+}
+var file_protocol_triple_internal_proto_greet_proto_depIdxs = []int32{
+ 0, // 0: greet.GreetService.Greet:input_type -> greet.GreetRequest
+ 2, // 1: greet.GreetService.GreetStream:input_type -> greet.GreetStreamRequest
+ 4, // 2: greet.GreetService.GreetClientStream:input_type -> greet.GreetClientStreamRequest
+ 6, // 3: greet.GreetService.GreetServerStream:input_type -> greet.GreetServerStreamRequest
+ 1, // 4: greet.GreetService.Greet:output_type -> greet.GreetResponse
+ 3, // 5: greet.GreetService.GreetStream:output_type -> greet.GreetStreamResponse
+ 5, // 6: greet.GreetService.GreetClientStream:output_type -> greet.GreetClientStreamResponse
+ 7, // 7: greet.GreetService.GreetServerStream:output_type -> greet.GreetServerStreamResponse
+ 4, // [4:8] is the sub-list for method output_type
+ 0, // [0:4] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_protocol_triple_internal_proto_greet_proto_init() }
+func file_protocol_triple_internal_proto_greet_proto_init() {
+ if File_protocol_triple_internal_proto_greet_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_protocol_triple_internal_proto_greet_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GreetRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_protocol_triple_internal_proto_greet_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GreetResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_protocol_triple_internal_proto_greet_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GreetStreamRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_protocol_triple_internal_proto_greet_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GreetStreamResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_protocol_triple_internal_proto_greet_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GreetClientStreamRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_protocol_triple_internal_proto_greet_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GreetClientStreamResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_protocol_triple_internal_proto_greet_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GreetServerStreamRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_protocol_triple_internal_proto_greet_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GreetServerStreamResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_protocol_triple_internal_proto_greet_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 8,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_protocol_triple_internal_proto_greet_proto_goTypes,
+ DependencyIndexes: file_protocol_triple_internal_proto_greet_proto_depIdxs,
+ MessageInfos: file_protocol_triple_internal_proto_greet_proto_msgTypes,
+ }.Build()
+ File_protocol_triple_internal_proto_greet_proto = out.File
+ file_protocol_triple_internal_proto_greet_proto_rawDesc = nil
+ file_protocol_triple_internal_proto_greet_proto_goTypes = nil
+ file_protocol_triple_internal_proto_greet_proto_depIdxs = nil
+}
diff --git a/protocol/triple/internal/proto/greet.proto b/protocol/triple/internal/proto/greet.proto
new file mode 100644
index 000000000..1a32ad25c
--- /dev/null
+++ b/protocol/triple/internal/proto/greet.proto
@@ -0,0 +1,44 @@
+syntax = "proto3";
+
+package greet;
+
+option go_package = "dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto;greet";
+
+message GreetRequest {
+ string name = 1;
+}
+
+message GreetResponse {
+ string greeting = 1;
+}
+
+message GreetStreamRequest {
+ string name = 1;
+}
+
+message GreetStreamResponse {
+ string greeting = 1;
+}
+
+message GreetClientStreamRequest {
+ string name = 1;
+}
+
+message GreetClientStreamResponse {
+ string greeting = 1;
+}
+
+message GreetServerStreamRequest {
+ string name = 1;
+}
+
+message GreetServerStreamResponse {
+ string greeting = 1;
+}
+
+service GreetService {
+ rpc Greet(GreetRequest) returns (GreetResponse) {}
+ rpc GreetStream(stream GreetStreamRequest) returns (stream GreetStreamResponse) {}
+ rpc GreetClientStream(stream GreetClientStreamRequest) returns (GreetClientStreamResponse) {}
+ rpc GreetServerStream(GreetServerStreamRequest) returns (stream GreetServerStreamResponse) {}
+}
\ No newline at end of file
diff --git a/protocol/triple/internal/proto/greettriple/greet.triple.go b/protocol/triple/internal/proto/greettriple/greet.triple.go
new file mode 100644
index 000000000..841223a49
--- /dev/null
+++ b/protocol/triple/internal/proto/greettriple/greet.triple.go
@@ -0,0 +1,388 @@
+// Code generated by protoc-gen-triple. DO NOT EDIT.
+//
+// Source: protocol/triple/internal/proto/greet.proto
+
+package greettriple
+
+import (
+ context "context"
+ errors "errors"
+ http "net/http"
+)
+
+import (
+ client "dubbo.apache.org/dubbo-go/v3/client"
+ "dubbo.apache.org/dubbo-go/v3/common"
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+ "dubbo.apache.org/dubbo-go/v3/config"
+ proto "dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto"
+ triple_protocol "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+ "dubbo.apache.org/dubbo-go/v3/provider"
+)
+
+// This is a compile-time assertion to ensure that this generated file and the connect package are
+// compatible. If you get a compiler error that this constant is not defined, this code was
+// generated with a version of connect newer than the one compiled into your binary. You can fix the
+// problem by either regenerating this code with an older version of connect or updating the connect
+// version compiled into your binary.
+const _ = triple_protocol.IsAtLeastVersion0_1_0
+
+const (
+ // GreetServiceName is the fully-qualified name of the GreetService service.
+ GreetServiceName = "greet.GreetService"
+)
+
+// These constants are the fully-qualified names of the RPCs defined in this package. They're
+// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route.
+//
+// Note that these are different from the fully-qualified method names used by
+// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to
+// reflection-formatted method names, remove the leading slash and convert the remaining slash to a
+// period.
+const (
+ // GreetServiceGreetProcedure is the fully-qualified name of the GreetService's Greet RPC.
+ GreetServiceGreetProcedure = "/greet.GreetService/Greet"
+ // GreetServiceGreetStreamProcedure is the fully-qualified name of the GreetService's GreetStream
+ // RPC.
+ GreetServiceGreetStreamProcedure = "/greet.GreetService/GreetStream"
+ // GreetServiceGreetClientStreamProcedure is the fully-qualified name of the GreetService's
+ // GreetClientStream RPC.
+ GreetServiceGreetClientStreamProcedure = "/greet.GreetService/GreetClientStream"
+ // GreetServiceGreetServerStreamProcedure is the fully-qualified name of the GreetService's
+ // GreetServerStream RPC.
+ GreetServiceGreetServerStreamProcedure = "/greet.GreetService/GreetServerStream"
+)
+
+// GreetService is a client for the greet.GreetService service.
+type GreetService interface {
+ Greet(ctx context.Context, req *proto.GreetRequest, opts ...client.CallOption) (*proto.GreetResponse, error)
+ GreetStream(ctx context.Context, opts ...client.CallOption) (GreetService_GreetStreamClient, error)
+ GreetClientStream(ctx context.Context, opts ...client.CallOption) (GreetService_GreetClientStreamClient, error)
+ GreetServerStream(ctx context.Context, req *proto.GreetServerStreamRequest, opts ...client.CallOption) (GreetService_GreetServerStreamClient, error)
+}
+
+// NewGreetService constructs a client for the greet.GreetService service. By default, it uses
+// the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends
+// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or
+// connect.WithGRPCWeb() options.
+//
+// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
+// http://api.acme.com or https://acme.com/grpc).
+func NewGreetService(cli *client.Client) (GreetService, error) {
+ if err := cli.Init(&GreetService_ClientInfo); err != nil {
+ return nil, err
+ }
+ return &GreetServiceImpl{
+ cli: cli,
+ }, nil
+}
+
+func SetConsumerService(srv common.RPCService) {
+ config.SetClientInfoService(&GreetService_ClientInfo, srv)
+}
+
+// GreetServiceImpl implements GreetService.
+type GreetServiceImpl struct {
+ cli *client.Client
+}
+
+func (c *GreetServiceImpl) Greet(ctx context.Context, req *proto.GreetRequest, opts ...client.CallOption) (*proto.GreetResponse, error) {
+ triReq := triple_protocol.NewRequest(req)
+ resp := new(proto.GreetResponse)
+ triResp := triple_protocol.NewResponse(resp)
+ if err := c.cli.CallUnary(ctx, triReq, triResp, "greet.GreetService", "Greet", opts...); err != nil {
+ return nil, err
+ }
+ return resp, nil
+}
+
+func (c *GreetServiceImpl) GreetStream(ctx context.Context, opts ...client.CallOption) (GreetService_GreetStreamClient, error) {
+ stream, err := c.cli.CallBidiStream(ctx, "greet.GreetService", "GreetStream", opts...)
+ if err != nil {
+ return nil, err
+ }
+ rawStream := stream.(*triple_protocol.BidiStreamForClient)
+ return &greetServiceGreetStreamClient{rawStream}, nil
+}
+
+func (c *GreetServiceImpl) GreetClientStream(ctx context.Context, opts ...client.CallOption) (GreetService_GreetClientStreamClient, error) {
+ stream, err := c.cli.CallClientStream(ctx, "greet.GreetService", "GreetClientStream", opts...)
+ if err != nil {
+ return nil, err
+ }
+ rawStream := stream.(*triple_protocol.ClientStreamForClient)
+ return &greetServiceGreetClientStreamClient{rawStream}, nil
+}
+
+func (c *GreetServiceImpl) GreetServerStream(ctx context.Context, req *proto.GreetServerStreamRequest, opts ...client.CallOption) (GreetService_GreetServerStreamClient, error) {
+ triReq := triple_protocol.NewRequest(req)
+ stream, err := c.cli.CallServerStream(ctx, triReq, "greet.GreetService", "GreetServerStream", opts...)
+ if err != nil {
+ return nil, err
+ }
+ rawStream := stream.(*triple_protocol.ServerStreamForClient)
+ return &greetServiceGreetServerStreamClient{rawStream}, nil
+}
+
+type GreetService_GreetStreamClient interface {
+ Spec() triple_protocol.Spec
+ Peer() triple_protocol.Peer
+ Send(*proto.GreetStreamRequest) error
+ RequestHeader() http.Header
+ CloseRequest() error
+ Recv() (*proto.GreetStreamResponse, error)
+ ResponseHeader() http.Header
+ ResponseTrailer() http.Header
+ CloseResponse() error
+}
+
+type greetServiceGreetStreamClient struct {
+ *triple_protocol.BidiStreamForClient
+}
+
+func (cli *greetServiceGreetStreamClient) Send(msg *proto.GreetStreamRequest) error {
+ return cli.BidiStreamForClient.Send(msg)
+}
+
+func (cli *greetServiceGreetStreamClient) Recv() (*proto.GreetStreamResponse, error) {
+ msg := new(proto.GreetStreamResponse)
+ if err := cli.BidiStreamForClient.Receive(msg); err != nil {
+ return nil, err
+ }
+ return msg, nil
+}
+
+type GreetService_GreetClientStreamClient interface {
+ Spec() triple_protocol.Spec
+ Peer() triple_protocol.Peer
+ Send(any) error
+ RequestHeader() http.Header
+ CloseAndRecv() (*proto.GreetClientStreamResponse, error)
+ Conn() (triple_protocol.StreamingClientConn, error)
+}
+
+type greetServiceGreetClientStreamClient struct {
+ *triple_protocol.ClientStreamForClient
+}
+
+func (cli *greetServiceGreetClientStreamClient) CloseAndRecv() (*proto.GreetClientStreamResponse, error) {
+ msg := new(proto.GreetClientStreamResponse)
+ resp := triple_protocol.NewResponse(msg)
+ if err := cli.ClientStreamForClient.CloseAndReceive(resp); err != nil {
+ return nil, err
+ }
+ return msg, nil
+}
+
+func (cli *greetServiceGreetClientStreamClient) Conn() (triple_protocol.StreamingClientConn, error) {
+ return cli.ClientStreamForClient.Conn()
+}
+
+type GreetService_GreetServerStreamClient interface {
+ Recv() bool
+ ResponseHeader() http.Header
+ ResponseTrailer() http.Header
+ Msg() *proto.GreetServerStreamResponse
+ Err() error
+ Conn() (triple_protocol.StreamingClientConn, error)
+ Close() error
+}
+
+type greetServiceGreetServerStreamClient struct {
+ *triple_protocol.ServerStreamForClient
+}
+
+func (cli *greetServiceGreetServerStreamClient) Recv() bool {
+ msg := new(proto.GreetServerStreamResponse)
+ return cli.ServerStreamForClient.Receive(msg)
+}
+
+func (cli *greetServiceGreetServerStreamClient) Msg() *proto.GreetServerStreamResponse {
+ msg := cli.ServerStreamForClient.Msg()
+ if msg == nil {
+ return new(proto.GreetServerStreamResponse)
+ }
+ return msg.(*proto.GreetServerStreamResponse)
+}
+
+func (cli *greetServiceGreetServerStreamClient) Conn() (triple_protocol.StreamingClientConn, error) {
+ return cli.ServerStreamForClient.Conn()
+}
+
+var GreetService_ClientInfo = client.ClientInfo{
+ InterfaceName: "greet.GreetService",
+ MethodNames: []string{"Greet", "GreetStream", "GreetClientStream", "GreetServerStream"},
+ ClientInjectFunc: func(dubboCliRaw interface{}, cli *client.Client) {
+ dubboCli := dubboCliRaw.(GreetServiceImpl)
+ dubboCli.cli = cli
+ },
+}
+
+// GreetServiceHandler is an implementation of the greet.GreetService service.
+type GreetServiceHandler interface {
+ Greet(context.Context, *proto.GreetRequest) (*proto.GreetResponse, error)
+ GreetStream(context.Context, GreetService_GreetStreamServer) error
+ GreetClientStream(context.Context, GreetService_GreetClientStreamServer) (*proto.GreetClientStreamResponse, error)
+ GreetServerStream(context.Context, *proto.GreetServerStreamRequest, GreetService_GreetServerStreamServer) error
+}
+
+func ProvideGreetServiceHandler(pro *provider.Provider, hdlr GreetServiceHandler) error {
+ return pro.Provide(hdlr, &GreetService_ServiceInfo)
+}
+
+type GreetService_GreetStreamServer interface {
+ Send(*proto.GreetStreamResponse) error
+ Recv() (*proto.GreetStreamRequest, error)
+ Spec() triple_protocol.Spec
+ Peer() triple_protocol.Peer
+ RequestHeader() http.Header
+ ResponseHeader() http.Header
+ ResponseTrailer() http.Header
+ Conn() triple_protocol.StreamingHandlerConn
+}
+
+type greetServiceGreetStreamServer struct {
+ *triple_protocol.BidiStream
+}
+
+func (srv *greetServiceGreetStreamServer) Send(msg *proto.GreetStreamResponse) error {
+ return srv.BidiStream.Send(msg)
+}
+
+func (srv greetServiceGreetStreamServer) Recv() (*proto.GreetStreamRequest, error) {
+ msg := new(proto.GreetStreamRequest)
+ if err := srv.BidiStream.Receive(msg); err != nil {
+ return nil, err
+ }
+ return msg, nil
+}
+
+type GreetService_GreetClientStreamServer interface {
+ Spec() triple_protocol.Spec
+ Peer() triple_protocol.Peer
+ Recv() bool
+ RequestHeader() http.Header
+ Msg() *proto.GreetClientStreamRequest
+ Err() error
+ Conn() triple_protocol.StreamingHandlerConn
+}
+
+type greetServiceGreetClientStreamServer struct {
+ *triple_protocol.ClientStream
+}
+
+func (srv *greetServiceGreetClientStreamServer) Recv() bool {
+ msg := new(proto.GreetClientStreamRequest)
+ return srv.ClientStream.Receive(msg)
+}
+
+func (srv *greetServiceGreetClientStreamServer) Msg() *proto.GreetClientStreamRequest {
+ msgRaw := srv.ClientStream.Msg()
+ if msgRaw == nil {
+ return new(proto.GreetClientStreamRequest)
+ }
+ return msgRaw.(*proto.GreetClientStreamRequest)
+}
+
+type GreetService_GreetServerStreamServer interface {
+ Send(*proto.GreetServerStreamResponse) error
+ ResponseHeader() http.Header
+ ResponseTrailer() http.Header
+ Conn() triple_protocol.StreamingHandlerConn
+}
+
+type greetServiceGreetServerStreamServer struct {
+ *triple_protocol.ServerStream
+}
+
+func (g greetServiceGreetServerStreamServer) Send(msg *proto.GreetServerStreamResponse) error {
+ return g.ServerStream.Send(msg)
+}
+
+var GreetService_ServiceInfo = provider.ServiceInfo{
+ InterfaceName: "greet.GreetService",
+ ServiceType: (*GreetServiceHandler)(nil),
+ Methods: []provider.MethodInfo{
+ {
+ Name: "Greet",
+ Type: constant.CallUnary,
+ ReqInitFunc: func() interface{} {
+ return new(proto.GreetRequest)
+ },
+ MethodFunc: func(ctx context.Context, args []interface{}, handler interface{}) (interface{}, error) {
+ req := args[0].(*proto.GreetRequest)
+ res, err := handler.(GreetServiceHandler).Greet(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+ return triple_protocol.NewResponse(res), nil
+ },
+ },
+ {
+ Name: "GreetStream",
+ Type: constant.CallBidiStream,
+ StreamInitFunc: func(baseStream interface{}) interface{} {
+ return greetServiceGreetStreamServer{baseStream.(*triple_protocol.BidiStream)}
+ },
+ MethodFunc: func(ctx context.Context, args []interface{}, handler interface{}) (interface{}, error) {
+ stream := args[0].(GreetService_GreetStreamServer)
+ if err := handler.(GreetServiceHandler).GreetStream(ctx, stream); err != nil {
+ return nil, err
+ }
+ return nil, nil
+ },
+ },
+ {
+ Name: "GreetClientStream",
+ Type: constant.CallClientStream,
+ StreamInitFunc: func(baseStream interface{}) interface{} {
+ return greetServiceGreetClientStreamServer{baseStream.(*triple_protocol.ClientStream)}
+ },
+ MethodFunc: func(ctx context.Context, args []interface{}, handler interface{}) (interface{}, error) {
+ stream := args[0].(GreetService_GreetClientStreamServer)
+ res, err := handler.(GreetServiceHandler).GreetClientStream(ctx, stream)
+ if err != nil {
+ return nil, err
+ }
+ return triple_protocol.NewResponse(res), nil
+ },
+ },
+ {
+ Name: "GreetServerStream",
+ Type: constant.CallServerStream,
+ ReqInitFunc: func() interface{} {
+ return new(proto.GreetClientStreamRequest)
+ },
+ StreamInitFunc: func(baseStream interface{}) interface{} {
+ return greetServiceGreetServerStreamServer{baseStream.(*triple_protocol.ServerStream)}
+ },
+ MethodFunc: func(ctx context.Context, args []interface{}, handler interface{}) (interface{}, error) {
+ req := args[0].(*proto.GreetServerStreamRequest)
+ stream := args[1].(GreetService_GreetServerStreamServer)
+ if err := handler.(GreetServiceHandler).GreetServerStream(ctx, req, stream); err != nil {
+ return nil, err
+ }
+ return nil, nil
+ },
+ },
+ },
+}
+
+// UnimplementedGreetServiceHandler returns CodeUnimplemented from all methods.
+type UnimplementedGreetServiceHandler struct{}
+
+func (UnimplementedGreetServiceHandler) Greet(context.Context, *proto.GreetRequest) (*proto.GreetResponse, error) {
+ return nil, triple_protocol.NewError(triple_protocol.CodeUnimplemented, errors.New("greet.GreetService.Greet is not implemented"))
+}
+
+func (UnimplementedGreetServiceHandler) GreetStream(context.Context, *triple_protocol.BidiStream) error {
+ return triple_protocol.NewError(triple_protocol.CodeUnimplemented, errors.New("greet.GreetService.GreetStream is not implemented"))
+}
+
+func (UnimplementedGreetServiceHandler) GreetClientStream(context.Context, *triple_protocol.ClientStream) (*triple_protocol.Response, error) {
+ return nil, triple_protocol.NewError(triple_protocol.CodeUnimplemented, errors.New("greet.GreetService.GreetClientStream is not implemented"))
+}
+
+func (UnimplementedGreetServiceHandler) GreetServerStream(context.Context, *triple_protocol.Request, *triple_protocol.ServerStream) error {
+ return triple_protocol.NewError(triple_protocol.CodeUnimplemented, errors.New("greet.GreetService.GreetServerStream is not implemented"))
+}
diff --git a/protocol/triple/internal/server/cmd/dubbogo.yml b/protocol/triple/internal/server/cmd/dubbogo.yml
new file mode 100644
index 000000000..75d198680
--- /dev/null
+++ b/protocol/triple/internal/server/cmd/dubbogo.yml
@@ -0,0 +1,16 @@
+dubbo:
+ registries:
+ demoZK:
+ protocol: zookeeper
+ address: 127.0.0.1:2181
+ protocols:
+ grpc_new:
+ name: grpc_new
+ port: 20000
+ provider:
+ services:
+ greet.GreetService:
+ interface: greet.GreetService
+ proxy: default
+ protocol-ids:
+ - grpc_new
\ No newline at end of file
diff --git a/protocol/triple/internal/server/cmd/main.go b/protocol/triple/internal/server/cmd/main.go
new file mode 100644
index 000000000..b38a89636
--- /dev/null
+++ b/protocol/triple/internal/server/cmd/main.go
@@ -0,0 +1,75 @@
+package main
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+)
+
+import (
+ "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+ _ "dubbo.apache.org/dubbo-go/v3/imports"
+ greet "dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto"
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto/greettriple"
+ "dubbo.apache.org/dubbo-go/v3/provider"
+)
+
+type GreetConnectServer struct {
+}
+
+func (srv *GreetConnectServer) Greet(ctx context.Context, req *greet.GreetRequest) (*greet.GreetResponse, error) {
+ resp := &greet.GreetResponse{Greeting: "hello " + req.Name}
+ return resp, nil
+}
+
+func (srv *GreetConnectServer) GreetStream(ctx context.Context, stream greettriple.GreetService_GreetStreamServer) error {
+ for {
+ req, err := stream.Recv()
+ if err != nil {
+ return fmt.Errorf("connect recv error: %s", err)
+ }
+ if err := stream.Send(&greet.GreetStreamResponse{Greeting: "hello " + req.Name}); err != nil {
+ return fmt.Errorf("connect send error: %s", err)
+ }
+ }
+}
+
+func (srv *GreetConnectServer) GreetClientStream(ctx context.Context, stream greettriple.GreetService_GreetClientStreamServer) (*greet.GreetClientStreamResponse, error) {
+ var reqs []string
+ for stream.Recv() {
+ reqs = append(reqs, stream.Msg().Name)
+ }
+ if stream.Err() != nil && !errors.Is(stream.Err(), io.EOF) {
+ logger.Errorf("ClientStream unexpected err: %s", stream.Err())
+ }
+ resp := &greet.GreetClientStreamResponse{
+ Greeting: "Hello" + strings.Join(reqs, ","),
+ }
+
+ return resp, nil
+}
+
+func (srv *GreetConnectServer) GreetServerStream(ctx context.Context, req *greet.GreetServerStreamRequest, stream greettriple.GreetService_GreetServerStreamServer) error {
+ for i := 0; i < 5; i++ {
+ if err := stream.Send(&greet.GreetServerStreamResponse{Greeting: "Hello" + req.Name}); err != nil {
+ logger.Errorf("ServerStream unexpected err: %s", err)
+ }
+ }
+ return nil
+}
+
+func main() {
+ pro, err := provider.NewProvider()
+ if err != nil {
+ panic(err)
+ }
+ if err := greettriple.ProvideGreetServiceHandler(pro, &GreetConnectServer{}); err != nil {
+ panic(err)
+ }
+ select {}
+}
diff --git a/protocol/triple/protoc-gen-triple/main.go b/protocol/triple/protoc-gen-triple/main.go
new file mode 100644
index 000000000..3e1eb681f
--- /dev/null
+++ b/protocol/triple/protoc-gen-triple/main.go
@@ -0,0 +1,838 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// protoc-gen-triple is a plugin for the Protobuf compiler that generates
+// Go code. To use it, build this program and make it available on your PATH as
+// protoc-gen-triple.
+//
+// The 'triple' suffix becomes part of the arguments for the Protobuf
+// compiler. To generate the base Go types and Connect code using protoc:
+//
+// protoc --go_out=gen --triple_out=gen path/to/file.proto
+//
+// With [buf], your buf.gen.yaml will look like this:
+//
+// version: v1
+// plugins:
+// - name: go
+// out: gen
+// - name: triple
+// out: gen
+//
+// This generates service definitions for the Protobuf types and services
+// defined by file.proto. If file.proto defines the foov1 Protobuf package, the
+// invocations above will write output to:
+//
+// gen/path/to/file.pb.go
+// gen/path/to/connectfoov1/file.connect.go
+//
+// [buf]: https://buf.build
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+ "unicode/utf8"
+)
+
+import (
+ "google.golang.org/protobuf/compiler/protogen"
+
+ "google.golang.org/protobuf/reflect/protoreflect"
+
+ "google.golang.org/protobuf/types/descriptorpb"
+ "google.golang.org/protobuf/types/pluginpb"
+)
+
+import (
+ tri "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+)
+
+const (
+ contextPackage = protogen.GoImportPath("context")
+ errorsPackage = protogen.GoImportPath("errors")
+ httpPackage = protogen.GoImportPath("net/http")
+ stringsPackage = protogen.GoImportPath("strings")
+ triplePackage = protogen.GoImportPath("dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol")
+ consumerPackage = protogen.GoImportPath("dubbo.apache.org/dubbo-go/v3/consumer")
+ dubboProtocolPackage = protogen.GoImportPath("dubbo.apache.org/dubbo-go/v3/protocol")
+ invocationPackage = protogen.GoImportPath("dubbo.apache.org/dubbo-go/v3/protocol/invocation")
+
+ generatedFilenameExtension = ".triple.go"
+ generatedPackageSuffix = "triple"
+
+ usage = "See https://connect.build/docs/go/getting-started to learn how to use this plugin.\n\nFlags:\n -h, --help\tPrint this help and exit.\n --version\tPrint the version and exit."
+
+ commentWidth = 97 // leave room for "// "
+
+ // To propagate top-level comments, we need the field number of the syntax
+ // declaration and the package name in the file descriptor.
+ protoSyntaxFieldNum = 12
+ protoPackageFieldNum = 2
+)
+
+func main() {
+ if len(os.Args) == 2 && os.Args[1] == "--version" {
+ fmt.Fprintln(os.Stdout, tri.Version)
+ os.Exit(0)
+ }
+ if len(os.Args) == 2 && (os.Args[1] == "-h" || os.Args[1] == "--help") {
+ fmt.Fprintln(os.Stdout, usage)
+ os.Exit(0)
+ }
+ if len(os.Args) != 1 {
+ fmt.Fprintln(os.Stderr, usage)
+ os.Exit(1)
+ }
+ protogen.Options{}.Run(
+ func(plugin *protogen.Plugin) error {
+ plugin.SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)
+ for _, file := range plugin.Files {
+ if file.Generate {
+ generate(plugin, file)
+ }
+ }
+ return nil
+ },
+ )
+}
+
+func needsWithIdempotency(file *protogen.File) bool {
+ for _, service := range file.Services {
+ for _, method := range service.Methods {
+ if methodIdempotency(method) != tri.IdempotencyUnknown {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+func generate(plugin *protogen.Plugin, file *protogen.File) {
+ if len(file.Services) == 0 {
+ return
+ }
+ file.GoPackageName += generatedPackageSuffix
+
+ generatedFilenamePrefixToSlash := filepath.ToSlash(file.GeneratedFilenamePrefix)
+ file.GeneratedFilenamePrefix = path.Join(
+ path.Dir(generatedFilenamePrefixToSlash),
+ string(file.GoPackageName),
+ path.Base(generatedFilenamePrefixToSlash),
+ )
+ generatedFile := plugin.NewGeneratedFile(
+ file.GeneratedFilenamePrefix+generatedFilenameExtension,
+ protogen.GoImportPath(path.Join(
+ string(file.GoImportPath),
+ string(file.GoPackageName),
+ )),
+ )
+ generatedFile.Import(file.GoImportPath)
+ generatePreamble(generatedFile, file)
+ generateServiceNameConstants(generatedFile, file.Services)
+ for _, service := range file.Services {
+ generateService(generatedFile, service)
+ }
+}
+
+func generatePreamble(g *protogen.GeneratedFile, file *protogen.File) {
+ syntaxPath := protoreflect.SourcePath{protoSyntaxFieldNum}
+ syntaxLocation := file.Desc.SourceLocations().ByPath(syntaxPath)
+ for _, comment := range syntaxLocation.LeadingDetachedComments {
+ leadingComments(g, protogen.Comments(comment), false /* deprecated */)
+ }
+ g.P()
+ leadingComments(g, protogen.Comments(syntaxLocation.LeadingComments), false /* deprecated */)
+ g.P()
+
+ g.P("// Code generated by ", filepath.Base(os.Args[0]), ". DO NOT EDIT.")
+ g.P("//")
+ if file.Proto.GetOptions().GetDeprecated() {
+ wrapComments(g, file.Desc.Path(), " is a deprecated file.")
+ } else {
+ g.P("// Source: ", file.Desc.Path())
+ }
+ g.P()
+
+ pkgPath := protoreflect.SourcePath{protoPackageFieldNum}
+ pkgLocation := file.Desc.SourceLocations().ByPath(pkgPath)
+ for _, comment := range pkgLocation.LeadingDetachedComments {
+ leadingComments(g, protogen.Comments(comment), false /* deprecated */)
+ }
+ g.P()
+ leadingComments(g, protogen.Comments(pkgLocation.LeadingComments), false /* deprecated */)
+
+ g.P("package ", file.GoPackageName)
+ g.P()
+ wrapComments(g, "This is a compile-time assertion to ensure that this generated file ",
+ "and the connect package are compatible. If you get a compiler error that this constant ",
+ "is not defined, this code was generated with a version of connect newer than the one ",
+ "compiled into your binary. You can fix the problem by either regenerating this code ",
+ "with an older version of connect or updating the connect version compiled into your binary.")
+ if needsWithIdempotency(file) {
+ g.P("const _ = ", triplePackage.Ident("IsAtLeastVersion1_6_0"))
+ } else {
+ g.P("const _ = ", triplePackage.Ident("IsAtLeastVersion0_1_0"))
+ }
+ g.P()
+}
+
+func generateServiceNameConstants(g *protogen.GeneratedFile, services []*protogen.Service) {
+ var numMethods int
+ g.P("const (")
+ for _, service := range services {
+ constName := fmt.Sprintf("%sName", service.Desc.Name())
+ wrapComments(g, constName, " is the fully-qualified name of the ",
+ service.Desc.Name(), " service.")
+ g.P(constName, ` = "`, service.Desc.FullName(), `"`)
+ numMethods += len(service.Methods)
+ }
+ g.P(")")
+ g.P()
+
+ if numMethods == 0 {
+ return
+ }
+ wrapComments(g, "These constants are the fully-qualified names of the RPCs defined in this package. ",
+ "They're exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route.")
+ g.P("//")
+ wrapComments(g, "Note that these are different from the fully-qualified method names used by ",
+ "google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to ",
+ "reflection-formatted method names, remove the leading slash and convert the ",
+ "remaining slash to a period.")
+ g.P("const (")
+ for _, service := range services {
+ for _, method := range service.Methods {
+ // The runtime exposes this value as Spec.Procedure, so we should use the
+ // same term here.
+ wrapComments(g, procedureConstName(method), " is the fully-qualified name of the ",
+ service.Desc.Name(), "'s ", method.Desc.Name(), " RPC.")
+ g.P(procedureConstName(method), ` = "`, fmt.Sprintf("/%s/%s", service.Desc.FullName(), method.Desc.Name()), `"`)
+ }
+ }
+ g.P(")")
+ g.P()
+}
+
+func generateService(g *protogen.GeneratedFile, service *protogen.Service) {
+ names := newNames(service)
+ generateClientInterface(g, service, names)
+ generateClientImplementation(g, service, names)
+ //generateDubboClientApi(g, service, names)
+ generateServerInterface(g, service, names)
+ generateServerConstructor(g, service, names)
+ generateDubboProviderBase(g, service, names)
+ generateUnimplementedServerImplementation(g, service, names)
+}
+
+func generateClientInterface(g *protogen.GeneratedFile, service *protogen.Service, names names) {
+ wrapComments(g, names.Client, " is a client for the ", service.Desc.FullName(), " service.")
+ if isDeprecatedService(service) {
+ g.P("//")
+ deprecated(g)
+ }
+ g.Annotate(names.Client, service.Location)
+ g.P("type ", names.Client, " interface {")
+ for _, method := range service.Methods {
+ g.Annotate(names.Client+"."+method.GoName, method.Location)
+ leadingComments(
+ g,
+ method.Comments.Leading,
+ isDeprecatedMethod(method),
+ )
+ g.P(clientSignature(g, method, true /* named */))
+ }
+ g.P("}")
+ g.P()
+}
+
+func generateClientImplementation(g *protogen.GeneratedFile, service *protogen.Service, names names) {
+ // Client constructor.
+ wrapComments(g, names.ClientConstructor, " constructs a client for the ", service.Desc.FullName(),
+ " service. By default, it uses the Connect protocol with the binary Protobuf Codec, ",
+ "asks for gzipped responses, and sends uncompressed requests. ",
+ "To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or ",
+ "connect.WithGRPCWeb() options.")
+ g.P("//")
+ wrapComments(g, "The URL supplied here should be the base URL for the Connect or gRPC server ",
+ "(for example, http://api.acme.com or https://acme.com/grpc).")
+ if isDeprecatedService(service) {
+ g.P("//")
+ deprecated(g)
+ }
+ methodsStr := "[]string{"
+ for i, method := range service.Methods {
+ if i != 0 {
+ methodsStr += " ,"
+ }
+ methodsStr += "\"" + method.GoName + "\""
+ }
+ methodsStr += "}"
+ g.P("func ", names.ClientConstructor, " (con *", consumerPackage.Ident("Consumer"), ") (", names.Client, ", error) {")
+ g.P("if err := con.Assemble(\"", service.Desc.FullName(), "\", ", methodsStr, ", nil); err != nil {")
+ g.P("return nil, err")
+ g.P("}")
+ g.P("return &", names.ClientImpl, "{")
+ g.P("con: con,")
+ g.P("}, nil")
+ g.P("}")
+ g.P()
+
+ // Client struct.
+ wrapComments(g, names.ClientImpl, " implements ", names.Client, ".")
+ g.P("type ", names.ClientImpl, " struct {")
+ g.P("con *", g.QualifiedGoIdent(consumerPackage.Ident("Consumer")))
+ //for _, method := range service.Methods {
+ // g.P(unexport(method.GoName), " *", triplePackage.Ident("Client"),
+ // "[", method.Input.GoIdent, ", ", method.Output.GoIdent, "]")
+ //}
+ g.P("}")
+ g.P()
+ for _, method := range service.Methods {
+ generateClientMethod(g, service, method, names)
+ }
+}
+
+func generateClientMethod(g *protogen.GeneratedFile, service *protogen.Service, method *protogen.Method, names names) {
+ receiver := names.ClientImpl
+ isStreamingClient := method.Desc.IsStreamingClient()
+ isStreamingServer := method.Desc.IsStreamingServer()
+ //wrapComments(g, method.GoName, " calls ", method.Desc.FullName(), ".")
+ if isDeprecatedMethod(method) {
+ g.P("//")
+ deprecated(g)
+ }
+ g.P("func (c *", receiver, ") ", clientSignature(g, method, true /* named */), " {")
+
+ switch {
+ case isStreamingClient && !isStreamingServer:
+ g.P("stream, err := c.con.ConsumeClientStream(ctx, \"", service.Desc.FullName(), "\", \"", method.GoName, "\", opts...)")
+ g.P("if err != nil {")
+ g.P("return nil, err")
+ g.P("}")
+ g.P("rawStream := stream.(*", g.QualifiedGoIdent(triplePackage.Ident("ClientStreamForClient")), ")")
+ g.P("return rawStream, nil")
+ case !isStreamingClient && isStreamingServer:
+ g.P("triReq := ", triplePackage.Ident("NewRequest(req)"))
+ g.P("stream, err := c.con.ConsumeServerStream(ctx, triReq, \"", service.Desc.FullName(), "\", \"", method.GoName, "\", opts...)")
+ g.P("if err != nil {")
+ g.P("return nil, err")
+ g.P("}")
+ g.P("rawStream := stream.(*", g.QualifiedGoIdent(triplePackage.Ident("ServerStreamForClient")), ")")
+ g.P("return rawStream, nil")
+ case isStreamingClient && isStreamingServer:
+ g.P("stream, err := c.con.ConsumeBidiStream(ctx, \"", service.Desc.FullName(), "\", \"", method.GoName, "\", opts...)")
+ g.P("if err != nil {")
+ g.P("return nil, err")
+ g.P("}")
+ g.P("rawStream := stream.(*", g.QualifiedGoIdent(triplePackage.Ident("BidiStreamForClient")), ")")
+ g.P("return rawStream, nil")
+ default:
+ g.P("triReq := ", triplePackage.Ident("NewRequest(req)"))
+ g.P("resp := new(", g.QualifiedGoIdent(method.Output.GoIdent), ")")
+ g.P("triResp := ", triplePackage.Ident("NewResponse(resp)"))
+ g.P("if err := c.con.ConsumeUnary(ctx, triReq, triResp, \"", service.Desc.FullName(), "\", \"", method.GoName, "\", opts...); err != nil {")
+ g.P("return nil, err")
+ g.P("}")
+ g.P("return resp, nil")
+ }
+ g.P("}")
+ g.P()
+}
+
+func clientSignature(g *protogen.GeneratedFile, method *protogen.Method, named bool) string {
+ reqName := "req"
+ ctxName := "ctx"
+ if !named {
+ reqName, ctxName = "", ""
+ }
+ if method.Desc.IsStreamingClient() && method.Desc.IsStreamingServer() {
+ // bidi streaming
+ return method.GoName + "(" + ctxName + " " + g.QualifiedGoIdent(contextPackage.Ident("Context")) + ", " +
+ "opts ..." + g.QualifiedGoIdent(consumerPackage.Ident("ConsumeOption")) + ") " +
+ "(*" + g.QualifiedGoIdent(triplePackage.Ident("BidiStreamForClient")) +
+ //"[" + g.QualifiedGoIdent(method.Input.GoIdent) + ", " + g.QualifiedGoIdent(method.Output.GoIdent) + "]" +
+ ", error)"
+ }
+ if method.Desc.IsStreamingClient() {
+ // client streaming
+ return method.GoName + "(" + ctxName + " " + g.QualifiedGoIdent(contextPackage.Ident("Context")) + ", " +
+ "opts ..." + g.QualifiedGoIdent(consumerPackage.Ident("ConsumeOption")) + ") " +
+ "(*" + g.QualifiedGoIdent(triplePackage.Ident("ClientStreamForClient")) +
+ //"[" + g.QualifiedGoIdent(method.Input.GoIdent) + ", " + g.QualifiedGoIdent(method.Output.GoIdent) + "]" +
+ ", error)"
+ }
+ if method.Desc.IsStreamingServer() {
+ return method.GoName + "(" + ctxName + " " + g.QualifiedGoIdent(contextPackage.Ident("Context")) +
+ ", " + reqName + " *" + g.QualifiedGoIdent(method.Input.GoIdent) + ", " +
+ "opts ..." + g.QualifiedGoIdent(consumerPackage.Ident("ConsumeOption")) + ") " +
+ "(*" + g.QualifiedGoIdent(triplePackage.Ident("ServerStreamForClient")) +
+ //"[" + g.QualifiedGoIdent(method.Output.GoIdent) + "]" +
+ ", error)"
+ }
+ // unary; symmetric so we can re-use server templating
+ return method.GoName + clientSignatureParams(g, method, named)
+}
+
+func generateDubboClientApi(g *protogen.GeneratedFile, service *protogen.Service, names names) {
+ dubboImpl := names.Client + "Impl"
+ wrapComments(g, dubboImpl, " is the Dubbo client api for the ", service.Desc.FullName(), " service.")
+ g.P("type ", dubboImpl, " struct {")
+ for _, method := range service.Methods {
+ g.Annotate(names.Client+"."+method.GoName, method.Location)
+ leadingComments(
+ g,
+ method.Comments.Leading,
+ isDeprecatedMethod(method),
+ )
+ g.P(dubboClientField(g, method, true))
+ }
+ g.P("}")
+ g.P("")
+
+ handlerOption := triplePackage.Ident("ClientOption")
+ wrapComments(g, "GetDubboStub is used for Dubbo to initialize client interface")
+ g.P("func (c *", dubboImpl, ") GetDubboStub(httpClient ", triplePackage.Ident("HTTPClient"),
+ ", baseURL string, opts ...", handlerOption, ") ", names.Client, " {")
+ g.P("return ", names.ClientConstructor, "(httpClient, baseURL, opts...)")
+ g.P("}")
+ g.P()
+
+ wrapComments(g, "Reference is used for Dubbo consumer to refer this service")
+ g.P("func (c *", dubboImpl, ") Reference() string {")
+ g.P("return \"", service.Desc.FullName(), "\"")
+ g.P("}")
+}
+
+func dubboClientField(g *protogen.GeneratedFile, method *protogen.Method, named bool) string {
+ reqName := "req"
+ ctxName := "ctx"
+ if !named {
+ reqName, ctxName = "", ""
+ }
+ if method.Desc.IsStreamingClient() && method.Desc.IsStreamingServer() {
+ // bidi streaming
+ return method.GoName + " func(" + ctxName + " " + g.QualifiedGoIdent(contextPackage.Ident("Context")) + ") " +
+ "(*" + g.QualifiedGoIdent(triplePackage.Ident("BidiStreamForClient")) +
+ "[" + g.QualifiedGoIdent(method.Input.GoIdent) + ", " + g.QualifiedGoIdent(method.Output.GoIdent) + "]" +
+ ", error)"
+ }
+ if method.Desc.IsStreamingClient() {
+ // client streaming
+ return method.GoName + " func(" + ctxName + " " + g.QualifiedGoIdent(contextPackage.Ident("Context")) + ") " +
+ "(*" + g.QualifiedGoIdent(triplePackage.Ident("ClientStreamForClient")) +
+ "[" + g.QualifiedGoIdent(method.Input.GoIdent) + ", " + g.QualifiedGoIdent(method.Output.GoIdent) + "]" +
+ ", error)"
+ }
+ if method.Desc.IsStreamingServer() {
+ return method.GoName + " func(" + ctxName + " " + g.QualifiedGoIdent(contextPackage.Ident("Context")) +
+ ", " + reqName + " *" + g.QualifiedGoIdent(triplePackage.Ident("Request")) + "[" +
+ g.QualifiedGoIdent(method.Input.GoIdent) + "]) " +
+ "(*" + g.QualifiedGoIdent(triplePackage.Ident("ServerStreamForClient")) +
+ "[" + g.QualifiedGoIdent(method.Output.GoIdent) + "]" +
+ ", error)"
+ }
+ // unary; symmetric so we can re-use server templating
+ return method.GoName + " func" + serverSignatureParams(g, method, named)
+}
+
+func generateServerInterface(g *protogen.GeneratedFile, service *protogen.Service, names names) {
+ wrapComments(g, names.Server, " is an implementation of the ", service.Desc.FullName(), " service.")
+ if isDeprecatedService(service) {
+ g.P("//")
+ deprecated(g)
+ }
+ g.Annotate(names.Server, service.Location)
+ g.P("type ", names.Server, " interface {")
+ for _, method := range service.Methods {
+ leadingComments(
+ g,
+ method.Comments.Leading,
+ isDeprecatedMethod(method),
+ )
+ g.Annotate(names.Server+"."+method.GoName, method.Location)
+ g.P(serverSignature(g, method))
+ }
+ g.P("}")
+ g.P()
+}
+
+func generateServerConstructor(g *protogen.GeneratedFile, service *protogen.Service, names names) {
+ wrapComments(g, names.ServerConstructor, " builds an HTTP handler from the service implementation.",
+ " It returns the path on which to mount the handler and the handler itself.")
+ g.P("//")
+ wrapComments(g, "By default, handlers support the Connect, gRPC, and gRPC-Web protocols with ",
+ "the binary Protobuf and JSON codecs. They also support gzip compression.")
+ if isDeprecatedService(service) {
+ g.P("//")
+ deprecated(g)
+ }
+ handlerOption := triplePackage.Ident("HandlerOption")
+ g.P("func ", names.ServerConstructor, "(svc ", names.Server, ", opts ...", handlerOption,
+ ") (string, ", httpPackage.Ident("Handler"), ") {")
+ g.P("mux := ", httpPackage.Ident("NewServeMux"), "()")
+ for _, method := range service.Methods {
+ isStreamingServer := method.Desc.IsStreamingServer()
+ isStreamingClient := method.Desc.IsStreamingClient()
+ idempotency := methodIdempotency(method)
+ switch {
+ case isStreamingClient && !isStreamingServer:
+ g.P(`mux.Handle(`, procedureConstName(method), `, `, triplePackage.Ident("NewClientStreamHandler"), "(")
+ case !isStreamingClient && isStreamingServer:
+ g.P(`mux.Handle(`, procedureConstName(method), `, `, triplePackage.Ident("NewServerStreamHandler"), "(")
+ case isStreamingClient && isStreamingServer:
+ g.P(`mux.Handle(`, procedureConstName(method), `, `, triplePackage.Ident("NewBidiStreamHandler"), "(")
+ default:
+ g.P(`mux.Handle(`, procedureConstName(method), `, `, triplePackage.Ident("NewUnaryHandler"), "(")
+ }
+ g.P(procedureConstName(method), `,`)
+ g.P("svc.", method.GoName, ",")
+ switch idempotency {
+ case tri.IdempotencyNoSideEffects:
+ g.P(triplePackage.Ident("WithIdempotency"), "(", triplePackage.Ident("IdempotencyNoSideEffects"), "),")
+ g.P(triplePackage.Ident("WithHandlerOptions"), "(opts...),")
+ case tri.IdempotencyIdempotent:
+ g.P(triplePackage.Ident("WithIdempotency"), "(", triplePackage.Ident("IdempotencyIdempotent"), "),")
+ g.P(triplePackage.Ident("WithHandlerOptions"), "(opts...),")
+ case tri.IdempotencyUnknown:
+ g.P("opts...,")
+ }
+ g.P("))")
+ }
+ g.P(`return "/`, reflectionName(service), `/", mux`)
+ g.P("}")
+ g.P()
+}
+
+func generateDubboProviderBase(g *protogen.GeneratedFile, service *protogen.Service, names names) {
+ base := names.Base + "ProviderBase"
+ wrapComments(g, base, " is the Dubbo handler base embedded into user implementation api for the ", service.Desc.FullName(), " service.")
+ g.P("type ", base, " struct {")
+ g.P("proxyImpl ", dubboProtocolPackage.Ident("Invoker"))
+ g.P("}")
+ g.P("")
+
+ wrapComments(g, "SetProxyImpl sets proxy.")
+ g.P("func (s *", base, ") SetProxyImpl(impl ", dubboProtocolPackage.Ident("Invoker"), ") {")
+ g.P("s.proxyImpl = impl")
+ g.P("}")
+ g.P("")
+
+ wrapComments(g, "GetProxyImpl gets proxy.")
+ g.P("func (s *", base, ") GetProxyImpl() ", dubboProtocolPackage.Ident("Invoker"), " {")
+ g.P("return s.proxyImpl")
+ g.P("}")
+ g.P("")
+
+ g.P("func (s *", base, ") BuildHandler(impl interface{}, opts ...", triplePackage.Ident("HandlerOption"), ") (string, ", httpPackage.Ident("Handler"), ") {")
+ g.P("_, ok := impl.(", names.Server, ")")
+ g.P("if !ok {")
+ g.P("panic(\"impl has not implemented ", names.Server, "\")")
+ g.P("}")
+ g.P("mux := ", httpPackage.Ident("NewServeMux"), "()")
+ for _, method := range service.Methods {
+ var invocationArgs []string
+ var twoReturnValsFlag bool
+ isStreamingServer := method.Desc.IsStreamingServer()
+ isStreamingClient := method.Desc.IsStreamingClient()
+ idempotency := methodIdempotency(method)
+ switch {
+ case isStreamingClient && !isStreamingServer:
+ g.P(`mux.Handle(`, procedureConstName(method), `, `, triplePackage.Ident("NewClientStreamHandler"), "(")
+ g.P(procedureConstName(method), `,`)
+ g.P("func(ctx ", contextPackage.Ident("Context"), ", stream *", triplePackage.Ident("ClientStream"),
+ "[", g.QualifiedGoIdent(method.Input.GoIdent), "]) (*", triplePackage.Ident("Response"),
+ "[", g.QualifiedGoIdent(method.Output.GoIdent), "], error) {")
+ invocationArgs = append(invocationArgs, "stream")
+ twoReturnValsFlag = true
+ case !isStreamingClient && isStreamingServer:
+ g.P(`mux.Handle(`, procedureConstName(method), `, `, triplePackage.Ident("NewServerStreamHandler"), "(")
+ g.P(procedureConstName(method), `,`)
+ g.P("func(ctx ", contextPackage.Ident("Context"), ", req *", triplePackage.Ident("Request"),
+ "[", g.QualifiedGoIdent(method.Input.GoIdent), "], stream *", triplePackage.Ident("ServerStream"),
+ "[", g.QualifiedGoIdent(method.Output.GoIdent), "]) error {")
+ invocationArgs = append(invocationArgs, "req", "stream")
+ case isStreamingClient && isStreamingServer:
+ g.P(`mux.Handle(`, procedureConstName(method), `, `, triplePackage.Ident("NewBidiStreamHandler"), "(")
+ g.P(procedureConstName(method), `,`)
+ g.P("func(ctx ", contextPackage.Ident("Context"), ", stream *", triplePackage.Ident("BidiStream"),
+ "[", g.QualifiedGoIdent(method.Input.GoIdent), ", ", g.QualifiedGoIdent(method.Output.GoIdent), "]) error {")
+ invocationArgs = append(invocationArgs, "stream")
+ default:
+ g.P(`mux.Handle(`, procedureConstName(method), `, `, triplePackage.Ident("NewUnaryHandler"), "(")
+ g.P(procedureConstName(method), `,`)
+ g.P("func(ctx ", contextPackage.Ident("Context"), ", req *", triplePackage.Ident("Request"),
+ "[", g.QualifiedGoIdent(method.Input.GoIdent), "]) (*", triplePackage.Ident("Response"),
+ "[", g.QualifiedGoIdent(method.Output.GoIdent), "], error) {")
+ invocationArgs = append(invocationArgs, "req")
+ twoReturnValsFlag = true
+ }
+ g.P("var args []interface{}")
+ var args string
+ for _, arg := range invocationArgs {
+ args += ", " + arg
+ }
+ g.P("args = append(args", args, ")")
+ g.P("invo := ", invocationPackage.Ident("NewRPCInvocation("), "\"", method.GoName, "\"", ", args, nil)")
+ g.P("res := s.proxyImpl.Invoke(ctx, invo)")
+ if twoReturnValsFlag {
+ g.P("return res.Result().(*", triplePackage.Ident("Response"), "[", g.QualifiedGoIdent(method.Output.GoIdent),
+ "]), res.Error()")
+ } else {
+ g.P("return res.Error()")
+ }
+ g.P("},")
+ switch idempotency {
+ case tri.IdempotencyNoSideEffects:
+ g.P(triplePackage.Ident("WithIdempotency"), "(", triplePackage.Ident("IdempotencyNoSideEffects"), "),")
+ g.P(triplePackage.Ident("WithHandlerOptions"), "(opts...),")
+ case tri.IdempotencyIdempotent:
+ g.P(triplePackage.Ident("WithIdempotency"), "(", triplePackage.Ident("IdempotencyIdempotent"), "),")
+ g.P(triplePackage.Ident("WithHandlerOptions"), "(opts...),")
+ case tri.IdempotencyUnknown:
+ g.P("opts...,")
+ }
+ g.P("))")
+ }
+ g.P(`return "/`, reflectionName(service), `/", mux`)
+ g.P("}")
+ g.P("")
+
+ g.P("func (s *", base, ") Reference() string {")
+ g.P("return \"", service.Desc.FullName(), "\"")
+ g.P("}")
+}
+
+func generateUnimplementedServerImplementation(g *protogen.GeneratedFile, service *protogen.Service, names names) {
+ wrapComments(g, names.UnimplementedServer, " returns CodeUnimplemented from all methods.")
+ g.P("type ", names.UnimplementedServer, " struct {}")
+ g.P()
+ for _, method := range service.Methods {
+ g.P("func (", names.UnimplementedServer, ") ", serverSignature(g, method), "{")
+ if method.Desc.IsStreamingServer() {
+ g.P("return ", triplePackage.Ident("NewError"), "(",
+ triplePackage.Ident("CodeUnimplemented"), ", ", errorsPackage.Ident("New"),
+ `("`, method.Desc.FullName(), ` is not implemented"))`)
+ } else {
+ g.P("return nil, ", triplePackage.Ident("NewError"), "(",
+ triplePackage.Ident("CodeUnimplemented"), ", ", errorsPackage.Ident("New"),
+ `("`, method.Desc.FullName(), ` is not implemented"))`)
+ }
+ g.P("}")
+ g.P()
+ }
+ g.P()
+}
+
+func serverSignature(g *protogen.GeneratedFile, method *protogen.Method) string {
+ return method.GoName + serverSignatureParams(g, method, false /* named */)
+}
+
+func clientSignatureParams(g *protogen.GeneratedFile, method *protogen.Method, named bool) string {
+ ctxName := "ctx "
+ reqName := "req "
+ streamName := "stream "
+ if !named {
+ ctxName, reqName, streamName = "", "", ""
+ }
+ if method.Desc.IsStreamingClient() && method.Desc.IsStreamingServer() {
+ // bidi streaming
+ return "(" + ctxName + g.QualifiedGoIdent(contextPackage.Ident("Context")) + ", " +
+ streamName + "*" + g.QualifiedGoIdent(triplePackage.Ident("BidiStream")) +
+ ") error"
+ }
+ if method.Desc.IsStreamingClient() {
+ // client streaming
+ return "(" + ctxName + g.QualifiedGoIdent(contextPackage.Ident("Context")) + ", " +
+ streamName + "*" + g.QualifiedGoIdent(triplePackage.Ident("ClientStream")) +
+ ") (*" + g.QualifiedGoIdent(triplePackage.Ident("Response")) + " ,error)"
+ }
+ if method.Desc.IsStreamingServer() {
+ // server streaming
+ return "(" + ctxName + g.QualifiedGoIdent(contextPackage.Ident("Context")) +
+ ", " + reqName + "*" + g.QualifiedGoIdent(triplePackage.Ident("Request")) +
+ ", " + streamName + "*" + g.QualifiedGoIdent(triplePackage.Ident("ServerStream")) +
+ ") error"
+ }
+ // unary
+ return "(" + ctxName + g.QualifiedGoIdent(contextPackage.Ident("Context")) +
+ ", " + reqName + "*" + g.QualifiedGoIdent(method.Input.GoIdent) + ", " +
+ "opts ..." + g.QualifiedGoIdent(consumerPackage.Ident("ConsumeOption")) + ") " +
+ "(*" + g.QualifiedGoIdent(method.Output.GoIdent) + ", error)"
+}
+
+func serverSignatureParams(g *protogen.GeneratedFile, method *protogen.Method, named bool) string {
+ ctxName := "ctx "
+ reqName := "req "
+ streamName := "stream "
+ if !named {
+ ctxName, reqName, streamName = "", "", ""
+ }
+ if method.Desc.IsStreamingClient() && method.Desc.IsStreamingServer() {
+ // bidi streaming
+ return "(" + ctxName + g.QualifiedGoIdent(contextPackage.Ident("Context")) + ", " +
+ streamName + "*" + g.QualifiedGoIdent(triplePackage.Ident("BidiStream")) +
+ //"[" + g.QualifiedGoIdent(method.Input.GoIdent) + ", " + g.QualifiedGoIdent(method.Output.GoIdent) + "]" +
+ ") error"
+ }
+ if method.Desc.IsStreamingClient() {
+ // client streaming
+ return "(" + ctxName + g.QualifiedGoIdent(contextPackage.Ident("Context")) + ", " +
+ streamName + "*" + g.QualifiedGoIdent(triplePackage.Ident("ClientStream")) +
+ //"[" + g.QualifiedGoIdent(method.Input.GoIdent) + "]" +
+ ") (*" + g.QualifiedGoIdent(triplePackage.Ident("Response")) + " ,error)"
+ }
+ if method.Desc.IsStreamingServer() {
+ // server streaming
+ return "(" + ctxName + g.QualifiedGoIdent(contextPackage.Ident("Context")) +
+ ", " + reqName + "*" + g.QualifiedGoIdent(triplePackage.Ident("Request")) +
+ ", " + streamName + "*" + g.QualifiedGoIdent(triplePackage.Ident("ServerStream")) +
+ //"[" + g.QualifiedGoIdent(method.Output.GoIdent) + "]" +
+ ") error"
+ }
+ // unary
+ return "(" + ctxName + g.QualifiedGoIdent(contextPackage.Ident("Context")) +
+ ", " + reqName + "*" + g.QualifiedGoIdent(method.Input.GoIdent) + ") " +
+ "(*" + g.QualifiedGoIdent(method.Output.GoIdent) + ", error)"
+}
+
+func procedureConstName(m *protogen.Method) string {
+ return fmt.Sprintf("%s%sProcedure", m.Parent.GoName, m.GoName)
+}
+
+func reflectionName(service *protogen.Service) string {
+ return fmt.Sprintf("%s.%s", service.Desc.ParentFile().Package(), service.Desc.Name())
+}
+
+func isDeprecatedService(service *protogen.Service) bool {
+ serviceOptions, ok := service.Desc.Options().(*descriptorpb.ServiceOptions)
+ return ok && serviceOptions.GetDeprecated()
+}
+
+func isDeprecatedMethod(method *protogen.Method) bool {
+ methodOptions, ok := method.Desc.Options().(*descriptorpb.MethodOptions)
+ return ok && methodOptions.GetDeprecated()
+}
+
+func methodIdempotency(method *protogen.Method) tri.IdempotencyLevel {
+ methodOptions, ok := method.Desc.Options().(*descriptorpb.MethodOptions)
+ if !ok {
+ return tri.IdempotencyUnknown
+ }
+ switch methodOptions.GetIdempotencyLevel() {
+ case descriptorpb.MethodOptions_NO_SIDE_EFFECTS:
+ return tri.IdempotencyNoSideEffects
+ case descriptorpb.MethodOptions_IDEMPOTENT:
+ return tri.IdempotencyIdempotent
+ case descriptorpb.MethodOptions_IDEMPOTENCY_UNKNOWN:
+ return tri.IdempotencyUnknown
+ }
+ return tri.IdempotencyUnknown
+}
+
+// Raggedy comments in the generated code are driving me insane. This
+// word-wrapping function is ruinously inefficient, but it gets the job done.
+func wrapComments(g *protogen.GeneratedFile, elems ...any) {
+ text := &bytes.Buffer{}
+ for _, el := range elems {
+ switch el := el.(type) {
+ case protogen.GoIdent:
+ fmt.Fprint(text, g.QualifiedGoIdent(el))
+ default:
+ fmt.Fprint(text, el)
+ }
+ }
+ words := strings.Fields(text.String())
+ text.Reset()
+ var pos int
+ for _, word := range words {
+ numRunes := utf8.RuneCountInString(word)
+ if pos > 0 && pos+numRunes+1 > commentWidth {
+ g.P("// ", text.String())
+ text.Reset()
+ pos = 0
+ }
+ if pos > 0 {
+ text.WriteRune(' ')
+ pos++
+ }
+ text.WriteString(word)
+ pos += numRunes
+ }
+ if text.Len() > 0 {
+ g.P("// ", text.String())
+ }
+}
+
+func leadingComments(g *protogen.GeneratedFile, comments protogen.Comments, isDeprecated bool) {
+ if comments.String() != "" {
+ g.P(strings.TrimSpace(comments.String()))
+ }
+ if isDeprecated {
+ if comments.String() != "" {
+ g.P("//")
+ }
+ deprecated(g)
+ }
+}
+
+func deprecated(g *protogen.GeneratedFile) {
+ g.P("// Deprecated: do not use.")
+}
+
+func unexport(s string) string {
+ lowercased := strings.ToLower(s[:1]) + s[1:]
+ switch lowercased {
+ // https://go.dev/ref/spec#Keywords
+ case "break", "default", "func", "interface", "select",
+ "case", "defer", "go", "map", "struct",
+ "chan", "else", "goto", "package", "switch",
+ "const", "fallthrough", "if", "range", "type",
+ "continue", "for", "import", "return", "var":
+ return "_" + lowercased
+ default:
+ return lowercased
+ }
+}
+
+type names struct {
+ Base string
+ Client string
+ ClientConstructor string
+ ClientImpl string
+ ClientExposeMethod string
+ Server string
+ ServerConstructor string
+ UnimplementedServer string
+}
+
+func newNames(service *protogen.Service) names {
+ base := service.GoName
+ return names{
+ Base: base,
+ Client: fmt.Sprintf("%sClient", base),
+ ClientConstructor: fmt.Sprintf("New%sClient", base),
+ ClientImpl: fmt.Sprintf("%sClient", unexport(base)),
+ Server: fmt.Sprintf("%sHandler", base),
+ ServerConstructor: fmt.Sprintf("New%sHandler", base),
+ UnimplementedServer: fmt.Sprintf("Unimplemented%sHandler", base),
+ }
+}
diff --git a/protocol/triple/server.go b/protocol/triple/server.go
new file mode 100644
index 000000000..3ac421ce8
--- /dev/null
+++ b/protocol/triple/server.go
@@ -0,0 +1,251 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package triple
+
+import (
+ "context"
+ "crypto/tls"
+ "fmt"
+ "net/http"
+ "path"
+ "sync"
+ "time"
+)
+
+import (
+ "github.com/dubbogo/gost/log/logger"
+
+ "github.com/dustin/go-humanize"
+
+ "golang.org/x/net/http2"
+ "golang.org/x/net/http2/h2c"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/common"
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+ "dubbo.apache.org/dubbo-go/v3/config"
+ "dubbo.apache.org/dubbo-go/v3/protocol"
+ "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
+ proto "dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto"
+ tri "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+)
+
+//// TripleService is implemented by user logic struct wrapping ProviderBase generated by protoc-gen-triple.
+//type TripleService interface {
+// // SetProxyImpl sets proxy. All invocation logics are embedded in impl.
+// SetProxyImpl(impl protocol.Invoker)
+// // GetProxyImpl gets proxy.
+// GetProxyImpl() protocol.Invoker
+// // BuildHandler receives user logic struct and handlerOption defined by triple to create handler.
+// // For now, impl is just used to finish type checking.
+// BuildHandler(impl interface{}, opts ...tri.HandlerOption) (string, http.Handler)
+//}
+// Server is TRIPLE server
+type Server struct {
+ httpServer *http.Server
+}
+
+// NewServer creates a new TRIPLE server
+func NewServer() *Server {
+ return &Server{}
+}
+
+// Start TRIPLE server
+func (s *Server) Start(url *common.URL) {
+ var (
+ addr string
+ err error
+ hanOpts []tri.HandlerOption
+ )
+ addr = url.Location
+ srv := &http.Server{
+ Addr: addr,
+ }
+
+ maxServerRecvMsgSize := constant.DefaultMaxServerRecvMsgSize
+ if recvMsgSize, convertErr := humanize.ParseBytes(url.GetParam(constant.MaxServerRecvMsgSize, "")); convertErr == nil && recvMsgSize != 0 {
+ maxServerRecvMsgSize = int(recvMsgSize)
+ }
+ hanOpts = append(hanOpts, tri.WithReadMaxBytes(maxServerRecvMsgSize))
+
+ maxServerSendMsgSize := constant.DefaultMaxServerSendMsgSize
+ if sendMsgSize, convertErr := humanize.ParseBytes(url.GetParam(constant.MaxServerSendMsgSize, "")); err == convertErr && sendMsgSize != 0 {
+ maxServerSendMsgSize = int(sendMsgSize)
+ }
+ hanOpts = append(hanOpts, tri.WithSendMaxBytes(maxServerSendMsgSize))
+
+ // If global trace instance was set, then server tracer instance
+ // can be get. If not, will return NoopTracer.
+ //tracer := opentracing.GlobalTracer()
+ //serverOpts = append(serverOpts,
+ // grpc.UnaryInterceptor(otgrpc.OpenTracingServerInterceptor(tracer)),
+ // grpc.StreamInterceptor(otgrpc.OpenTracingStreamServerInterceptor(tracer)),
+ // grpc.MaxRecvMsgSize(maxServerRecvMsgSize),
+ // grpc.MaxSendMsgSize(maxServerSendMsgSize),
+ //)
+ var cfg *tls.Config
+ tlsConfig := config.GetRootConfig().TLSConfig
+ if tlsConfig != nil {
+ cfg, err = config.GetServerTlsConfig(&config.TLSConfig{
+ CACertFile: tlsConfig.CACertFile,
+ TLSCertFile: tlsConfig.TLSCertFile,
+ TLSKeyFile: tlsConfig.TLSKeyFile,
+ TLSServerName: tlsConfig.TLSServerName,
+ })
+ if err != nil {
+ return
+ }
+ logger.Infof("Grpc Server initialized the TLSConfig configuration")
+ }
+ srv.TLSConfig = cfg
+
+ // todo:// open tracing
+ hanOpts = append(hanOpts, tri.WithInterceptors())
+ // todo:// move tls config to handleService
+ s.httpServer = srv
+
+ go func() {
+ providerServices := config.GetProviderConfig().Services
+
+ if len(providerServices) == 0 {
+ panic("provider service map is null")
+ }
+ // todo: remove this logic?
+ // wait all exporter ready , then set proxy impl and grpc registerService
+ waitTripleExporter(providerServices)
+ mux := http.NewServeMux()
+ handleService(providerServices, mux)
+ // todo: figure it out this process
+ //reflection.Register(server)
+ // todo: without tls
+ if cfg == nil {
+ srv.Handler = h2c.NewHandler(mux, &http2.Server{})
+ } else {
+ srv.Handler = mux
+ }
+
+ if err = srv.ListenAndServe(); err != nil {
+ logger.Errorf("server serve failed with err: %v", err)
+ }
+ }()
+}
+
+// getSyncMapLen gets sync map len
+func getSyncMapLen(m *sync.Map) int {
+ length := 0
+
+ m.Range(func(_, _ interface{}) bool {
+ length++
+ return true
+ })
+ return length
+}
+
+// waitTripleExporter wait until len(providerServices) = len(ExporterMap)
+func waitTripleExporter(providerServices map[string]*config.ServiceConfig) {
+ t := time.NewTicker(50 * time.Millisecond)
+ defer t.Stop()
+ pLen := len(providerServices)
+ ta := time.NewTimer(10 * time.Second)
+ defer ta.Stop()
+
+ for {
+ select {
+ case <-t.C:
+ mLen := getSyncMapLen(tripleProtocol.ExporterMap())
+ if pLen == mLen {
+ return
+ }
+ case <-ta.C:
+ panic("wait GRPC_NEW exporter timeout when start GRPC_NEW server")
+ }
+ }
+}
+
+// handleService injects invoker and creates handler based on ServiceConfig and provider service.
+func handleService(providerServices map[string]*config.ServiceConfig, mux *http.ServeMux, opts ...tri.HandlerOption) {
+ for key, providerService := range providerServices {
+ service := config.GetProviderService(key)
+ ds, ok := service.(TripleService)
+ if !ok {
+ panic("illegal service type registered")
+ }
+
+ serviceKey := common.ServiceKey(providerService.Interface, providerService.Group, providerService.Version)
+ exporter, _ := tripleProtocol.ExporterMap().Load(serviceKey)
+ if exporter == nil {
+ panic(fmt.Sprintf("no exporter found for servicekey: %v", serviceKey))
+ }
+ invoker := exporter.(protocol.Exporter).GetInvoker()
+ if invoker == nil {
+ panic(fmt.Sprintf("no invoker found for servicekey: %v", serviceKey))
+ }
+
+ // inject invoker, it has all invocation logics
+ ds.SetProxyImpl(invoker)
+ path, handler := ds.BuildHandler(service, opts...)
+ mux.Handle(path, tri.New)
+ mux.Handle(path, handler)
+ }
+}
+
+func handleService2(url *common.URL, mux *http.ServeMux, opts ...tri.HandlerOption) {
+ interfaceName := ""
+ methodNames := []string{}
+ types := []string{}
+ serviceKey := url.ServiceKey()
+ exporter, ok := tripleProtocol.ExporterMap().Load(serviceKey)
+ if !ok {
+ panic(fmt.Sprintf("no exporter found for servicekey: %v", serviceKey))
+ }
+ for i, method := range methodNames {
+ var handler http.Handler
+ procedure := path.Join(interfaceName, method)
+ typ := types[i]
+ switch typ {
+ case constant.CallUnary:
+ handler = tri.NewUnaryHandler(
+ procedure,
+ func(ctx context.Context, req *tri.Request) (*tri.Response, error) {
+ var args []interface{}
+ args = append(args, req.)
+ // provider.Serve()
+ invo := invocation.NewRPCInvocation("Greet", args, nil)
+ res := s.proxyImpl.Invoke(ctx, invo)
+ return res.Result().(*triple_protocol.Response[proto.GreetResponse]), res.Error()
+ },
+ opts...,
+ )
+
+ }
+
+ }
+}
+
+// Stop TRIPLE server
+func (s *Server) Stop() {
+ // todo: process error
+ s.httpServer.Close()
+}
+
+// GracefulStop TRIPLE server
+func (s *Server) GracefulStop() {
+ // todo: process error and use timeout
+ s.httpServer.Shutdown(context.Background())
+}
diff --git a/protocol/triple/triple.go b/protocol/triple/triple.go
new file mode 100644
index 000000000..b429b915f
--- /dev/null
+++ b/protocol/triple/triple.go
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package triple
+
+import (
+ "sync"
+)
+
+import (
+ "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/common"
+ "dubbo.apache.org/dubbo-go/v3/common/extension"
+ "dubbo.apache.org/dubbo-go/v3/protocol"
+)
+
+const (
+ // TRIPLE protocol name
+ TRIPLE = "triple"
+)
+
+var (
+ tripleProtocol *TripleProtocol
+)
+
+func init() {
+ extension.SetProtocol(TRIPLE, GetProtocol)
+}
+
+type TripleProtocol struct {
+ protocol.BaseProtocol
+ serverLock sync.Mutex
+ serverMap map[string]*Server
+}
+
+// Export TRIPLE service for remote invocation
+func (tp *TripleProtocol) Export(invoker protocol.Invoker) protocol.Exporter {
+ url := invoker.GetURL()
+ serviceKey := url.ServiceKey()
+ exporter := NewTripleExporter(serviceKey, invoker, tp.ExporterMap())
+ tp.SetExporterMap(serviceKey, exporter)
+ logger.Infof("[TRIPLE Protocol] Export service: %s", url.String())
+ tp.openServer(url)
+ return exporter
+}
+
+func (tp *TripleProtocol) openServer(url *common.URL) {
+ tp.serverLock.Lock()
+ defer tp.serverLock.Unlock()
+
+ if _, ok := tp.serverMap[url.Location]; ok {
+ return
+ }
+
+ // todo: remove this logic?
+ if _, ok := tp.ExporterMap().Load(url.ServiceKey()); !ok {
+ panic("[GRPC_NEW Protocol]" + url.Key() + "is not existing")
+ }
+
+ srv := NewServer()
+ tp.serverMap[url.Location] = srv
+ srv.Start(url)
+}
+
+// Refer a remote triple service
+func (tp *TripleProtocol) Refer(url *common.URL) protocol.Invoker {
+ //client, err := NewClient(url)
+ //if err != nil {
+ // logger.Warnf("can't dial the server: %s", url.Key())
+ // return nil
+ //}
+ invoker, err := NewTripleInvoker(url)
+ if err != nil {
+ logger.Warnf("can't dial the server: %s", url.Key())
+ return nil
+ }
+ tp.SetInvokers(invoker)
+ logger.Infof("[TRIPLE Protocol] Refer service: %s", url.String())
+ return invoker
+}
+
+func (tp *TripleProtocol) Destroy() {
+ logger.Infof("GrpcProtocol destroy.")
+
+ tp.serverLock.Lock()
+ defer tp.serverLock.Unlock()
+ for key, server := range tp.serverMap {
+ delete(tp.serverMap, key)
+ server.GracefulStop()
+ }
+
+ tp.BaseProtocol.Destroy()
+}
+
+func NewTripleProtocol() *TripleProtocol {
+ return &TripleProtocol{
+ BaseProtocol: protocol.NewBaseProtocol(),
+ serverMap: make(map[string]*Server),
+ }
+}
+
+func GetProtocol() protocol.Protocol {
+ if tripleProtocol == nil {
+ tripleProtocol = NewTripleProtocol()
+ }
+ return tripleProtocol
+}
diff --git a/protocol/triple/triple_exporter.go b/protocol/triple/triple_exporter.go
new file mode 100644
index 000000000..2dd45ad29
--- /dev/null
+++ b/protocol/triple/triple_exporter.go
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package triple
+
+import (
+ "sync"
+)
+
+import (
+ "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/common"
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+ "dubbo.apache.org/dubbo-go/v3/protocol"
+)
+
+// TripleExporter wraps BaseExporter
+type TripleExporter struct {
+ *protocol.BaseExporter
+}
+
+func NewTripleExporter(key string, invoker protocol.Invoker, exporterMap *sync.Map) *TripleExporter {
+ return &TripleExporter{
+ BaseExporter: protocol.NewBaseExporter(key, invoker, exporterMap),
+ }
+}
+
+// UnExport and unregister Triple service from registry and memory.
+func (te *TripleExporter) UnExport() {
+ interfaceName := te.GetInvoker().GetURL().GetParam(constant.InterfaceKey, "")
+ te.BaseExporter.UnExport()
+ // todo: move UnRegister logic to a better place
+ err := common.ServiceMap.UnRegister(interfaceName, TRIPLE, te.GetInvoker().GetURL().ServiceKey())
+ if err != nil {
+ logger.Errorf("[GrpcNewExporter.UnExport] error: %v", err)
+ }
+}
diff --git a/protocol/triple/triple_invoker.go b/protocol/triple/triple_invoker.go
new file mode 100644
index 000000000..4861818bb
--- /dev/null
+++ b/protocol/triple/triple_invoker.go
@@ -0,0 +1,151 @@
+package triple
+
+import (
+ "context"
+ "fmt"
+ "sync"
+)
+
+import (
+ "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/common"
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+ "dubbo.apache.org/dubbo-go/v3/protocol"
+)
+
+type TripleInvoker struct {
+ protocol.BaseInvoker
+ quitOnce sync.Once
+ clientGuard *sync.RWMutex
+ clientManager *clientManager
+}
+
+func (gni *TripleInvoker) setClientManager(cm *clientManager) {
+ gni.clientGuard.Lock()
+ defer gni.clientGuard.Unlock()
+
+ gni.clientManager = cm
+}
+
+func (gni *TripleInvoker) getClientManager() *clientManager {
+ gni.clientGuard.RLock()
+ defer gni.clientGuard.RUnlock()
+
+ return gni.clientManager
+}
+
+// Invoke is used to call client-side method.
+func (ti *TripleInvoker) Invoke(ctx context.Context, invocation protocol.Invocation) protocol.Result {
+ var result protocol.RPCResult
+
+ if !ti.BaseInvoker.IsAvailable() {
+ // Generally, the case will not happen, because the invoker has been removed
+ // from the invoker list before destroy,so no new request will enter the destroyed invoker
+ logger.Warnf("TripleInvoker is destroyed")
+ result.Err = protocol.ErrDestroyedInvoker
+ return &result
+ }
+
+ ti.clientGuard.RLock()
+ defer ti.clientGuard.RUnlock()
+
+ if ti.clientManager == nil {
+ result.Err = protocol.ErrClientClosed
+ return &result
+ }
+ callTypeRaw, ok := invocation.GetAttribute(constant.CallTypeKey)
+ if !ok {
+ panic("Miss CallType to invoke TripleInvoker")
+ }
+ callType, ok := callTypeRaw.(string)
+ if !ok {
+ panic(fmt.Sprintf("CallType should be string, but got %v", callTypeRaw))
+ }
+ inRaw := invocation.ParameterRawValues()
+ inRawLen := len(inRaw)
+ method := invocation.MethodName()
+ switch callType {
+ case constant.CallUnary:
+ if len(inRaw) != 2 {
+ panic(fmt.Sprintf("Wrong parameter Values number for CallUnary, want 2, but got %d", inRawLen))
+ }
+ if err := ti.clientManager.callUnary(ctx, method, inRaw[0], inRaw[1]); err != nil {
+ result.SetError(err)
+ return &result
+ }
+ case constant.CallClientStream:
+ stream, err := ti.clientManager.callClientStream(ctx, method)
+ if err != nil {
+ result.SetError(err)
+ return &result
+ }
+ result.SetResult(stream)
+ case constant.CallServerStream:
+ if inRawLen != 1 {
+ panic(fmt.Sprintf("Wrong parameter Values number for CallServerStream, want 1, but got %d", inRawLen))
+ }
+ stream, err := ti.clientManager.callServerStream(ctx, method, inRaw[0])
+ if err != nil {
+ result.Err = err
+ return &result
+ }
+ result.SetResult(stream)
+ case constant.CallBidiStream:
+ stream, err := ti.clientManager.callBidiStream(ctx, method)
+ if err != nil {
+ result.Err = err
+ return &result
+ }
+ result.SetResult(stream)
+ default:
+ panic(fmt.Sprintf("Unsupported CallType: %s", callType))
+ }
+
+ return &result
+}
+
+// IsAvailable get available status
+func (gni *TripleInvoker) IsAvailable() bool {
+ if gni.getClientManager() != nil {
+ return gni.BaseInvoker.IsAvailable()
+ }
+
+ return false
+}
+
+// IsDestroyed get destroyed status
+func (gni *TripleInvoker) IsDestroyed() bool {
+ if gni.getClientManager() != nil {
+ return gni.BaseInvoker.IsDestroyed()
+ }
+
+ return false
+}
+
+// Destroy will destroy Triple's invoker and client, so it is only called once
+func (ti *TripleInvoker) Destroy() {
+ ti.quitOnce.Do(func() {
+ ti.BaseInvoker.Destroy()
+ if cm := ti.getClientManager(); cm != nil {
+ ti.setClientManager(nil)
+ // todo:// find a better way to destroy these resources
+ cm.close()
+ }
+ })
+}
+
+func NewTripleInvoker(url *common.URL) (*TripleInvoker, error) {
+ cm, err := newClientManager(url)
+ if err != nil {
+ return nil, err
+ }
+ return &TripleInvoker{
+ BaseInvoker: *protocol.NewBaseInvoker(url),
+ quitOnce: sync.Once{},
+ clientGuard: &sync.RWMutex{},
+ clientManager: cm,
+ }, nil
+}
diff --git a/protocol/triple/triple_protocol/Makefile b/protocol/triple/triple_protocol/Makefile
new file mode 100644
index 000000000..a872b47aa
--- /dev/null
+++ b/protocol/triple/triple_protocol/Makefile
@@ -0,0 +1,94 @@
+# See https://tech.davis-hansson.com/p/make/
+SHELL := bash
+.DELETE_ON_ERROR:
+.SHELLFLAGS := -eu -o pipefail -c
+.DEFAULT_GOAL := all
+MAKEFLAGS += --warn-undefined-variables
+MAKEFLAGS += --no-builtin-rules
+MAKEFLAGS += --no-print-directory
+BIN := .tmp/bin
+COPYRIGHT_YEARS := 2021-2023
+LICENSE_IGNORE := --ignore /testdata/
+# Set to use a different compiler. For example, `GO=go1.18rc1 make test`.
+GO ?= go
+
+.PHONY: help
+help: ## Describe useful make targets
+ @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "%-30s %s\n", $$1, $$2}'
+
+.PHONY: all
+all: ## Build, test, and lint (default)
+ $(MAKE) test
+ $(MAKE) lint
+
+.PHONY: clean
+clean: ## Delete intermediate build artifacts
+ @# -X only removes untracked files, -d recurses into directories, -f actually removes files/dirs
+ git clean -Xdf
+
+.PHONY: test
+test: build ## Run unit tests
+ $(GO) test -vet=off -race -cover ./...
+
+.PHONY: build
+build: generate ## Build all packages
+ $(GO) build ./...
+
+.PHONY: install
+install: ## Install all binaries
+ $(GO) install ./...
+
+.PHONY: lint
+lint: $(BIN)/golangci-lint $(BIN)/buf ## Lint Go and protobuf
+ test -z "$$($(BIN)/buf format -d . | tee /dev/stderr)"
+ $(GO) vet ./...
+ $(BIN)/golangci-lint run
+ $(BIN)/buf lint
+ $(BIN)/buf format -d --exit-code
+
+.PHONY: lintfix
+lintfix: $(BIN)/golangci-lint $(BIN)/buf ## Automatically fix some lint errors
+ $(BIN)/golangci-lint run --fix
+ $(BIN)/buf format -w
+
+.PHONY: generate
+generate: $(BIN)/buf $(BIN)/protoc-gen-go $(BIN)/protoc-gen-connect-go $(BIN)/license-header ## Regenerate code and licenses
+ rm -rf internal/gen
+ PATH=$(abspath $(BIN)) $(BIN)/buf generate
+ $(BIN)/license-header \
+ --license-type apache \
+ --copyright-holder "Buf Technologies, Inc." \
+ --year-range "$(COPYRIGHT_YEARS)" $(LICENSE_IGNORE)
+
+.PHONY: upgrade
+upgrade: ## Upgrade dependencies
+ go get -u -t ./... && go mod tidy -v
+
+.PHONY: checkgenerate
+checkgenerate:
+ @# Used in CI to verify that `make generate` doesn't produce a diff.
+ test -z "$$(git status --porcelain | tee /dev/stderr)"
+
+.PHONY: $(BIN)/protoc-gen-connect-go
+$(BIN)/protoc-gen-connect-go:
+ @mkdir -p $(@D)
+ $(GO) build -o $(@) ./cmd/protoc-gen-connect-go
+
+$(BIN)/buf: Makefile
+ @mkdir -p $(@D)
+ GOBIN=$(abspath $(@D)) $(GO) install github.com/bufbuild/buf/cmd/buf@v1.13.1
+
+$(BIN)/license-header: Makefile
+ @mkdir -p $(@D)
+ GOBIN=$(abspath $(@D)) $(GO) install \
+ github.com/bufbuild/buf/private/pkg/licenseheader/cmd/license-header@90fa81df0e9ef86ed505956be1ab1e8ccd49aa52
+
+$(BIN)/golangci-lint: Makefile
+ @mkdir -p $(@D)
+ GOBIN=$(abspath $(@D)) $(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.0
+
+$(BIN)/protoc-gen-go: Makefile go.mod
+ @mkdir -p $(@D)
+ @# The version of protoc-gen-go is determined by the version in go.mod
+ GOBIN=$(abspath $(@D)) $(GO) install google.golang.org/protobuf/cmd/protoc-gen-go
+
diff --git a/protocol/triple/triple_protocol/assert/assert.go b/protocol/triple/triple_protocol/assert/assert.go
new file mode 100644
index 000000000..a1717c8fc
--- /dev/null
+++ b/protocol/triple/triple_protocol/assert/assert.go
@@ -0,0 +1,212 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package assert is a minimal assert package using generics.
+//
+// This prevents connect from needing additional dependencies.
+package assert
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "reflect"
+ "regexp"
+ "testing"
+)
+
+import (
+ "github.com/google/go-cmp/cmp"
+
+ "google.golang.org/protobuf/testing/protocmp"
+)
+
+// Equal asserts that two values are equal.
+func Equal[T any](tb testing.TB, got, want T, options ...Option) bool {
+ tb.Helper()
+ if cmpEqual(got, want) {
+ return true
+ }
+ report(tb, got, want, "assert.Equal", true /* showWant */, options...)
+ return false
+}
+
+// NotEqual asserts that two values aren't equal.
+func NotEqual[T any](tb testing.TB, got, want T, options ...Option) bool {
+ tb.Helper()
+ if !cmpEqual(got, want) {
+ return true
+ }
+ report(tb, got, want, "assert.NotEqual", true /* showWant */, options...)
+ return false
+}
+
+// Nil asserts that the value is nil.
+func Nil(tb testing.TB, got any, options ...Option) bool {
+ tb.Helper()
+ if isNil(got) {
+ return true
+ }
+ report(tb, got, nil, "assert.Nil", false /* showWant */, options...)
+ return false
+}
+
+// NotNil asserts that the value isn't nil.
+func NotNil(tb testing.TB, got any, options ...Option) bool {
+ tb.Helper()
+ if !isNil(got) {
+ return true
+ }
+ report(tb, got, nil, "assert.NotNil", false /* showWant */, options...)
+ return false
+}
+
+// Zero asserts that the value is its type's zero value.
+func Zero[T any](tb testing.TB, got T, options ...Option) bool {
+ tb.Helper()
+ var want T
+ if cmpEqual(got, want) {
+ return true
+ }
+ report(tb, got, want, fmt.Sprintf("assert.Zero (type %T)", got), false /* showWant */, options...)
+ return false
+}
+
+// NotZero asserts that the value is non-zero.
+func NotZero[T any](tb testing.TB, got T, options ...Option) bool {
+ tb.Helper()
+ var want T
+ if !cmpEqual(got, want) {
+ return true
+ }
+ report(tb, got, want, fmt.Sprintf("assert.NotZero (type %T)", got), false /* showWant */, options...)
+ return false
+}
+
+// Match asserts that the value matches a regexp.
+func Match(tb testing.TB, got, want string, options ...Option) bool {
+ tb.Helper()
+ re, err := regexp.Compile(want)
+ if err != nil {
+ tb.Fatalf("invalid regexp %q: %v", want, err)
+ }
+ if re.MatchString(got) {
+ return true
+ }
+ report(tb, got, want, "assert.Match", true /* showWant */, options...)
+ return false
+}
+
+// ErrorIs asserts that "want" is in "got's" error chain. See the standard
+// library's errors package for details on error chains. On failure, output is
+// identical to Equal.
+func ErrorIs(tb testing.TB, got, want error, options ...Option) bool {
+ tb.Helper()
+ if errors.Is(got, want) {
+ return true
+ }
+ report(tb, got, want, "assert.ErrorIs", true /* showWant */, options...)
+ return false
+}
+
+// False asserts that "got" is false.
+func False(tb testing.TB, got bool, options ...Option) bool {
+ tb.Helper()
+ if !got {
+ return true
+ }
+ report(tb, got, false, "assert.False", false /* showWant */, options...)
+ return false
+}
+
+// True asserts that "got" is true.
+func True(tb testing.TB, got bool, options ...Option) bool {
+ tb.Helper()
+ if got {
+ return true
+ }
+ report(tb, got, true, "assert.True", false /* showWant */, options...)
+ return false
+}
+
+// Panics asserts that the function called panics.
+func Panics(tb testing.TB, panicker func(), options ...Option) {
+ tb.Helper()
+ defer func() {
+ if r := recover(); r == nil {
+ report(tb, r, nil, "assert.Panic", false /* showWant */, options...)
+ }
+ }()
+ panicker()
+}
+
+// An Option configures an assertion.
+type Option interface {
+ // Only option we've needed so far is a formatted message, so we can keep
+ // this simple.
+ message() string
+}
+
+// Sprintf adds a user-defined message to the assertion's output. The arguments
+// are passed directly to fmt.Sprintf for formatting.
+//
+// If Sprintf is passed multiple times, only the last message is used.
+func Sprintf(template string, args ...any) Option {
+ return &sprintfOption{fmt.Sprintf(template, args...)}
+}
+
+type sprintfOption struct {
+ msg string
+}
+
+func (o *sprintfOption) message() string {
+ return o.msg
+}
+
+func report(tb testing.TB, got, want any, desc string, showWant bool, options ...Option) {
+ tb.Helper()
+ buffer := &bytes.Buffer{}
+ if len(options) > 0 {
+ buffer.WriteString(options[len(options)-1].message())
+ }
+ buffer.WriteString("\n")
+ fmt.Fprintf(buffer, "assertion:\t%s\n", desc)
+ fmt.Fprintf(buffer, "got:\t%+v\n", got)
+ if showWant {
+ fmt.Fprintf(buffer, "want:\t%+v\n", want)
+ }
+ tb.Fatal(buffer.String())
+}
+
+func isNil(got any) bool {
+ // Simple case, true only when the user directly passes a literal nil.
+ if got == nil {
+ return true
+ }
+ // Possibly more complex. Interfaces are a pair of words: a pointer to a type
+ // and a pointer to a value. Because we're passing got as an interface, it's
+ // likely that we've gotten a non-nil type and a nil value. This makes got
+ // itself non-nil, but the user's code passed a nil value.
+ val := reflect.ValueOf(got)
+ switch val.Kind() {
+ case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+ return val.IsNil()
+ default:
+ return false
+ }
+}
+
+func cmpEqual(got, want any) bool {
+ return cmp.Equal(got, want, protocmp.Transform())
+}
diff --git a/protocol/triple/triple_protocol/assert/assert_test.go b/protocol/triple/triple_protocol/assert/assert_test.go
new file mode 100644
index 000000000..2c8f35a1e
--- /dev/null
+++ b/protocol/triple/triple_protocol/assert/assert_test.go
@@ -0,0 +1,96 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package assert
+
+import (
+ "errors"
+ "fmt"
+ "testing"
+)
+
+func TestAssertions(t *testing.T) {
+ t.Parallel()
+
+ t.Run("equal", func(t *testing.T) {
+ t.Parallel()
+ Equal(t, 1, 1, Sprintf("1 == %d", 1))
+ NotEqual(t, 1, 2)
+ })
+
+ t.Run("nil", func(t *testing.T) {
+ t.Parallel()
+ Nil(t, nil)
+ Nil(t, (*chan int)(nil))
+ Nil(t, (*func())(nil))
+ Nil(t, (*map[int]int)(nil))
+ Nil(t, (*pair)(nil))
+ Nil(t, (*[]int)(nil))
+
+ NotNil(t, make(chan int))
+ NotNil(t, func() {})
+ NotNil(t, any(1))
+ NotNil(t, make(map[int]int))
+ NotNil(t, &pair{})
+ NotNil(t, make([]int, 0))
+
+ NotNil(t, "foo")
+ NotNil(t, 0)
+ NotNil(t, false)
+ NotNil(t, pair{})
+ })
+
+ t.Run("zero", func(t *testing.T) {
+ t.Parallel()
+ var n *int
+ Zero(t, n)
+ var p pair
+ Zero(t, p)
+ var null *pair
+ Zero(t, null)
+ var s []int
+ Zero(t, s)
+ var m map[string]string
+ Zero(t, m)
+ NotZero(t, 3)
+ })
+
+ t.Run("error chain", func(t *testing.T) {
+ t.Parallel()
+ want := errors.New("base error")
+ ErrorIs(t, fmt.Errorf("context: %w", want), want)
+ })
+
+ t.Run("unexported fields", func(t *testing.T) {
+ t.Parallel()
+ // Two pairs differ only in an unexported field.
+ p1 := pair{1, 2}
+ p2 := pair{1, 3}
+ NotEqual(t, p1, p2)
+ })
+
+ t.Run("regexp", func(t *testing.T) {
+ t.Parallel()
+ Match(t, "foobar", `^foo`)
+ })
+
+ t.Run("panics", func(t *testing.T) {
+ t.Parallel()
+ Panics(t, func() { panic("testing") }) //nolint:forbidigo
+ })
+}
+
+type pair struct {
+ First, Second int
+}
diff --git a/protocol/triple/triple_protocol/bench_test.go b/protocol/triple/triple_protocol/bench_test.go
new file mode 100644
index 000000000..28b3ec931
--- /dev/null
+++ b/protocol/triple/triple_protocol/bench_test.go
@@ -0,0 +1,176 @@
+// // Copyright 2021-2023 Buf Technologies, Inc.
+// //
+// // Licensed under the Apache License, Version 2.0 (the "License");
+// // you may not use this file except in compliance with the License.
+// // You may obtain a copy of the License at
+// //
+// // http://www.apache.org/licenses/LICENSE-2.0
+// //
+// // Unless required by applicable law or agreed to in writing, software
+// // distributed under the License is distributed on an "AS IS" BASIS,
+// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// // See the License for the specific language governing permissions and
+// // limitations under the License.
+package triple_protocol_test
+
+//
+//import (
+// "bytes"
+// "compress/gzip"
+// "context"
+// tri "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+// "encoding/json"
+// "io"
+// "net/http"
+// "net/http/httptest"
+// "strings"
+// "testing"
+//
+// "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/assert"
+// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/proto/connect/ping/v1"
+// "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/proto/connect/ping/v1/pingv1connect"
+//)
+//
+//func BenchmarkTriple(b *testing.B) {
+// mux := http.NewServeMux()
+// mux.Handle(
+// pingv1connect.NewPingServiceHandler(
+// &ExamplePingServer{},
+// ),
+// )
+// server := httptest.NewUnstartedServer(mux)
+// server.EnableHTTP2 = true
+// server.StartTLS()
+// defer server.Close()
+//
+// httpClient := server.Client()
+// httpTransport, ok := httpClient.Transport.(*http.Transport)
+// assert.True(b, ok)
+// httpTransport.DisableCompression = true
+//
+// client := pingv1connect.NewPingServiceClient(
+// httpClient,
+// server.URL,
+// tri.WithGRPC(),
+// tri.WithSendGzip(),
+// )
+// twoMiB := strings.Repeat("a", 2*1024*1024)
+// b.ResetTimer()
+//
+// b.Run("unary", func(b *testing.B) {
+// b.RunParallel(func(pb *testing.PB) {
+// for pb.Next() {
+// _, _ = client.Ping(
+// context.Background(),
+// tri.NewRequest(&pingv1.PingRequest{Text: twoMiB}),
+// )
+// }
+// })
+// })
+//}
+//
+//type ping struct {
+// Text string `json:"text"`
+//}
+//
+//func BenchmarkREST(b *testing.B) {
+// handler := func(writer http.ResponseWriter, request *http.Request) {
+// defer request.Body.Close()
+// defer func() {
+// _, err := io.Copy(io.Discard, request.Body)
+// assert.Nil(b, err)
+// }()
+// writer.Header().Set("Content-Type", "application/json")
+// var body io.Reader = request.Body
+// if request.Header.Get("Content-Encoding") == "gzip" {
+// gzipReader, err := gzip.NewReader(body)
+// if err != nil {
+// b.Fatalf("get gzip reader: %v", err)
+// }
+// defer gzipReader.Close()
+// body = gzipReader
+// }
+// var out io.Writer = writer
+// if strings.Contains(request.Header.Get("Accept-Encoding"), "gzip") {
+// writer.Header().Set("Content-Encoding", "gzip")
+// gzipWriter := gzip.NewWriter(writer)
+// defer gzipWriter.Close()
+// out = gzipWriter
+// }
+// raw, err := io.ReadAll(body)
+// if err != nil {
+// b.Fatalf("read body: %v", err)
+// }
+// var pingRequest ping
+// if err := json.Unmarshal(raw, &pingRequest); err != nil {
+// b.Fatalf("json unmarshal: %v", err)
+// }
+// bs, err := json.Marshal(&pingRequest)
+// if err != nil {
+// b.Fatalf("json marshal: %v", err)
+// }
+// _, err = out.Write(bs)
+// assert.Nil(b, err)
+// }
+//
+// server := httptest.NewUnstartedServer(http.HandlerFunc(handler))
+// server.EnableHTTP2 = true
+// server.StartTLS()
+// defer server.Close()
+// twoMiB := strings.Repeat("a", 2*1024*1024)
+// b.ResetTimer()
+//
+// b.Run("unary", func(b *testing.B) {
+// b.RunParallel(func(pb *testing.PB) {
+// for pb.Next() {
+// unaryRESTIteration(b, server.Client(), server.URL, twoMiB)
+// }
+// })
+// })
+//}
+//
+//func unaryRESTIteration(b *testing.B, client *http.Client, url string, text string) {
+// b.Helper()
+// rawRequestBody := bytes.NewBuffer(nil)
+// compressedRequestBody := gzip.NewWriter(rawRequestBody)
+// encoder := json.NewEncoder(compressedRequestBody)
+// if err := encoder.Encode(&ping{text}); err != nil {
+// b.Fatalf("marshal request: %v", err)
+// }
+// compressedRequestBody.Close()
+// request, err := http.NewRequestWithContext(
+// context.Background(),
+// http.MethodPost,
+// url,
+// rawRequestBody,
+// )
+// if err != nil {
+// b.Fatalf("construct request: %v", err)
+// }
+// request.Header.Set("Content-Encoding", "gzip")
+// request.Header.Set("Accept-Encoding", "gzip")
+// request.Header.Set("Content-Type", "application/json")
+// response, err := client.Do(request)
+// if err != nil {
+// b.Fatalf("do request: %v", err)
+// }
+// defer func() {
+// _, err := io.Copy(io.Discard, response.Body)
+// assert.Nil(b, err)
+// }()
+// if response.StatusCode != http.StatusOK {
+// b.Fatalf("response status: %v", response.Status)
+// }
+// uncompressed, err := gzip.NewReader(response.Body)
+// if err != nil {
+// b.Fatalf("uncompress response: %v", err)
+// }
+// raw, err := io.ReadAll(uncompressed)
+// if err != nil {
+// b.Fatalf("read response: %v", err)
+// }
+// var got ping
+// if err := json.Unmarshal(raw, &got); err != nil {
+// b.Fatalf("unmarshal: %v", err)
+// }
+//}
diff --git a/protocol/triple/triple_protocol/buffer_pool.go b/protocol/triple/triple_protocol/buffer_pool.go
new file mode 100644
index 000000000..471c09f8b
--- /dev/null
+++ b/protocol/triple/triple_protocol/buffer_pool.go
@@ -0,0 +1,54 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package triple_protocol
+
+import (
+ "bytes"
+ "sync"
+)
+
+const (
+ initialBufferSize = 512
+ maxRecycleBufferSize = 8 * 1024 * 1024 // if >8MiB, don't hold onto a buffer
+)
+
+type bufferPool struct {
+ sync.Pool
+}
+
+func newBufferPool() *bufferPool {
+ return &bufferPool{
+ Pool: sync.Pool{
+ New: func() any {
+ return bytes.NewBuffer(make([]byte, 0, initialBufferSize))
+ },
+ },
+ }
+}
+
+func (b *bufferPool) Get() *bytes.Buffer {
+ if buf, ok := b.Pool.Get().(*bytes.Buffer); ok {
+ return buf
+ }
+ return bytes.NewBuffer(make([]byte, 0, initialBufferSize))
+}
+
+func (b *bufferPool) Put(buffer *bytes.Buffer) {
+ if buffer.Cap() > maxRecycleBufferSize {
+ return
+ }
+ buffer.Reset()
+ b.Pool.Put(buffer)
+}
diff --git a/protocol/triple/triple_protocol/client.go b/protocol/triple/triple_protocol/client.go
new file mode 100644
index 000000000..d3b57245d
--- /dev/null
+++ b/protocol/triple/triple_protocol/client.go
@@ -0,0 +1,265 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package triple_protocol
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+)
+
+// Client is a reusable, concurrency-safe client for a single procedure.
+// Depending on the procedure's type, use the CallUnary, CallClientStream,
+// CallServerStream, or CallBidiStream method.
+//
+// todo:// modify comment
+// By default, clients use the Connect protocol with the binary Protobuf Codec,
+// ask for gzipped responses, and send uncompressed requests. To use the gRPC
+// or gRPC-Web protocols, use the [WithGRPC] or [WithGRPCWeb] options.
+type Client struct {
+ config *clientConfig
+ callUnary func(context.Context, *Request, *Response) error
+ protocolClient protocolClient
+ err error
+}
+
+// NewClient constructs a new Client.
+func NewClient(httpClient HTTPClient, url string, options ...ClientOption) *Client {
+ client := &Client{}
+ config, err := newClientConfig(url, options)
+ if err != nil {
+ client.err = err
+ return client
+ }
+ client.config = config
+ protocolClient, protocolErr := client.config.Protocol.NewClient(
+ &protocolClientParams{
+ CompressionName: config.RequestCompressionName,
+ CompressionPools: newReadOnlyCompressionPools(
+ config.CompressionPools,
+ config.CompressionNames,
+ ),
+ Codec: config.Codec,
+ Protobuf: config.protobuf(),
+ CompressMinBytes: config.CompressMinBytes,
+ HTTPClient: httpClient,
+ URL: config.URL,
+ BufferPool: config.BufferPool,
+ ReadMaxBytes: config.ReadMaxBytes,
+ SendMaxBytes: config.SendMaxBytes,
+ EnableGet: config.EnableGet,
+ GetURLMaxBytes: config.GetURLMaxBytes,
+ GetUseFallback: config.GetUseFallback,
+ },
+ )
+ if protocolErr != nil {
+ client.err = protocolErr
+ return client
+ }
+ client.protocolClient = protocolClient
+ // Rather than applying unary interceptors along the hot path, we can do it
+ // once at client creation.
+ unarySpec := config.newSpec(StreamTypeUnary)
+ unaryFunc := UnaryFunc(func(ctx context.Context, request AnyRequest, response AnyResponse) error {
+ conn := client.protocolClient.NewConn(ctx, unarySpec, request.Header())
+ // Send always returns an io.EOF unless the error is from the client-side.
+ // We want the user to continue to call Receive in those cases to get the
+ // full error from the server-side.
+ if err := conn.Send(request.Any()); err != nil && !errors.Is(err, io.EOF) {
+ _ = conn.CloseRequest()
+ _ = conn.CloseResponse()
+ return err
+ }
+ if err := conn.CloseRequest(); err != nil {
+ _ = conn.CloseResponse()
+ return err
+ }
+ if err := receiveUnaryResponse(conn, response); err != nil {
+ _ = conn.CloseResponse()
+ return err
+ }
+ return conn.CloseResponse()
+ })
+ if interceptor := config.Interceptor; interceptor != nil {
+ unaryFunc = interceptor.WrapUnary(unaryFunc)
+ }
+ client.callUnary = func(ctx context.Context, request *Request, response *Response) error {
+ // To make the specification, peer, and RPC headers visible to the full
+ // interceptor chain (as though they were supplied by the caller), we'll
+ // add them here.
+ request.spec = unarySpec
+ request.peer = client.protocolClient.Peer()
+ protocolClient.WriteRequestHeader(StreamTypeUnary, request.Header())
+ if err := unaryFunc(ctx, request, response); err != nil {
+ return err
+ }
+ //typed, ok := response.(*Response[Res])
+ //if !ok {
+ // return nil, errorf(CodeInternal, "unexpected client response type %T", response)
+ //}
+ return nil
+ }
+ return client
+}
+
+// CallUnary calls a request-response procedure.
+func (c *Client) CallUnary(ctx context.Context, request *Request, response *Response) error {
+ if c.err != nil {
+ return c.err
+ }
+ return c.callUnary(ctx, request, response)
+}
+
+// CallClientStream calls a client streaming procedure.
+func (c *Client) CallClientStream(ctx context.Context) (*ClientStreamForClient, error) {
+ if c.err != nil {
+ return &ClientStreamForClient{err: c.err}, c.err
+ }
+ return &ClientStreamForClient{conn: c.newConn(ctx, StreamTypeClient)}, nil
+}
+
+// CallServerStream calls a server streaming procedure.
+func (c *Client) CallServerStream(ctx context.Context, request *Request) (*ServerStreamForClient, error) {
+ if c.err != nil {
+ return nil, c.err
+ }
+ conn := c.newConn(ctx, StreamTypeServer)
+ request.spec = conn.Spec()
+ request.peer = conn.Peer()
+ mergeHeaders(conn.RequestHeader(), request.header)
+ // Send always returns an io.EOF unless the error is from the client-side.
+ // We want the user to continue to call Receive in those cases to get the
+ // full error from the server-side.
+ if err := conn.Send(request.Msg); err != nil && !errors.Is(err, io.EOF) {
+ _ = conn.CloseRequest()
+ _ = conn.CloseResponse()
+ return nil, err
+ }
+ if err := conn.CloseRequest(); err != nil {
+ return nil, err
+ }
+ return &ServerStreamForClient{conn: conn}, nil
+}
+
+// CallBidiStream calls a bidirectional streaming procedure.
+func (c *Client) CallBidiStream(ctx context.Context) (*BidiStreamForClient, error) {
+ if c.err != nil {
+ return &BidiStreamForClient{err: c.err}, c.err
+ }
+ return &BidiStreamForClient{conn: c.newConn(ctx, StreamTypeBidi)}, nil
+}
+
+func (c *Client) newConn(ctx context.Context, streamType StreamType) StreamingClientConn {
+ newConn := func(ctx context.Context, spec Spec) StreamingClientConn {
+ header := make(http.Header, 8) // arbitrary power of two, prevent immediate resizing
+ c.protocolClient.WriteRequestHeader(streamType, header)
+ return c.protocolClient.NewConn(ctx, spec, header)
+ }
+ if interceptor := c.config.Interceptor; interceptor != nil {
+ newConn = interceptor.WrapStreamingClient(newConn)
+ }
+ return newConn(ctx, c.config.newSpec(streamType))
+}
+
+type clientConfig struct {
+ URL *url.URL
+ Protocol protocol
+ Procedure string
+ CompressMinBytes int
+ Interceptor Interceptor
+ CompressionPools map[string]*compressionPool
+ CompressionNames []string
+ Codec Codec
+ RequestCompressionName string
+ BufferPool *bufferPool
+ ReadMaxBytes int
+ SendMaxBytes int
+ EnableGet bool
+ GetURLMaxBytes int
+ GetUseFallback bool
+ IdempotencyLevel IdempotencyLevel
+}
+
+func newClientConfig(rawURL string, options []ClientOption) (*clientConfig, *Error) {
+ url, err := parseRequestURL(rawURL)
+ if err != nil {
+ return nil, err
+ }
+ protoPath := extractProtoPath(url.Path)
+ config := clientConfig{
+ URL: url,
+ Protocol: &protocolTriple{},
+ Procedure: protoPath,
+ CompressionPools: make(map[string]*compressionPool),
+ BufferPool: newBufferPool(),
+ }
+ withProtoBinaryCodec().applyToClient(&config)
+ withGzip().applyToClient(&config)
+ for _, opt := range options {
+ opt.applyToClient(&config)
+ }
+ if err := config.validate(); err != nil {
+ return nil, err
+ }
+ return &config, nil
+}
+
+func (c *clientConfig) validate() *Error {
+ if c.Codec == nil || c.Codec.Name() == "" {
+ return errorf(CodeUnknown, "no codec configured")
+ }
+ if c.RequestCompressionName != "" && c.RequestCompressionName != compressionIdentity {
+ if _, ok := c.CompressionPools[c.RequestCompressionName]; !ok {
+ return errorf(CodeUnknown, "unknown compression %q", c.RequestCompressionName)
+ }
+ }
+ return nil
+}
+
+func (c *clientConfig) protobuf() Codec {
+ if c.Codec.Name() == codecNameProto {
+ return c.Codec
+ }
+ return &protoBinaryCodec{}
+}
+
+func (c *clientConfig) newSpec(t StreamType) Spec {
+ return Spec{
+ StreamType: t,
+ Procedure: c.Procedure,
+ IsClient: true,
+ IdempotencyLevel: c.IdempotencyLevel,
+ }
+}
+
+func parseRequestURL(rawURL string) (*url.URL, *Error) {
+ url, err := url.ParseRequestURI(rawURL)
+ if err == nil {
+ return url, nil
+ }
+ if !strings.Contains(rawURL, "://") {
+ // URL doesn't have a scheme, so the user is likely accustomed to
+ // grpc-go's APIs.
+ err = fmt.Errorf(
+ "URL %q missing scheme: use http:// or https:// (unlike grpc-go)",
+ rawURL,
+ )
+ }
+ return nil, NewError(CodeUnavailable, err)
+}
diff --git a/protocol/triple/triple_protocol/client_example_test.go b/protocol/triple/triple_protocol/client_example_test.go
new file mode 100644
index 000000000..fa40d919b
--- /dev/null
+++ b/protocol/triple/triple_protocol/client_example_test.go
@@ -0,0 +1,57 @@
+// // Copyright 2021-2023 Buf Technologies, Inc.
+// //
+// // Licensed under the Apache License, Version 2.0 (the "License");
+// // you may not use this file except in compliance with the License.
+// // You may obtain a copy of the License at
+// //
+// // http://www.apache.org/licenses/LICENSE-2.0
+// //
+// // Unless required by applicable law or agreed to in writing, software
+// // distributed under the License is distributed on an "AS IS" BASIS,
+// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// // See the License for the specific language governing permissions and
+// // limitations under the License.
+package triple_protocol_test
+
+//
+//
+//import (
+// "context"
+// tri "dubbo.apache.org/dubbo-go/v3/protocol//triple/triple_protocol"
+// "log"
+// "net/http"
+// "os"
+//
+// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/proto/connect/ping/v1"
+// "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/proto/connect/ping/v1/pingv1connect"
+//)
+//
+//func Example_client() {
+// logger := log.New(os.Stdout, "" /* prefix */, 0 /* flags */)
+// // Unfortunately, pkg.go.dev can't run examples that actually use the
+// // network. To keep this example runnable, we'll use an HTTP server and
+// // client that communicate over in-memory pipes. The client is still a plain
+// // *http.Client!
+// var httpClient *http.Client = examplePingServer.Client()
+//
+// // By default, clients use the Connect protocol. Add connect.WithGRPC() or
+// // connect.WithGRPCWeb() to switch protocols.
+// client := pingv1connect.NewPingServiceClient(
+// httpClient,
+// examplePingServer.URL(),
+// )
+// response, err := client.Ping(
+// context.Background(),
+// tri.NewRequest(&pingv1.PingRequest{Number: 42}),
+// )
+// if err != nil {
+// logger.Println("error:", err)
+// return
+// }
+// logger.Println("response content-type:", response.Header().Get("Content-Type"))
+// logger.Println("response message:", response.Msg)
+//
+// // Output:
+// // response content-type: application/proto
+// // response message: number:42
+//}
diff --git a/protocol/triple/triple_protocol/client_ext_test.go b/protocol/triple/triple_protocol/client_ext_test.go
new file mode 100644
index 000000000..77909c1df
--- /dev/null
+++ b/protocol/triple/triple_protocol/client_ext_test.go
@@ -0,0 +1,181 @@
+// // Copyright 2021-2023 Buf Technologies, Inc.
+// //
+// // Licensed under the Apache License, Version 2.0 (the "License");
+// // you may not use this file except in compliance with the License.
+// // You may obtain a copy of the License at
+// //
+// // http://www.apache.org/licenses/LICENSE-2.0
+// //
+// // Unless required by applicable law or agreed to in writing, software
+// // distributed under the License is distributed on an "AS IS" BASIS,
+// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// // See the License for the specific language governing permissions and
+// // limitations under the License.
+package triple_protocol_test
+
+//
+//import (
+// "context"
+// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/triple"
+// "errors"
+// "net/http"
+// "net/http/httptest"
+// "strings"
+// "testing"
+//
+// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/assert"
+// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1"
+// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1/pingv1connect"
+//)
+//
+//func TestNewClient_InitFailure(t *testing.T) {
+// t.Parallel()
+// client := pingv1connect.NewPingServiceClient(
+// http.DefaultClient,
+// "http://127.0.0.1:8080",
+// // This triggers an error during initialization, so each call will short circuit returning an error.
+// triple.WithSendCompression("invalid"),
+// )
+// validateExpectedError := func(t *testing.T, err error) {
+// t.Helper()
+// assert.NotNil(t, err)
+// var connectErr *triple.Error
+// assert.True(t, errors.As(err, &connectErr))
+// assert.Equal(t, connectErr.Message(), `unknown compression "invalid"`)
+// }
+//
+// t.Run("unary", func(t *testing.T) {
+// t.Parallel()
+// _, err := client.Ping(context.Background(), triple.NewRequest(&pingv1.PingRequest{}))
+// validateExpectedError(t, err)
+// })
+//
+// t.Run("bidi", func(t *testing.T) {
+// t.Parallel()
+// bidiStream, err := client.CumSum(context.Background())
+// validateExpectedError(t, err)
+// err = bidiStream.Send(&pingv1.CumSumRequest{})
+// validateExpectedError(t, err)
+// })
+//
+// t.Run("client_stream", func(t *testing.T) {
+// t.Parallel()
+// clientStream, err := client.Sum(context.Background())
+// validateExpectedError(t, err)
+// err = clientStream.Send(&pingv1.SumRequest{})
+// validateExpectedError(t, err)
+// })
+//
+// t.Run("server_stream", func(t *testing.T) {
+// t.Parallel()
+// _, err := client.CountUp(context.Background(), triple.NewRequest(&pingv1.CountUpRequest{Number: 3}))
+// validateExpectedError(t, err)
+// })
+//}
+//
+//func TestClientPeer(t *testing.T) {
+// t.Parallel()
+// mux := http.NewServeMux()
+// mux.Handle(pingv1connect.NewPingServiceHandler(pingServer{}))
+// server := httptest.NewUnstartedServer(mux)
+// server.EnableHTTP2 = true
+// server.StartTLS()
+// t.Cleanup(server.Close)
+//
+// run := func(t *testing.T, opts ...triple.ClientOption) {
+// t.Helper()
+// client := pingv1connect.NewPingServiceClient(
+// server.Client(),
+// server.URL,
+// triple.WithClientOptions(opts...),
+// triple.WithInterceptors(&assertPeerInterceptor{t}),
+// )
+// ctx := context.Background()
+// // unary
+// _, err := client.Ping(ctx, triple.NewRequest[pingv1.PingRequest](nil))
+// assert.Nil(t, err)
+// text := strings.Repeat(".", 256)
+// r, err := client.Ping(ctx, triple.NewRequest(&pingv1.PingRequest{Text: text}))
+// assert.Nil(t, err)
+// assert.Equal(t, r.Msg.Text, text)
+// // client streaming
+// clientStream, err := client.Sum(ctx)
+// assert.Nil(t, err)
+// t.Cleanup(func() {
+// _, closeErr := clientStream.CloseAndReceive()
+// assert.Nil(t, closeErr)
+// })
+// assert.NotZero(t, clientStream.Peer().Addr)
+// assert.NotZero(t, clientStream.Peer().Protocol)
+// err = clientStream.Send(&pingv1.SumRequest{})
+// assert.Nil(t, err)
+// // server streaming
+// serverStream, err := client.CountUp(ctx, triple.NewRequest(&pingv1.CountUpRequest{}))
+// t.Cleanup(func() {
+// assert.Nil(t, serverStream.Close())
+// })
+// assert.Nil(t, err)
+// // bidi streaming
+// bidiStream, err := client.CumSum(ctx)
+// assert.Nil(t, err)
+// t.Cleanup(func() {
+// assert.Nil(t, bidiStream.CloseRequest())
+// assert.Nil(t, bidiStream.CloseResponse())
+// })
+// assert.NotZero(t, bidiStream.Peer().Addr)
+// assert.NotZero(t, bidiStream.Peer().Protocol)
+// err = bidiStream.Send(&pingv1.CumSumRequest{})
+// assert.Nil(t, err)
+// }
+//
+// t.Run("connect", func(t *testing.T) {
+// t.Parallel()
+// run(t)
+// })
+// t.Run("connect+get", func(t *testing.T) {
+// t.Parallel()
+// run(t,
+// triple.WithHTTPGet(),
+// triple.WithSendGzip(),
+// )
+// })
+// t.Run("grpc", func(t *testing.T) {
+// t.Parallel()
+// run(t, triple.WithGRPC())
+// })
+// t.Run("grpcweb", func(t *testing.T) {
+// t.Parallel()
+// run(t, triple.WithGRPCWeb())
+// })
+//}
+//
+//type assertPeerInterceptor struct {
+// tb testing.TB
+//}
+//
+//func (a *assertPeerInterceptor) WrapUnary(next triple.UnaryFunc) triple.UnaryFunc {
+// return func(ctx context.Context, req triple.AnyRequest) (triple.AnyResponse, error) {
+// assert.NotZero(a.tb, req.Peer().Addr)
+// assert.NotZero(a.tb, req.Peer().Protocol)
+// return next(ctx, req)
+// }
+//}
+//
+//func (a *assertPeerInterceptor) WrapStreamingClient(next triple.StreamingClientFunc) triple.StreamingClientFunc {
+// return func(ctx context.Context, spec triple.Spec) triple.StreamingClientConn {
+// conn := next(ctx, spec)
+// assert.NotZero(a.tb, conn.Peer().Addr)
+// assert.NotZero(a.tb, conn.Peer().Protocol)
+// assert.NotZero(a.tb, conn.Spec())
+// return conn
+// }
+//}
+//
+//func (a *assertPeerInterceptor) WrapStreamingHandler(next triple.StreamingHandlerFunc) triple.StreamingHandlerFunc {
+// return func(ctx context.Context, conn triple.StreamingHandlerConn) error {
+// assert.NotZero(a.tb, conn.Peer().Addr)
+// assert.NotZero(a.tb, conn.Peer().Protocol)
+// assert.NotZero(a.tb, conn.Spec())
+// return next(ctx, conn)
+// }
+//}
diff --git a/protocol/triple/triple_protocol/client_get_fallback_test.go b/protocol/triple/triple_protocol/client_get_fallback_test.go
new file mode 100644
index 000000000..22e333be2
--- /dev/null
+++ b/protocol/triple/triple_protocol/client_get_fallback_test.go
@@ -0,0 +1,62 @@
+// // Copyright 2021-2023 Buf Technologies, Inc.
+// //
+// // Licensed under the Apache License, Version 2.0 (the "License");
+// // you may not use this file except in compliance with the License.
+// // You may obtain a copy of the License at
+// //
+// // http://www.apache.org/licenses/LICENSE-2.0
+// //
+// // Unless required by applicable law or agreed to in writing, software
+// // distributed under the License is distributed on an "AS IS" BASIS,
+// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// // See the License for the specific language governing permissions and
+// // limitations under the License.
+package triple_protocol
+
+//
+//import (
+// "context"
+// "net/http"
+// "net/http/httptest"
+// "strings"
+// "testing"
+//
+// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/assert"
+// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1"
+//)
+//
+//func TestClientUnaryGetFallback(t *testing.T) {
+// t.Parallel()
+// mux := http.NewServeMux()
+// mux.Handle("/connect.ping.v1.PingService/Ping", NewUnaryHandler(
+// "/connect.ping.v1.PingService/Ping",
+// func(ctx context.Context, r *Request[pingv1.PingRequest]) (*Response[pingv1.PingResponse], error) {
+// return NewResponse(&pingv1.PingResponse{
+// Number: r.Msg.Number,
+// Text: r.Msg.Text,
+// }), nil
+// },
+// WithIdempotency(IdempotencyNoSideEffects),
+// ))
+// server := httptest.NewUnstartedServer(mux)
+// server.EnableHTTP2 = true
+// server.StartTLS()
+// t.Cleanup(server.Close)
+//
+// client := NewClient[pingv1.PingRequest, pingv1.PingResponse](
+// server.Client(),
+// server.URL+"/connect.ping.v1.PingService/Ping",
+// WithHTTPGet(),
+// withHTTPGetMaxURLSize(1, true),
+// WithSendGzip(),
+// )
+// ctx := context.Background()
+//
+// _, err := client.CallUnary(ctx, NewRequest[pingv1.PingRequest](nil))
+// assert.Nil(t, err)
+//
+// text := strings.Repeat(".", 256)
+// r, err := client.CallUnary(ctx, NewRequest(&pingv1.PingRequest{Text: text}))
+// assert.Nil(t, err)
+// assert.Equal(t, r.Msg.Text, text)
+//}
diff --git a/protocol/triple/triple_protocol/client_stream.go b/protocol/triple/triple_protocol/client_stream.go
new file mode 100644
index 000000000..f2af36a3c
--- /dev/null
+++ b/protocol/triple/triple_protocol/client_stream.go
@@ -0,0 +1,272 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package triple_protocol
+
+import (
+ "errors"
+ "io"
+ "net/http"
+)
+
+// ClientStreamForClient is the client's view of a client streaming RPC.
+//
+// It's returned from [Client].CallClientStream, but doesn't currently have an
+// exported constructor function.
+type ClientStreamForClient struct {
+ conn StreamingClientConn
+ // Error from client construction. If non-nil, return for all calls.
+ err error
+}
+
+// Spec returns the specification for the RPC.
+func (c *ClientStreamForClient) Spec() Spec {
+ return c.conn.Spec()
+}
+
+// Peer describes the server for the RPC.
+func (c *ClientStreamForClient) Peer() Peer {
+ return c.conn.Peer()
+}
+
+// RequestHeader returns the request headers. Headers are sent to the server with the
+// first call to Send.
+//
+// Headers beginning with "Triple-" and "Grpc-" are reserved for use by the
+// Triple and gRPC protocols. Applications shouldn't write them.
+func (c *ClientStreamForClient) RequestHeader() http.Header {
+ if c.err != nil {
+ return http.Header{}
+ }
+ return c.conn.RequestHeader()
+}
+
+// Send a message to the server. The first call to Send also sends the request
+// headers.
+//
+// If the server returns an error, Send returns an error that wraps [io.EOF].
+// Clients should check for case using the standard library's [errors.Is] and
+// unmarshal the error using CloseAndReceive.
+func (c *ClientStreamForClient) Send(request any) error {
+ if c.err != nil {
+ return c.err
+ }
+ if request == nil {
+ return c.conn.Send(nil)
+ }
+ return c.conn.Send(request)
+}
+
+// CloseAndReceive closes the send side of the stream and waits for the
+// response.
+func (c *ClientStreamForClient) CloseAndReceive(response *Response) error {
+ if c.err != nil {
+ return c.err
+ }
+ if err := c.conn.CloseRequest(); err != nil {
+ _ = c.conn.CloseResponse()
+ return err
+ }
+ if err := receiveUnaryResponse(c.conn, response); err != nil {
+ _ = c.conn.CloseResponse()
+ return err
+ }
+ return c.conn.CloseResponse()
+}
+
+// Conn exposes the underlying StreamingClientConn. This may be useful if
+// you'd prefer to wrap the connection in a different high-level API.
+func (c *ClientStreamForClient) Conn() (StreamingClientConn, error) {
+ return c.conn, c.err
+}
+
+// ServerStreamForClient is the client's view of a server streaming RPC.
+//
+// It's returned from [Client].CallServerStream, but doesn't currently have an
+// exported constructor function.
+type ServerStreamForClient struct {
+ conn StreamingClientConn
+ msg any
+ // Error from client construction. If non-nil, return for all calls.
+ constructErr error
+ // Error from conn.Receive().
+ receiveErr error
+}
+
+// Receive advances the stream to the next message, which will then be
+// available through the Msg method. It returns false when the stream stops,
+// either by reaching the end or by encountering an unexpected error. After
+// Receive returns false, the Err method will return any unexpected error
+// encountered.
+func (s *ServerStreamForClient) Receive(msg any) bool {
+ if s.constructErr != nil || s.receiveErr != nil {
+ return false
+ }
+ s.msg = msg
+ s.receiveErr = s.conn.Receive(s.msg)
+ return s.receiveErr == nil
+}
+
+// Msg returns the most recent message unmarshaled by a call to Receive.
+func (s *ServerStreamForClient) Msg() any {
+ // todo:// processing nil pointer
+ //if s.msg == nil {
+ // s.msg = new(Res)
+ //}
+ return s.msg
+}
+
+// Err returns the first non-EOF error that was encountered by Receive.
+func (s *ServerStreamForClient) Err() error {
+ if s.constructErr != nil {
+ return s.constructErr
+ }
+ if s.receiveErr != nil && !errors.Is(s.receiveErr, io.EOF) {
+ return s.receiveErr
+ }
+ return nil
+}
+
+// ResponseHeader returns the headers received from the server. It blocks until
+// the first call to Receive returns.
+func (s *ServerStreamForClient) ResponseHeader() http.Header {
+ if s.constructErr != nil {
+ return http.Header{}
+ }
+ return s.conn.ResponseHeader()
+}
+
+// ResponseTrailer returns the trailers received from the server. Trailers
+// aren't fully populated until Receive() returns an error wrapping io.EOF.
+func (s *ServerStreamForClient) ResponseTrailer() http.Header {
+ if s.constructErr != nil {
+ return http.Header{}
+ }
+ return s.conn.ResponseTrailer()
+}
+
+// Close the receive side of the stream.
+func (s *ServerStreamForClient) Close() error {
+ if s.constructErr != nil {
+ return s.constructErr
+ }
+ return s.conn.CloseResponse()
+}
+
+// Conn exposes the underlying StreamingClientConn. This may be useful if
+// you'd prefer to wrap the connection in a different high-level API.
+func (s *ServerStreamForClient) Conn() (StreamingClientConn, error) {
+ return s.conn, s.constructErr
+}
+
+// BidiStreamForClient is the client's view of a bidirectional streaming RPC.
+//
+// It's returned from [Client].CallBidiStream, but doesn't currently have an
+// exported constructor function.
+type BidiStreamForClient struct {
+ conn StreamingClientConn
+ // Error from client construction. If non-nil, return for all calls.
+ err error
+}
+
+// Spec returns the specification for the RPC.
+func (b *BidiStreamForClient) Spec() Spec {
+ return b.conn.Spec()
+}
+
+// Peer describes the server for the RPC.
+func (b *BidiStreamForClient) Peer() Peer {
+ return b.conn.Peer()
+}
+
+// RequestHeader returns the request headers. Headers are sent with the first
+// call to Send.
+//
+// Headers beginning with "Triple-" and "Grpc-" are reserved for use by the
+// Triple and gRPC protocols. Applications shouldn't write them.
+func (b *BidiStreamForClient) RequestHeader() http.Header {
+ if b.err != nil {
+ return http.Header{}
+ }
+ return b.conn.RequestHeader()
+}
+
+// Send a message to the server. The first call to Send also sends the request
+// headers. To send just the request headers, without a body, call Send with a
+// nil pointer.
+//
+// If the server returns an error, Send returns an error that wraps [io.EOF].
+// Clients should check for EOF using the standard library's [errors.Is] and
+// call Receive to retrieve the error.
+func (b *BidiStreamForClient) Send(msg any) error {
+ if b.err != nil {
+ return b.err
+ }
+ if msg == nil {
+ return b.conn.Send(nil)
+ }
+ return b.conn.Send(msg)
+}
+
+// CloseRequest closes the send side of the stream.
+func (b *BidiStreamForClient) CloseRequest() error {
+ if b.err != nil {
+ return b.err
+ }
+ return b.conn.CloseRequest()
+}
+
+// Receive a message. When the server is done sending messages and no other
+// errors have occurred, Receive will return an error that wraps [io.EOF].
+func (b *BidiStreamForClient) Receive(msg any) error {
+ if b.err != nil {
+ return b.err
+ }
+ if err := b.conn.Receive(&msg); err != nil {
+ return err
+ }
+ return nil
+}
+
+// CloseResponse closes the receive side of the stream.
+func (b *BidiStreamForClient) CloseResponse() error {
+ if b.err != nil {
+ return b.err
+ }
+ return b.conn.CloseResponse()
+}
+
+// ResponseHeader returns the headers received from the server. It blocks until
+// the first call to Receive returns.
+func (b *BidiStreamForClient) ResponseHeader() http.Header {
+ if b.err != nil {
+ return http.Header{}
+ }
+ return b.conn.ResponseHeader()
+}
+
+// ResponseTrailer returns the trailers received from the server. Trailers
+// aren't fully populated until Receive() returns an error wrapping [io.EOF].
+func (b *BidiStreamForClient) ResponseTrailer() http.Header {
+ if b.err != nil {
+ return http.Header{}
+ }
+ return b.conn.ResponseTrailer()
+}
+
+// Conn exposes the underlying StreamingClientConn. This may be useful if
+// you'd prefer to wrap the connection in a different high-level API.
+func (b *BidiStreamForClient) Conn() (StreamingClientConn, error) {
+ return b.conn, b.err
+}
diff --git a/protocol/triple/triple_protocol/client_stream_test.go b/protocol/triple/triple_protocol/client_stream_test.go
new file mode 100644
index 000000000..506e91fdf
--- /dev/null
+++ b/protocol/triple/triple_protocol/client_stream_test.go
@@ -0,0 +1,106 @@
+// // Copyright 2021-2023 Buf Technologies, Inc.
+// //
+// // Licensed under the Apache License, Version 2.0 (the "License");
+// // you may not use this file except in compliance with the License.
+// // You may obtain a copy of the License at
+// //
+// // http://www.apache.org/licenses/LICENSE-2.0
+// //
+// // Unless required by applicable law or agreed to in writing, software
+// // distributed under the License is distributed on an "AS IS" BASIS,
+// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// // See the License for the specific language governing permissions and
+// // limitations under the License.
+package triple_protocol
+
+//
+//import (
+// "errors"
+// "fmt"
+// "net/http"
+// "testing"
+//
+// "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/assert"
+// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/grpc_new/connect/proto/connect/ping/v1"
+//)
+//
+//func TestClientStreamForClient_NoPanics(t *testing.T) {
+// t.Parallel()
+// initErr := errors.New("client init failure")
+// clientStream := &ClientStreamForClient[pingv1.PingRequest, pingv1.PingResponse]{err: initErr}
+// assert.ErrorIs(t, clientStream.Send(&pingv1.PingRequest{}), initErr)
+// verifyHeaders(t, clientStream.RequestHeader())
+// res, err := clientStream.CloseAndReceive()
+// assert.Nil(t, res)
+// assert.ErrorIs(t, err, initErr)
+// conn, err := clientStream.Conn()
+// assert.NotNil(t, err)
+// assert.Nil(t, conn)
+//}
+//
+//func TestServerStreamForClient_NoPanics(t *testing.T) {
+// t.Parallel()
+// initErr := errors.New("client init failure")
+// serverStream := &ServerStreamForClient[pingv1.PingResponse]{constructErr: initErr}
+// assert.ErrorIs(t, serverStream.Err(), initErr)
+// assert.ErrorIs(t, serverStream.Close(), initErr)
+// assert.NotNil(t, serverStream.Msg())
+// assert.False(t, serverStream.Receive())
+// verifyHeaders(t, serverStream.ResponseHeader())
+// verifyHeaders(t, serverStream.ResponseTrailer())
+// conn, err := serverStream.Conn()
+// assert.NotNil(t, err)
+// assert.Nil(t, conn)
+//}
+//
+//func TestServerStreamForClient(t *testing.T) {
+// t.Parallel()
+// stream := &ServerStreamForClient[pingv1.PingResponse]{conn: &nopStreamingClientConn{}}
+// // Ensure that each call to Receive allocates a new message. This helps
+// // vtprotobuf, which doesn't automatically zero messages before unmarshaling
+// // (see https://github.com/bufbuild/connect-go/issues/345), and it's also
+// // less error-prone for users.
+// assert.True(t, stream.Receive())
+// first := fmt.Sprintf("%p", stream.Msg())
+// assert.True(t, stream.Receive())
+// second := fmt.Sprintf("%p", stream.Msg())
+// assert.NotEqual(t, first, second)
+// conn, err := stream.Conn()
+// assert.Nil(t, err)
+// assert.NotNil(t, conn)
+//}
+//
+//func TestBidiStreamForClient_NoPanics(t *testing.T) {
+// t.Parallel()
+// initErr := errors.New("client init failure")
+// bidiStream := &BidiStreamForClient[pingv1.CumSumRequest, pingv1.CumSumResponse]{err: initErr}
+// res, err := bidiStream.Receive()
+// assert.Nil(t, res)
+// assert.ErrorIs(t, err, initErr)
+// verifyHeaders(t, bidiStream.RequestHeader())
+// verifyHeaders(t, bidiStream.ResponseHeader())
+// verifyHeaders(t, bidiStream.ResponseTrailer())
+// assert.ErrorIs(t, bidiStream.Send(&pingv1.CumSumRequest{}), initErr)
+// assert.ErrorIs(t, bidiStream.CloseRequest(), initErr)
+// assert.ErrorIs(t, bidiStream.CloseResponse(), initErr)
+// conn, err := bidiStream.Conn()
+// assert.NotNil(t, err)
+// assert.Nil(t, conn)
+//}
+//
+//func verifyHeaders(t *testing.T, headers http.Header) {
+// t.Helper()
+// assert.Equal(t, headers, http.Header{})
+//
+// // Verify set/del don't panic
+// headers.Set("a", "b")
+// headers.Del("a")
+//}
+//
+//type nopStreamingClientConn struct {
+// StreamingClientConn
+//}
+//
+//func (c *nopStreamingClientConn) Receive(msg any) error {
+// return nil
+//}
diff --git a/protocol/triple/triple_protocol/code.go b/protocol/triple/triple_protocol/code.go
new file mode 100644
index 000000000..95d634549
--- /dev/null
+++ b/protocol/triple/triple_protocol/code.go
@@ -0,0 +1,226 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package triple_protocol
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+// A Code is one of the Connect protocol's error codes. There are no user-defined
+// codes, so only the codes enumerated below are valid. In both name and
+// semantics, these codes match the gRPC status codes.
+//
+// The descriptions below are optimized for brevity rather than completeness.
+// See the [Connect protocol specification] for detailed descriptions of each
+// code and example usage.
+//
+// [Connect protocol specification]: https://connect.build/docs/protocol
+type Code uint32
+
+const (
+ // The zero code in gRPC is OK, which indicates that the operation was a
+ // success. We don't define a constant for it because it overlaps awkwardly
+ // with Go's error semantics: what does it mean to have a non-nil error with
+ // an OK status? (Also, the Connect protocol doesn't use a code for
+ // successes.)
+
+ // CodeCanceled indicates that the operation was canceled, typically by the
+ // caller.
+ CodeCanceled Code = 1
+
+ // CodeUnknown indicates that the operation failed for an unknown reason.
+ CodeUnknown Code = 2
+
+ // CodeInvalidArgument indicates that client supplied an invalid argument.
+ CodeInvalidArgument Code = 3
+
+ // CodeDeadlineExceeded indicates that deadline expired before the operation
+ // could complete.
+ CodeDeadlineExceeded Code = 4
+
+ // CodeNotFound indicates that some requested entity (for example, a file or
+ // directory) was not found.
+ CodeNotFound Code = 5
+
+ // CodeAlreadyExists indicates that client attempted to create an entity (for
+ // example, a file or directory) that already exists.
+ CodeAlreadyExists Code = 6
+
+ // CodePermissionDenied indicates that the caller doesn't have permission to
+ // execute the specified operation.
+ CodePermissionDenied Code = 7
+
+ // CodeResourceExhausted indicates that some resource has been exhausted. For
+ // example, a per-user quota may be exhausted or the entire file system may
+ // be full.
+ CodeResourceExhausted Code = 8
+
+ // CodeFailedPrecondition indicates that the system is not in a state
+ // required for the operation's execution.
+ CodeFailedPrecondition Code = 9
+
+ // CodeAborted indicates that operation was aborted by the system, usually
+ // because of a concurrency issue such as a sequencer check failure or
+ // transaction abort.
+ CodeAborted Code = 10
+
+ // CodeOutOfRange indicates that the operation was attempted past the valid
+ // range (for example, seeking past end-of-file).
+ CodeOutOfRange Code = 11
+
+ // CodeUnimplemented indicates that the operation isn't implemented,
+ // supported, or enabled in this service.
+ CodeUnimplemented Code = 12
+
+ // CodeInternal indicates that some invariants expected by the underlying
+ // system have been broken. This code is reserved for serious errors.
+ CodeInternal Code = 13
+
+ // CodeUnavailable indicates that the service is currently unavailable. This
+ // is usually temporary, so clients can back off and retry idempotent
+ // operations.
+ CodeUnavailable Code = 14
+
+ // CodeDataLoss indicates that the operation has resulted in unrecoverable
+ // data loss or corruption.
+ CodeDataLoss Code = 15
+
+ // CodeUnauthenticated indicates that the request does not have valid
+ // authentication credentials for the operation.
+ CodeUnauthenticated Code = 16
+
+ minCode = CodeCanceled
+ maxCode = CodeUnauthenticated
+)
+
+func (c Code) String() string {
+ switch c {
+ case CodeCanceled:
+ return "canceled"
+ case CodeUnknown:
+ return "unknown"
+ case CodeInvalidArgument:
+ return "invalid_argument"
+ case CodeDeadlineExceeded:
+ return "deadline_exceeded"
+ case CodeNotFound:
+ return "not_found"
+ case CodeAlreadyExists:
+ return "already_exists"
+ case CodePermissionDenied:
+ return "permission_denied"
+ case CodeResourceExhausted:
+ return "resource_exhausted"
+ case CodeFailedPrecondition:
+ return "failed_precondition"
+ case CodeAborted:
+ return "aborted"
+ case CodeOutOfRange:
+ return "out_of_range"
+ case CodeUnimplemented:
+ return "unimplemented"
+ case CodeInternal:
+ return "internal"
+ case CodeUnavailable:
+ return "unavailable"
+ case CodeDataLoss:
+ return "data_loss"
+ case CodeUnauthenticated:
+ return "unauthenticated"
+ }
+ return fmt.Sprintf("code_%d", c)
+}
+
+// MarshalText implements [encoding.TextMarshaler].
+func (c Code) MarshalText() ([]byte, error) {
+ return []byte(c.String()), nil
+}
+
+// UnmarshalText implements [encoding.TextUnmarshaler].
+func (c *Code) UnmarshalText(data []byte) error {
+ dataStr := string(data)
+ switch dataStr {
+ case "canceled":
+ *c = CodeCanceled
+ return nil
+ case "unknown":
+ *c = CodeUnknown
+ return nil
+ case "invalid_argument":
+ *c = CodeInvalidArgument
+ return nil
+ case "deadline_exceeded":
+ *c = CodeDeadlineExceeded
+ return nil
+ case "not_found":
+ *c = CodeNotFound
+ return nil
+ case "already_exists":
+ *c = CodeAlreadyExists
+ return nil
+ case "permission_denied":
+ *c = CodePermissionDenied
+ return nil
+ case "resource_exhausted":
+ *c = CodeResourceExhausted
+ return nil
+ case "failed_precondition":
+ *c = CodeFailedPrecondition
+ return nil
+ case "aborted":
+ *c = CodeAborted
+ return nil
+ case "out_of_range":
+ *c = CodeOutOfRange
+ return nil
+ case "unimplemented":
+ *c = CodeUnimplemented
+ return nil
+ case "internal":
+ *c = CodeInternal
+ return nil
+ case "unavailable":
+ *c = CodeUnavailable
+ return nil
+ case "data_loss":
+ *c = CodeDataLoss
+ return nil
+ case "unauthenticated":
+ *c = CodeUnauthenticated
+ return nil
+ }
+ // Ensure that non-canonical codes round-trip through MarshalText and
+ // UnmarshalText.
+ if strings.HasPrefix(dataStr, "code_") {
+ dataStr = strings.TrimPrefix(dataStr, "code_")
+ code, err := strconv.ParseUint(dataStr, 10 /* base */, 64 /* bitsize */)
+ if err == nil && (code < uint64(minCode) || code > uint64(maxCode)) {
+ *c = Code(code)
+ return nil
+ }
+ }
+ return fmt.Errorf("invalid code %q", dataStr)
+}
+
+// CodeOf returns the error's status code if it is or wraps an [*Error] and
+// [CodeUnknown] otherwise.
+func CodeOf(err error) Code {
+ if connectErr, ok := asError(err); ok {
+ return connectErr.Code()
+ }
+ return CodeUnknown
+}
diff --git a/protocol/triple/triple_protocol/code_test.go b/protocol/triple/triple_protocol/code_test.go
new file mode 100644
index 000000000..89c8ca44d
--- /dev/null
+++ b/protocol/triple/triple_protocol/code_test.go
@@ -0,0 +1,58 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package triple_protocol
+
+import (
+ "strconv"
+ "strings"
+ "testing"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/assert"
+)
+
+func TestCode(t *testing.T) {
+ t.Parallel()
+ var valid []Code
+ for code := minCode; code <= maxCode; code++ {
+ valid = append(valid, code)
+ }
+ // Ensures that we don't forget to update the mapping in the Stringer
+ // implementation.
+ for _, code := range valid {
+ assert.False(
+ t,
+ strings.HasPrefix(code.String(), "code_"),
+ assert.Sprintf("update Code.String() method for new code %v", code),
+ )
+ assertCodeRoundTrips(t, code)
+ }
+ assertCodeRoundTrips(t, Code(999))
+}
+
+func assertCodeRoundTrips(tb testing.TB, code Code) {
+ tb.Helper()
+ encoded, err := code.MarshalText()
+ assert.Nil(tb, err)
+ var decoded Code
+ assert.Nil(tb, decoded.UnmarshalText(encoded))
+ assert.Equal(tb, decoded, code)
+ if code >= minCode && code <= maxCode {
+ var invalid Code
+ // For the known codes, we only accept the canonical string representation: "canceled", not "code_1".
+ assert.NotNil(tb, invalid.UnmarshalText([]byte("code_"+strconv.Itoa(int(code)))))
+ }
+}
diff --git a/protocol/triple/triple_protocol/codec.go b/protocol/triple/triple_protocol/codec.go
new file mode 100644
index 000000000..e3ba583ce
--- /dev/null
+++ b/protocol/triple/triple_protocol/codec.go
@@ -0,0 +1,226 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package triple_protocol
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+)
+
+import (
+ "google.golang.org/protobuf/encoding/protojson"
+
+ "google.golang.org/protobuf/proto"
+
+ "google.golang.org/protobuf/runtime/protoiface"
+)
+
+const (
+ codecNameProto = "proto"
+ codecNameJSON = "json"
+ codecNameJSONCharsetUTF8 = codecNameJSON + "; charset=utf-8"
+)
+
+// Codec marshals structs (typically generated from a schema) to and from bytes.
+type Codec interface {
+ // Name returns the name of the Codec.
+ //
+ // This may be used as part of the Content-Type within HTTP. For example,
+ // with gRPC this is the content subtype, so "application/grpc+proto" will
+ // map to the Codec with name "proto".
+ //
+ // Names must not be empty.
+ Name() string
+ // Marshal marshals the given message.
+ //
+ // Marshal may expect a specific type of message, and will error if this type
+ // is not given.
+ Marshal(any) ([]byte, error)
+ // Unmarshal unmarshals the given message.
+ //
+ // Unmarshal may expect a specific type of message, and will error if this
+ // type is not given.
+ Unmarshal([]byte, any) error
+}
+
+// stableCodec is an extension to Codec for serializing with stable output.
+type stableCodec interface {
+ Codec
+
+ // MarshalStable marshals the given message with stable field ordering.
+ //
+ // MarshalStable should return the same output for a given input. Although
+ // it is not guaranteed to be canonicalized, the marshalling routine for
+ // MarshalStable will opt for the most normalized output available for a
+ // given serialization.
+ //
+ // For practical reasons, it is possible for MarshalStable to return two
+ // different results for two inputs considered to be "equal" in their own
+ // domain, and it may change in the future with codec updates, but for
+ // any given concrete value and any given version, it should return the
+ // same output.
+ MarshalStable(any) ([]byte, error)
+
+ // IsBinary returns true if the marshalled data is binary for this codec.
+ //
+ // If this function returns false, the data returned from Marshal and
+ // MarshalStable are considered valid text and may be used in contexts
+ // where text is expected.
+ IsBinary() bool
+}
+
+type protoBinaryCodec struct{}
+
+var _ Codec = (*protoBinaryCodec)(nil)
+
+func (c *protoBinaryCodec) Name() string { return codecNameProto }
+
+func (c *protoBinaryCodec) Marshal(message any) ([]byte, error) {
+ protoMessage, ok := message.(proto.Message)
+ if !ok {
+ return nil, errNotProto(message)
+ }
+ return proto.Marshal(protoMessage)
+}
+
+func (c *protoBinaryCodec) Unmarshal(data []byte, message any) error {
+ protoMessage, ok := message.(proto.Message)
+ if !ok {
+ return errNotProto(message)
+ }
+ return proto.Unmarshal(data, protoMessage)
+}
+
+func (c *protoBinaryCodec) MarshalStable(message any) ([]byte, error) {
+ protoMessage, ok := message.(proto.Message)
+ if !ok {
+ return nil, errNotProto(message)
+ }
+ // protobuf does not offer a canonical output today, so this format is not
+ // guaranteed to match deterministic output from other protobuf libraries.
+ // In addition, unknown fields may cause inconsistent output for otherwise
+ // equal messages.
+ // https://github.com/golang/protobuf/issues/1121
+ options := proto.MarshalOptions{Deterministic: true}
+ return options.Marshal(protoMessage)
+}
+
+func (c *protoBinaryCodec) IsBinary() bool {
+ return true
+}
+
+type protoJSONCodec struct {
+ name string
+}
+
+var _ Codec = (*protoJSONCodec)(nil)
+
+func (c *protoJSONCodec) Name() string { return c.name }
+
+func (c *protoJSONCodec) Marshal(message any) ([]byte, error) {
+ protoMessage, ok := message.(proto.Message)
+ if !ok {
+ return nil, errNotProto(message)
+ }
+ var options protojson.MarshalOptions
+ return options.Marshal(protoMessage)
+}
+
+func (c *protoJSONCodec) Unmarshal(binary []byte, message any) error {
+ protoMessage, ok := message.(proto.Message)
+ if !ok {
+ return errNotProto(message)
+ }
+ if len(binary) == 0 {
+ return errors.New("zero-length payload is not a valid JSON object")
+ }
+ var options protojson.UnmarshalOptions
+ return options.Unmarshal(binary, protoMessage)
+}
+
+func (c *protoJSONCodec) MarshalStable(message any) ([]byte, error) {
+ // protojson does not offer a "deterministic" field ordering, but fields
+ // are still ordered consistently by their index. However, protojson can
+ // output inconsistent whitespace for some reason, therefore it is
+ // suggested to use a formatter to ensure consistent formatting.
+ // https://github.com/golang/protobuf/issues/1373
+ messageJSON, err := c.Marshal(message)
+ if err != nil {
+ return nil, err
+ }
+ compactedJSON := bytes.NewBuffer(messageJSON[:0])
+ if err = json.Compact(compactedJSON, messageJSON); err != nil {
+ return nil, err
+ }
+ return compactedJSON.Bytes(), nil
+}
+
+func (c *protoJSONCodec) IsBinary() bool {
+ return false
+}
+
+// readOnlyCodecs is a read-only interface to a map of named codecs.
+type readOnlyCodecs interface {
+ // Get gets the Codec with the given name.
+ Get(string) Codec
+ // Protobuf gets the user-supplied protobuf codec, falling back to the default
+ // implementation if necessary.
+ //
+ // This is helpful in the gRPC protocol, where the wire protocol requires
+ // marshaling protobuf structs to binary even if the RPC procedures were
+ // generated from a different IDL.
+ Protobuf() Codec
+ // Names returns a copy of the registered codec names. The returned slice is
+ // safe for the caller to mutate.
+ Names() []string
+}
+
+func newReadOnlyCodecs(nameToCodec map[string]Codec) readOnlyCodecs {
+ return &codecMap{
+ nameToCodec: nameToCodec,
+ }
+}
+
+type codecMap struct {
+ nameToCodec map[string]Codec
+}
+
+func (m *codecMap) Get(name string) Codec {
+ return m.nameToCodec[name]
+}
+
+func (m *codecMap) Protobuf() Codec {
+ if pb, ok := m.nameToCodec[codecNameProto]; ok {
+ return pb
+ }
+ return &protoBinaryCodec{}
+}
+
+func (m *codecMap) Names() []string {
+ names := make([]string, 0, len(m.nameToCodec))
+ for name := range m.nameToCodec {
+ names = append(names, name)
+ }
+ return names
+}
+
+func errNotProto(message any) error {
+ if _, ok := message.(protoiface.MessageV1); ok {
+ return fmt.Errorf("%T uses github.com/golang/protobuf, but connect-go only supports google.golang.org/protobuf: see https://go.dev/blog/protobuf-apiv2", message)
+ }
+ return fmt.Errorf("%T doesn't implement proto.Message", message)
+}
diff --git a/protocol/triple/triple_protocol/codec_test.go b/protocol/triple/triple_protocol/codec_test.go
new file mode 100644
index 000000000..6793d160c
--- /dev/null
+++ b/protocol/triple/triple_protocol/codec_test.go
@@ -0,0 +1,112 @@
+// // Copyright 2021-2023 Buf Technologies, Inc.
+// //
+// // Licensed under the Apache License, Version 2.0 (the "License");
+// // you may not use this file except in compliance with the License.
+// // You may obtain a copy of the License at
+// //
+// // http://www.apache.org/licenses/LICENSE-2.0
+// //
+// // Unless required by applicable law or agreed to in writing, software
+// // distributed under the License is distributed on an "AS IS" BASIS,
+// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// // See the License for the specific language governing permissions and
+// // limitations under the License.
+package triple_protocol
+
+//
+//import (
+// "bytes"
+// "strings"
+// "testing"
+// "testing/quick"
+//
+// "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/assert"
+// pingv1 "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/proto/connect/ping/v1"
+// "google.golang.org/protobuf/proto"
+// "google.golang.org/protobuf/types/known/emptypb"
+// "google.golang.org/protobuf/types/known/structpb"
+//)
+//
+//func convertMapToInterface(stringMap map[string]string) map[string]interface{} {
+// interfaceMap := make(map[string]interface{})
+// for key, value := range stringMap {
+// interfaceMap[key] = value
+// }
+// return interfaceMap
+//}
+//
+//func TestCodecRoundTrips(t *testing.T) {
+// t.Parallel()
+// makeRoundtrip := func(codec Codec) func(string, int64) bool {
+// return func(text string, number int64) bool {
+// got := pingv1.PingRequest{}
+// want := pingv1.PingRequest{Text: text, Number: number}
+// data, err := codec.Marshal(&want)
+// if err != nil {
+// t.Fatal(err)
+// }
+// err = codec.Unmarshal(data, &got)
+// if err != nil {
+// t.Fatal(err)
+// }
+// return proto.Equal(&got, &want)
+// }
+// }
+// if err := quick.Check(makeRoundtrip(&protoBinaryCodec{}), nil /* config */); err != nil {
+// t.Error(err)
+// }
+// if err := quick.Check(makeRoundtrip(&protoJSONCodec{}), nil /* config */); err != nil {
+// t.Error(err)
+// }
+//}
+//
+//func TestStableCodec(t *testing.T) {
+// t.Parallel()
+// makeRoundtrip := func(codec stableCodec) func(map[string]string) bool {
+// return func(input map[string]string) bool {
+// initialProto, err := structpb.NewStruct(convertMapToInterface(input))
+// if err != nil {
+// t.Fatal(err)
+// }
+// want, err := codec.MarshalStable(initialProto)
+// if err != nil {
+// t.Fatal(err)
+// }
+// for i := 0; i < 10; i++ {
+// roundtripProto := &structpb.Struct{}
+// err = codec.Unmarshal(want, roundtripProto)
+// if err != nil {
+// t.Fatal(err)
+// }
+// got, err := codec.MarshalStable(roundtripProto)
+// if err != nil {
+// t.Fatal(err)
+// }
+// if !bytes.Equal(got, want) {
+// return false
+// }
+// }
+// return true
+// }
+// }
+// if err := quick.Check(makeRoundtrip(&protoBinaryCodec{}), nil /* config */); err != nil {
+// t.Error(err)
+// }
+// if err := quick.Check(makeRoundtrip(&protoJSONCodec{}), nil /* config */); err != nil {
+// t.Error(err)
+// }
+//}
+//
+//func TestJSONCodec(t *testing.T) {
+// t.Parallel()
+//
+// var empty emptypb.Empty
+// codec := &protoJSONCodec{name: "json"}
+// err := codec.Unmarshal([]byte{}, &empty)
+// assert.NotNil(t, err)
+// assert.True(
+// t,
+// strings.Contains(err.Error(), "valid JSON"),
+// assert.Sprintf(`error message should explain that "" is not a valid JSON object`),
+// )
+//}
diff --git a/protocol/triple/triple_protocol/compression.go b/protocol/triple/triple_protocol/compression.go
new file mode 100644
index 000000000..db93f4431
--- /dev/null
+++ b/protocol/triple/triple_protocol/compression.go
@@ -0,0 +1,215 @@
+// Copyright 2021-2023 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package triple_protocol
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "math"
+ "strings"
+ "sync"
+)
+
+const (
+ compressionGzip = "gzip"
+ compressionIdentity = "identity"
+)
+
+// A Decompressor is a reusable wrapper that decompresses an underlying data
+// source. The standard library's [*gzip.Reader] implements Decompressor.
+type Decompressor interface {
+ io.Reader
+
+ // Close closes the Decompressor, but not the underlying data source. It may
+ // return an error if the Decompressor wasn't read to EOF.
+ Close() error
+
+ // Reset discards the Decompressor's internal state, if any, and prepares it
+ // to read from a new source of compressed data.
+ Reset(io.Reader) error
+}
+
+// A Compressor is a reusable wrapper that compresses data written to an
+// underlying sink. The standard library's [*gzip.Writer] implements Compressor.
+type Compressor interface {
+ io.Writer
+
+ // Close flushes any buffered data to the underlying sink, then closes the
+ // Compressor. It must not close the underlying sink.
+ Close() error
+
+ // Reset discards the Compressor's internal state, if any, and prepares it to
+ // write compressed data to a new sink.
+ Reset(io.Writer)
+}
+
+type compressionPool struct {
+ decompressors sync.Pool
+ compressors sync.Pool
+}
+
+func newCompressionPool(
+ newDecompressor func() Decompressor,
+ newCompressor func() Compressor,
+) *compressionPool {
+ if newDecompressor == nil && newCompressor == nil {
+ return nil
+ }
+ return &compressionPool{
+ decompressors: sync.Pool{
+ New: func() any { return newDecompressor() },
+ },
+ compressors: sync.Pool{
+ New: func() any { return newCompressor() },
+ },
+ }
+}
+
+func (c *compressionPool) Decompress(dst *bytes.Buffer, src *bytes.Buffer, readMaxBytes int64) *Error {
+ decompressor, err := c.getDecompressor(src)
+ if err != nil {
+ return errorf(CodeInvalidArgument, "get decompressor: %w", err)
+ }
+ reader := io.Reader(decompressor)
+ if readMaxBytes > 0 && readMaxBytes < math.MaxInt64 {
+ reader = io.LimitReader(decompressor, readMaxBytes+1)
+ }
+ bytesRead, err := dst.ReadFrom(reader)
+ if err != nil {
+ _ = c.putDecompressor(decompressor)
+ return errorf(CodeInvalidArgument, "decompress: %w", err)
+ }
+ if readMaxBytes > 0 && bytesRead > readMaxBytes {
+ discardedBytes, err := io.Copy(io.Discard, decompressor)
+ _ = c.putDecompressor(decompressor)
+ if err != nil {
+ return errorf(CodeResourceExhausted, "message is larger than configured max %d - unable to determine message size: %w", readMaxBytes, err)
+ }
+ return errorf(CodeResourceExhausted, "message size %d is larger than configured max %d", bytesRead+discardedBytes, readMaxBytes)
+ }
+ if err := c.putDecompressor(decompressor); err != nil {
+ return errorf(CodeUnknown, "recycle decompressor: %w", err)
+ }
+ return nil
+}
+
+func (c *compressionPool) Compress(dst *bytes.Buffer, src *bytes.Buffer) *Error {
+ compressor, err := c.getCompressor(dst)
+ if err != nil {
+ return errorf(CodeUnknown, "get compressor: %w", err)
+ }
+ if _, err := io.Copy(compressor, src); err != nil {
+ _ = c.putCompressor(compressor)
+ return errorf(CodeInternal, "compress: %w", err)
+ }
+ if err := c.putCompressor(compressor); err != nil {
+ return errorf(CodeInternal, "recycle compressor: %w", err)
+ }
+ return nil
+}
+
+func (c *compressionPool) getDecompressor(reader io.Reader) (Decompressor, error) {
+ decompressor, ok := c.decompressors.Get().(Decompressor)
+ if !ok {
+ return nil, errors.New("expected Decompressor, got incorrect type from pool")
+ }
+ return decompressor, decompressor.Reset(reader)
+}
+
+func (c *compressionPool) putDecompressor(decompressor Decompressor) error {
+ if err := decompressor.Close(); err != nil {
+ return err
+ }
+ // While it's in the pool, we don't want the decompressor to retain a
+ // reference to the underlying reader. However, most decompressors attempt to
+ // read some header data from the new data source when Reset; since we don't
+ // know the compression format, we can't provide a valid header. Since we
+ // also reset the decompressor when it's pulled out of the pool, we can
+ // ignore errors here.
+ _ = decompressor.Reset(strings.NewReader(""))
+ c.decompressors.Put(decompressor)
+ return nil
+}
+
+func (c *compressionPool) getCompressor(writer io.Writer) (Compressor, error) {
+ compressor, ok := c.compressors.Get().(Compressor)
+ if !ok {
+ return nil, errors.New("expected Compressor, got incorrect type from pool")
+ }
+ compressor.Reset(writer)
+ return compressor, nil
+}
+
+func (c *compressionPool) putCompressor(compressor Compressor) error {
+ if err := compressor.Close(); err != nil {
+ return err
+ }
+ compressor.Reset(io.Discard) // don't keep references
+ c.compressors.Put(compressor)
+ return nil
+}
+
+// readOnlyCompressionPools is a read-only interface to a map of named
+// compressionPools.
+type readOnlyCompressionPools interface {
+ Get(string) *compressionPool
+ Contains(string) bool
+ // Wordy, but clarifies how this is different from readOnlyCodecs.Names().
+ CommaSeparatedNames() string
+}
+
+func newReadOnlyCompressionPools(
+ nameToPool map[string]*compressionPool,
+ reversedNames []string,
+) readOnlyCompressionPools {
+ // Client and handler configs keep compression names in registration order,
+ // but we want the last registered to be the most preferred.
+ names := make([]string, 0, len(reversedNames))
+ seen := make(map[string]struct{}, len(reversedNames))
+ for i := len(reversedNames) - 1; i >= 0; i-- {
+ name := reversedNames[i]
+ if _, ok := seen[name]; ok {
+ continue
+ }
+ seen[name] = struct{}{}
+ names = append(names, name)
+ }
+ return &namedCompressionPools{
+ nameToPool: nameToPool,
+ commaSeparatedNames: strings.Join(names, ","),
+ }
+}
+
+type namedCompressionPools struct {
+ nameToPool map[string]*compressionPool
+ commaSeparatedNames string
+}
+
+func (m *namedCompressionPools) Get(name string) *compressionPool {
+ if name == "" || name == compressionIdentity {
+ return nil
+ }
+ return m.nameToPool[name]
+}
+
+func (m *namedCompressionPools) Contains(name string) bool {
+ _, ok := m.nameToPool[name]
+ return ok
+}
+
+func (m *namedCompressionPools) CommaSeparatedNames() string {
+ return m.commaSeparatedNames
+}
diff --git a/protocol/triple/triple_protocol/compression_test.go b/protocol/triple/triple_protocol/compression_test.go
new file mode 100644
index 000000000..c905a53a3
--- /dev/null
+++ b/protocol/triple/triple_protocol/compression_test.go
@@ -0,0 +1,163 @@
+// // Copyright 2021-2023 Buf Technologies, Inc.
+// //
+// // Licensed under the Apache License, Version 2.0 (the "License");
+// // you may not use this file except in compliance with the License.
+// // You may obtain a copy of the License at
+// //
+// // http://www.apache.org/licenses/LICENSE-2.0
+// //
+// // Unless required by applicable law or agreed to in writing, software
+// // distributed under the License is distributed on an "AS IS" BASIS,
+// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// // See the License for the specific language governing permissions and
+// // limitations under the License.
+package triple_protocol
+
+//
+//import (
+// "context"
+// "net/http"
+// "net/http/httptest"
+// "testing"
+//
+// "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol/assert"
+// "google.golang.org/protobuf/types/known/emptypb"
+//)
+//
+//func TestAcceptEncodingOrdering(t *testing.T) {
+// t.Parallel()
+// const (
+// compressionBrotli = "br"
+// expect = compressionGzip + "," + compressionBrotli
+// )
+//
+// withFakeBrotli, ok := withGzip().(*compressionOption)
+// assert.True(t, ok)
+// withFakeBrotli.Name = compressionBrotli
+//
+// var called bool
+// verify := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+// got := r.Header.Get(connectUnaryHeaderAcceptCompression)
+// assert.Equal(t, got, expect)
+// w.WriteHeader(http.StatusOK)
+// called = true
+// })
+// server := httptest.NewServer(verify)
+// defer server.Close()
+//
+// client := NewClient[emptypb.Empty, emptypb.Empty](
+// server.Client(),
+// server.URL,
+// withFakeBrotli,
+// withGzip(),
+// )
+// _, _ = client.CallUnary(context.Background(), NewRequest(&emptypb.Empty{}))
+// assert.True(t, called)
+//}
+//
+//func TestClientCompressionOptionTest(t *testing.T) {
+// t.Parallel()
+// const testURL = "http://foo.bar.com/service/method"
+//
+// checkPools := func(t *testing.T, config *clientConfig) {
+// t.Helper()
+// assert.Equal(t, len(config.CompressionNames), len(config.CompressionPools))
+// for _, name := range config.CompressionNames {
+// pool := config.CompressionPools[name]
+// assert.NotNil(t, pool)
+// }
+// }
+// dummyDecompressCtor := func() Decompressor { return nil }
+// dummyCompressCtor := func() Compressor { return nil }
+//
+// t.Run("defaults", func(t *testing.T) {
+// t.Parallel()
+// config, err := newClientConfig(testURL, nil)
+// assert.Nil(t, err)
+// assert.Equal(t, config.CompressionNames, []string{compressionGzip})
+// checkPools(t, config)
+// })
+// t.Run("WithAcceptCompression", func(t *testing.T) {
+// t.Parallel()
+// opts := []ClientOption{WithAcceptCompression("foo", dummyDecompressCtor, dummyCompressCtor)}
+// config, err := newClientConfig(testURL, opts)
+// assert.Nil(t, err)
+// assert.Equal(t, config.CompressionNames, []string{compressionGzip, "foo"})
+// checkPools(t, config)
+// })
+// t.Run("WithAcceptCompression-empty-name-noop", func(t *testing.T) {
+// t.Parallel()
+// opts := []ClientOption{WithAcceptCompression("", dummyDecompressCtor, dummyCompressCtor)}
+// config, err := newClientConfig(testURL, opts)
+// assert.Nil(t, err)
+// assert.Equal(t, config.CompressionNames, []string{compressionGzip})
+// checkPools(t, config)
+// })
+// t.Run("WithAcceptCompression-nil-ctors-noop", func(t *testing.T) {
+// t.Parallel()
+// opts := []ClientOption{WithAcceptCompression("foo", nil, nil)}
+// config, err := newClientConfig(testURL, opts)
+// assert.Nil(t, err)
+// assert.Equal(t, config.CompressionNames, []string{compressionGzip})
+// checkPools(t, config)
+// })
+// t.Run("WithAcceptCompression-nil-ctors-unregisters", func(t *testing.T) {
+// t.Parallel()
+// opts := []ClientOption{WithAcceptCompression("gzip", nil, nil)}
+// config, err := newClientConfig(testURL, opts)
+// assert.Nil(t, err)
+// assert.Equal(t, config.CompressionNames, nil)
+// checkPools(t, config)
+// })
+//}
+//
+//func TestHandlerCompressionOptionTest(t *testing.T) {
+// t.Parallel()
+// const testProc = "/service/method"
+//
+// checkPools := func(t *testing.T, config *handlerConfig) {
+// t.Helper()
+// assert.Equal(t, len(config.CompressionNames), len(config.CompressionPools))
+// for _, name := range config.CompressionNames {
+// pool := config.CompressionPools[name]
+// assert.NotNil(t, pool)
+// }
+// }
+// dummyDecompressCtor := func() Decompressor { return nil }
+// dummyCompressCtor := func() Compressor { return nil }
+//
+// t.Run("defaults", func(t *testing.T) {
+// t.Parallel()
+// config := newHandlerConfig(testProc, nil)
+// assert.Equal(t, config.CompressionNames, []string{compressionGzip})
+// checkPools(t, config)
+// })
+// t.Run("WithCompression", func(t *testing.T) {
+// t.Parallel()
+// opts := []HandlerOption{WithCompression("foo", dummyDecompressCtor, dummyCompressCtor)}
+// config := newHandlerConfig(testProc, opts)
+// assert.Equal(t, config.CompressionNames, []string{compressionGzip, "foo"})
+// checkPools(t, config)
+// })
+// t.Run("WithCompression-empty-name-noop", func(t *testing.T) {
+// t.Parallel()
+// opts := []HandlerOption{WithCompression("", dummyDecompressCtor, dummyCompressCtor)}
+// config := newHandlerConfig(testProc, opts)
+// assert.Equal(t, config.CompressionNames, []string{compressionGzip})
+// checkPools(t, config)
+// })
+// t.Run("WithCompression-nil-ctors-noop", func(t *testing.T) {
+// t.Parallel()
+// opts := []HandlerOption{WithCompression("foo", nil, nil)}
+// config := newHandlerConfig(testProc, opts)
+// assert.Equal(t, config.CompressionNames, []string{compressionGzip})
+// checkPools(t, config)
+// })
+// t.Run("WithCompression-nil-ctors-unregisters", func(t *testing.T) {
+// t.Parallel()
+// opts := []HandlerOption{WithCompression("gzip", nil, nil)}
+// config := newHandlerConfig(testProc, opts)
+// assert.Equal(t, config.CompressionNames, nil)
+// checkPools(t, config)
+// })
+//}
diff --git a/protocol/triple/triple_protocol/connect_ext_test.go b/protocol/triple/triple_protocol/connect_ext_test.go
new file mode 100644
index 000000000..9f8a7a3c9
--- /dev/null
+++ b/protocol/triple/triple_protocol/connect_ext_test.go
@@ -0,0 +1,2392 @@
+// // Copyright 2021-2023 Buf Technologies, Inc.
+// //
+// // Licensed under the Apache License, Version 2.0 (the "License");
+// // you may not use this file except in compliance with the License.
+// // You may obtain a copy of the License at
+// //
+// // http://www.apache.org/licenses/LICENSE-2.0
+// //
+// // Unless required by applicable law or agreed to in writing, software
+// // distributed under the License is distributed on an "AS IS" BASIS,
+// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// // See the License for the specific language governing permissions and
+// // limitations under the License.
+package triple_protocol_test
+
+//
+//import (
+// "bytes"
+// "compress/flate"
+// "compress/gzip"
+// "context"
+// "encoding/binary"
+// "errors"
... 10002 lines suppressed ...