frostfs-api-go/v2/netmap/client.go
Leonard Lyubich 88d6857a3c [#259] netmap: Add NetworkInfo call to Client
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2021-02-19 16:25:53 +03:00

190 lines
4.7 KiB
Go

package netmap
import (
"context"
"github.com/nspcc-dev/neofs-api-go/v2/client"
netmap "github.com/nspcc-dev/neofs-api-go/v2/netmap/grpc"
"github.com/pkg/errors"
"google.golang.org/grpc"
)
// Client represents universal netmap transport client.
type Client struct {
cLocalNodeInfo *localNodeInfoClient
cNetworkInfo *networkInfoClient
}
// Option represents Client option.
type Option func(*cfg)
type cfg struct {
proto client.Protocol
globalOpts []client.Option
gRPC cfgGRPC
}
type cfgGRPC struct {
serviceClient netmap.NetmapServiceClient
grpcCallOpts []grpc.CallOption
callOpts []netmap.Option
client *netmap.Client
}
type localNodeInfoClient struct {
requestConverter func(*LocalNodeInfoRequest) interface{}
caller func(context.Context, interface{}) (interface{}, error)
responseConverter func(interface{}) *LocalNodeInfoResponse
}
type networkInfoClient struct {
requestConverter func(*NetworkInfoRequest) interface{}
caller func(context.Context, interface{}) (interface{}, error)
responseConverter func(interface{}) *NetworkInfoResponse
}
// LocalNodeInfo sends LocalNodeInfoRequest over the network.
func (c *Client) LocalNodeInfo(ctx context.Context, req *LocalNodeInfoRequest) (*LocalNodeInfoResponse, error) {
resp, err := c.cLocalNodeInfo.caller(ctx, c.cLocalNodeInfo.requestConverter(req))
if err != nil {
return nil, errors.Wrap(err, "could not send local node info request")
}
return c.cLocalNodeInfo.responseConverter(resp), nil
}
// NetworkInfo sends NetworkInfoRequest over the network.
func (c *Client) NetworkInfo(ctx context.Context, req *NetworkInfoRequest) (*NetworkInfoResponse, error) {
resp, err := c.cNetworkInfo.caller(ctx, c.cNetworkInfo.requestConverter(req))
if err != nil {
return nil, errors.Wrap(err, "could not send network info request")
}
return c.cNetworkInfo.responseConverter(resp), nil
}
func defaultCfg() *cfg {
return &cfg{
proto: client.ProtoGRPC,
}
}
// NewClient is a constructor for netmap transport client.
func NewClient(opts ...Option) (*Client, error) {
cfg := defaultCfg()
for i := range opts {
opts[i](cfg)
}
var err error
switch cfg.proto {
case client.ProtoGRPC:
var c *netmap.Client
if c, err = newGRPCClient(cfg); err != nil {
break
}
return &Client{
cLocalNodeInfo: &localNodeInfoClient{
requestConverter: func(req *LocalNodeInfoRequest) interface{} {
return LocalNodeInfoRequestToGRPCMessage(req)
},
caller: func(ctx context.Context, req interface{}) (interface{}, error) {
return c.LocalNodeInfo(ctx, req.(*netmap.LocalNodeInfoRequest))
},
responseConverter: func(resp interface{}) *LocalNodeInfoResponse {
return LocalNodeInfoResponseFromGRPCMessage(resp.(*netmap.LocalNodeInfoResponse))
},
},
cNetworkInfo: &networkInfoClient{
requestConverter: func(req *NetworkInfoRequest) interface{} {
return NetworkInfoRequestToGRPCMessage(req)
},
caller: func(ctx context.Context, req interface{}) (interface{}, error) {
return c.NetworkInfo(ctx, req.(*netmap.NetworkInfoRequest))
},
responseConverter: func(resp interface{}) *NetworkInfoResponse {
return NetworkInfoResponseFromGRPCMessage(resp.(*netmap.NetworkInfoResponse))
},
},
}, nil
default:
err = client.ErrProtoUnsupported
}
return nil, errors.Wrapf(err, "could not create %s Netmap client", cfg.proto)
}
func newGRPCClient(cfg *cfg) (*netmap.Client, error) {
var err error
if cfg.gRPC.client == nil {
if cfg.gRPC.serviceClient == nil {
conn, err := client.NewGRPCClientConn(cfg.globalOpts...)
if err != nil {
return nil, errors.Wrap(err, "could not open gRPC client connection")
}
cfg.gRPC.serviceClient = netmap.NewNetmapServiceClient(conn)
}
cfg.gRPC.client, err = netmap.NewClient(
cfg.gRPC.serviceClient,
append(
cfg.gRPC.callOpts,
netmap.WithCallOptions(cfg.gRPC.grpcCallOpts),
)...,
)
}
return cfg.gRPC.client, err
}
// WithGlobalOpts sets global client options to client.
func WithGlobalOpts(v ...client.Option) Option {
return func(c *cfg) {
if len(v) > 0 {
c.globalOpts = v
}
}
}
// WithGRPCServiceClient sets existing service client.
func WithGRPCServiceClient(v netmap.NetmapServiceClient) Option {
return func(c *cfg) {
c.gRPC.serviceClient = v
}
}
// WithGRPCServiceClient sets GRPC specific call options.
func WithGRPCCallOpts(v []grpc.CallOption) Option {
return func(c *cfg) {
c.gRPC.grpcCallOpts = v
}
}
// WithGRPCServiceClient sets GRPC specific client options.
func WithGRPCClientOpts(v []netmap.Option) Option {
return func(c *cfg) {
c.gRPC.callOpts = v
}
}
// WithGRPCServiceClient sets existing GRPC client.
func WithGRPCClient(v *netmap.Client) Option {
return func(c *cfg) {
c.gRPC.client = v
}
}