rpc

package
v1.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 5, 2024 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package rpc provides a proto RPC service.

A simple client example (based on the server below):

client, err := New(socketAddr, cred.UID.Int(), cred.GID.Int(), []os.FileMode{0770, 0771})
if err != nil {
	// Do something
}

ctx, cancel := context.WitheTimeout(5 * time.Second)
req := &pb.SumReq{Ints: 1, 2, 3}
resp := &pb.SumResp{}

retry:
	if err := client.Call(ctx, "/math/sum", req, resp); err != nil {
		if rpc.Retryable(err) {
			// Okay, so you probably should do this in a for loop, but I wanted to use
			// a label for the hell of it.
			goto retry
		}
		// Do something here, cause you have a non-retryable error.
	}
	if resp.Err != nil {
		// Do something with the internal error.
	}
	fmt.Printf("Sum of %#v = %d\n", req, resp.Sum)

A simple service works like:

type MathServer struct{}

func (m *MathServer) Sum(ctx context.Context, req []byte]) ([]byte, error) {
	request := &pb.SumReq{}
	if err := proto.Unmarshal(req, request); err != nil {
		return nil, rpc.Errorf(rpc.ETBadData, "request could not be unmarshalled into SumReq: %s", err)
	}

	response := &pb.SumResp{}
	for _, i := range request.Ints {
		response.Sum += i
	}
	b, err := proto.Marshal(response)
	if err != nil {
		return nil, rpc.Errorf(rpc.ETBadData, "request could not be unmarshalled into SumReq: %s", err)
	}
	return b, nil
}

func main() {
	cred, err := uds.Current()
	if err != nil {
		panic(err)
	}

	serv, err := NewServer("socketAddr", cred.UID.Int(), cred.GID.Int(), 0770)
	if err != nil {
		panic(err)
	}

	ms := MathServer{}

	serv.RegisterMethod("/math/sum", ms.Sum)

	if err := serv.Start(); err != nil {
		log.Fatal(err)
	}
}

Note: The server should only return errors to clients when something goes wrong with the RPC. This makes it predictable on the server side when the error is retryable. When the service has an error, I recommend returning the expected response, which should have a dict containing your custom error code and the error message. This allows your clients to decide if they should retry a request.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CredFromCtx

func CredFromCtx(ctx context.Context) uds.Cred

CredFromCtx will extract the Cred from the Context object.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client provides an RPC client using JSON.

func New

func New(socketAddr string, uid, gid int, fileModes []os.FileMode, options ...Option) (*Client, error)

New is the constructor for Client.

func (*Client) Call

func (c *Client) Call(ctx context.Context, method string, req, resp proto.Message) error

Call calls the RPC service. If Context timeout is not set, will default to 5 minutes.

func (*Client) Close

func (c *Client) Close() error

Close closes the underyling connection.

type Option

type Option func(c *Client)

Option is an optional argument to New.

func MaxSize

func MaxSize(size int64) Option

MaxSize is the maximum size a read message is allowed to be. If a message is larger than this, Next() will fail and the underlying connection will be closed.

func SharedPool

func SharedPool(pool *chunk.Pool) Option

SharedPool allows the use of a shared pool of buffers between Client instead of a pool per client. This is useful when clients are short lived and have similar message sizes. Client will panic if the pool does not return a *[]byte object.

type RequestHandler

type RequestHandler = rpc.RequestHandler

RequestHandler will receive a Context object with a Deadline set and you can retrieve the calling process creds with CredFromCtx. The bytes of the request and resp will be the json.Marshal of the response. An error returned is a ErrServer that can not be retried. Generally, service errors should be in the resp and not a returned error. See the note in the package intro.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server provides a proto RPC server.

func NewServer

func NewServer(socketAddr string, uid, gid int, fileMode os.FileMode) (*Server, error)

NewServer is the constructor for a Server.

func (*Server) RegisterMethod

func (s *Server) RegisterMethod(method string, handler RequestHandler)

RegisterMethod registers an RPC method with the server.

func (*Server) Start

func (s *Server) Start() error

Start starts the server. This will block until the server stops.

func (*Server) Stop

func (s *Server) Stop(ctx context.Context) error

Stop stops the server, which will stop listening for new connections. This should slowly kill off existing calls. Stop will return when all calls have completed or the context deadline is reached(or cancelled). A nil error indicates that all jobs were completed. Note: a Server cannot be reused.

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL