2020-11-08 18:28:33 +00:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
2020-11-27 13:00:45 +00:00
|
|
|
"context"
|
2020-11-08 18:28:33 +00:00
|
|
|
"crypto/tls"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
2021-11-23 14:15:47 +00:00
|
|
|
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
2020-11-08 18:28:33 +00:00
|
|
|
"google.golang.org/grpc"
|
|
|
|
"google.golang.org/grpc/credentials"
|
|
|
|
"google.golang.org/grpc/resolver"
|
|
|
|
|
2021-07-17 20:40:06 +00:00
|
|
|
"go.linka.cloud/grpc/registry/noop"
|
2020-11-08 18:28:33 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type Client interface {
|
2020-11-27 13:00:45 +00:00
|
|
|
grpc.ClientConnInterface
|
2020-11-08 18:28:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func New(opts ...Option) (Client, error) {
|
|
|
|
c := &client{opts: &options{}}
|
|
|
|
for _, o := range opts {
|
|
|
|
o(c.opts)
|
|
|
|
}
|
|
|
|
if c.opts.registry == nil {
|
|
|
|
c.opts.registry = noop.New()
|
|
|
|
}
|
|
|
|
resolver.Register(c.opts.registry.ResolverBuilder())
|
|
|
|
c.pool = newPool(DefaultPoolSize, DefaultPoolTTL, DefaultPoolMaxIdle, DefaultPoolMaxStreams)
|
2020-11-27 13:00:45 +00:00
|
|
|
if c.opts.tlsConfig == nil && c.opts.Secure() {
|
|
|
|
c.opts.tlsConfig = &tls.Config{InsecureSkipVerify: true}
|
|
|
|
}
|
|
|
|
if c.opts.tlsConfig != nil {
|
|
|
|
c.opts.dialOptions = append(c.opts.dialOptions, grpc.WithTransportCredentials(credentials.NewTLS(c.opts.tlsConfig)))
|
|
|
|
}
|
2021-09-17 23:39:15 +00:00
|
|
|
if !c.opts.secure {
|
|
|
|
c.opts.dialOptions = append(c.opts.dialOptions, grpc.WithInsecure())
|
|
|
|
}
|
2021-11-23 14:15:47 +00:00
|
|
|
if len(c.opts.unaryInterceptors) > 0 {
|
|
|
|
c.opts.dialOptions = append(c.opts.dialOptions, grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(c.opts.unaryInterceptors...)))
|
|
|
|
}
|
|
|
|
if len(c.opts.streamInterceptors) > 0 {
|
|
|
|
c.opts.dialOptions = append(c.opts.dialOptions, grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(c.opts.streamInterceptors...)))
|
|
|
|
}
|
2022-09-05 10:33:01 +00:00
|
|
|
switch {
|
|
|
|
case c.opts.addr == "":
|
2021-11-22 13:04:47 +00:00
|
|
|
c.addr = fmt.Sprintf("%s:///%s", c.opts.registry.String(), c.opts.name)
|
2022-09-05 10:33:01 +00:00
|
|
|
case strings.HasPrefix(c.opts.addr, "tcp://"):
|
2021-11-22 13:04:47 +00:00
|
|
|
c.addr = strings.Replace(c.opts.addr, "tcp://", "", 1)
|
2022-09-05 10:33:01 +00:00
|
|
|
case strings.HasPrefix(c.opts.addr, "unix:///"):
|
|
|
|
c.addr = c.opts.addr
|
|
|
|
case strings.HasPrefix(c.opts.addr, "unix://"):
|
|
|
|
c.addr = strings.Replace(c.opts.addr, "unix://", "unix:", 1)
|
|
|
|
default:
|
2021-11-22 13:04:47 +00:00
|
|
|
c.addr = c.opts.addr
|
|
|
|
}
|
|
|
|
if c.opts.version != "" && c.opts.addr == "" {
|
2020-11-27 13:00:45 +00:00
|
|
|
c.addr = c.addr + ":" + strings.TrimSpace(c.opts.version)
|
|
|
|
}
|
2020-11-08 18:28:33 +00:00
|
|
|
return c, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type client struct {
|
2020-11-27 13:00:45 +00:00
|
|
|
addr string
|
2020-11-08 18:28:33 +00:00
|
|
|
pool *pool
|
|
|
|
opts *options
|
|
|
|
}
|
|
|
|
|
2020-11-27 13:00:45 +00:00
|
|
|
func (c *client) Invoke(ctx context.Context, method string, args interface{}, reply interface{}, opts ...grpc.CallOption) error {
|
|
|
|
pc, err := c.pool.getConn(c.addr, c.opts.dialOptions...)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2020-11-08 18:28:33 +00:00
|
|
|
}
|
2020-11-27 13:00:45 +00:00
|
|
|
return pc.Invoke(ctx, method, args, reply, opts...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *client) NewStream(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) {
|
|
|
|
pc, err := c.pool.getConn(c.addr, c.opts.dialOptions...)
|
2020-11-08 18:28:33 +00:00
|
|
|
if err != nil {
|
2020-11-27 13:00:45 +00:00
|
|
|
return nil, err
|
2020-11-08 18:28:33 +00:00
|
|
|
}
|
2020-11-27 13:00:45 +00:00
|
|
|
return pc.NewStream(ctx, desc, method, opts...)
|
2020-11-08 18:28:33 +00:00
|
|
|
}
|