[#263] Implement client for exchanging raw Protobuf messages
Implement generic `Client` that can communicate with the remote server via protobuf `Message`'s. The client can uniformly execute any protobuf RPC on the remote server using any of the supported transport protocols. Currently only gRPC protocol is supported. Additionally implement helpful functions to transmit messages by one of the flow types: unary, client- or server-side stream. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
c61656a43f
commit
30c6ca0714
6 changed files with 364 additions and 0 deletions
83
rpc/client/init.go
Normal file
83
rpc/client/init.go
Normal file
|
@ -0,0 +1,83 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/rpc/common"
|
||||
"github.com/nspcc-dev/neofs-api-go/rpc/grpc"
|
||||
"github.com/nspcc-dev/neofs-api-go/rpc/message"
|
||||
)
|
||||
|
||||
// MessageReader is an interface of the Message reader.
|
||||
type MessageReader interface {
|
||||
// ReadMessage reads the next Message.
|
||||
//
|
||||
// Returns io.EOF if there are no more messages to read.
|
||||
// ReadMessage should not be called after io.EOF occasion.
|
||||
ReadMessage(message.Message) error
|
||||
}
|
||||
|
||||
// MessageWriter is an interface of the Message writer.
|
||||
type MessageWriter interface {
|
||||
// WriteMessage writers the next Message.
|
||||
//
|
||||
// WriteMessage should not be called after any error.
|
||||
WriteMessage(message.Message) error
|
||||
}
|
||||
|
||||
// MessageReadWriter is a component interface
|
||||
// for transmitting raw Protobuf messages.
|
||||
type MessageReadWriter interface {
|
||||
MessageReader
|
||||
MessageWriter
|
||||
|
||||
// Closes the communication session.
|
||||
//
|
||||
// All calls to send/receive messages must be done before closing.
|
||||
io.Closer
|
||||
}
|
||||
|
||||
// Init initiates a messaging session and returns the interface for message transmitting.
|
||||
func (c *Client) Init(info common.CallMethodInfo, opts ...CallOption) (MessageReadWriter, error) {
|
||||
prm := defaultCallParameters()
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(prm)
|
||||
}
|
||||
|
||||
return c.initGRPC(info, prm)
|
||||
}
|
||||
|
||||
type rwGRPC struct {
|
||||
grpc.MessageReadWriter
|
||||
}
|
||||
|
||||
func (g rwGRPC) ReadMessage(m message.Message) error {
|
||||
// Can be optimized: we can create blank message here.
|
||||
gm := m.ToGRPCMessage()
|
||||
|
||||
if err := g.MessageReadWriter.ReadMessage(gm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return m.FromGRPCMessage(gm)
|
||||
}
|
||||
|
||||
func (g rwGRPC) WriteMessage(m message.Message) error {
|
||||
return g.MessageReadWriter.WriteMessage(m.ToGRPCMessage())
|
||||
}
|
||||
|
||||
func (c *Client) initGRPC(info common.CallMethodInfo, prm *callParameters) (MessageReadWriter, error) {
|
||||
if err := c.createGRPCClient(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rw, err := c.gRPCClient.Init(info, prm.callOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &rwGRPC{
|
||||
MessageReadWriter: rw,
|
||||
}, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue