package client import ( "errors" "io" "sync" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/common" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message" ) // SendUnary initializes communication session by RPC info, performs unary RPC // and closes the session. func SendUnary(cli *Client, info common.CallMethodInfo, req, resp message.Message, opts ...CallOption) error { rw, err := cli.Init(info, opts...) if err != nil { return err } err = rw.WriteMessage(req) if err != nil { return err } err = rw.ReadMessage(resp) if err != nil { return err } return rw.Close() } // MessageWriterCloser wraps MessageWriter // and io.Closer interfaces. type MessageWriterCloser interface { MessageWriter io.Closer } type clientStreamWriterCloser struct { MessageReadWriter resp message.Message } func (c *clientStreamWriterCloser) Close() error { err := c.MessageReadWriter.Close() if err != nil { return err } return c.ReadMessage(c.resp) } // OpenClientStream initializes communication session by RPC info, opens client-side stream // and returns its interface. // // All stream writes must be performed before the closing. Close must be called once. func OpenClientStream(cli *Client, info common.CallMethodInfo, resp message.Message, opts ...CallOption) (MessageWriterCloser, error) { rw, err := cli.Init(info, opts...) if err != nil { return nil, err } return &clientStreamWriterCloser{ MessageReadWriter: rw, resp: resp, }, nil } // MessageReaderCloser wraps MessageReader // and io.Closer interface. type MessageReaderCloser interface { MessageReader io.Closer } type serverStreamReaderCloser struct { rw MessageReadWriter once sync.Once req message.Message } func (s *serverStreamReaderCloser) ReadMessage(msg message.Message) error { var err error s.once.Do(func() { err = s.rw.WriteMessage(s.req) }) if err != nil { return err } err = s.rw.ReadMessage(msg) if !errors.Is(err, io.EOF) { return err } err = s.rw.Close() if err != nil { return err } return io.EOF } // OpenServerStream initializes communication session by RPC info, opens server-side stream // and returns its interface. // // All stream reads must be performed before the closing. Close must be called once. func OpenServerStream(cli *Client, info common.CallMethodInfo, req message.Message, opts ...CallOption) (MessageReader, error) { rw, err := cli.Init(info, opts...) if err != nil { return nil, err } return &serverStreamReaderCloser{ rw: rw, req: req, }, nil }