Giter Club home page Giter Club logo

execrpc's Introduction

Tests on Linux, MacOS and Windows Go Report Card GoDoc

This library implements a simple, custom RPC protocol via os/exex and stdin and stdout. Both server and client comes in a raw ([]byte) and strongly typed variant (using Go generics).

A strongly typed client may look like this:

// Define the request, message and receipt types for the RPC call.
client, err := execrpc.StartClient(
	client, err := execrpc.StartClient(
	execrpc.ClientOptions[model.ExampleConfig, model.ExampleRequest, model.ExampleMessage, model.ExampleReceipt]{
		ClientRawOptions: execrpc.ClientRawOptions{
			Version: 1,
			Cmd:     "go",
			Dir:     "./examples/servers/typed",
			Args:    []string{"run", "."},
			Env:     env,
			Timeout: 30 * time.Second,
		},
		Config: model.ExampleConfig{},
		Codec:  codec,
	},
)

if err != nil {
	log.Fatal(err)
}

// Consume standalone messages (e.g. log messages) in its own goroutine.
go func() {
	for msg := range client.MessagesRaw() {
		fmt.Println("got message", string(msg.Body))
	}
}()

// Execute the request.
result := client.Execute(model.ExampleRequest{Text: "world"})

// Check for errors.
if err := result.Err(); err != nil {
	log.Fatal(err)
}

// Consume the messages.
for m := range result.Messages() {
	fmt.Println(m)
}

// Wait for the receipt.
receipt := <-result.Receipt()

// Check again for errors.
if err := result.Err(); err != nil {
	log.Fatal(err)
}

fmt.Println(receipt.Text)

// Close the client.
if err := client.Close(); err != nil {
	log.Fatal(err)
}

To get the best performance you should keep the client open as long as its needed โ€“ and store it as a shared object; it's safe and encouraged to call Execute from multiple goroutines.

And the server side of the above:

func main() {
	log.SetFlags(0)
	log.SetPrefix("readme-example: ")

	var clientConfig model.ExampleConfig

	server, err := execrpc.NewServer(
		execrpc.ServerOptions[model.ExampleConfig, model.ExampleRequest, model.ExampleMessage, model.ExampleReceipt]{
			// Optional function to provide a hasher for the ETag.
			GetHasher: func() hash.Hash {
				return fnv.New64a()
			},

			// Allows you to delay message delivery, and drop
			// them after reading the receipt (e.g. the ETag matches the ETag seen by client).
			DelayDelivery: false,

			// Optional function to initialize the server
			// with the client configuration.
			// This will be called once on server start.
			Init: func(cfg model.ExampleConfig) error {
				clientConfig = cfg
				return clientConfig.Init()
			},

			// Handle the incoming call.
			Handle: func(c *execrpc.Call[model.ExampleRequest, model.ExampleMessage, model.ExampleReceipt]) {
				// Raw messages are passed directly to the client,
				// typically used for log messages.
				c.SendRaw(
					execrpc.Message{
						Header: execrpc.Header{
							Version: 32,
							Status:  150,
						},
						Body: []byte("log message"),
					},
				)

				// Enqueue one or more messages.
				c.Enqueue(
					model.ExampleMessage{
						Hello: "Hello 1!",
					},
					model.ExampleMessage{
						Hello: "Hello 2!",
					},
				)

				c.Enqueue(
					model.ExampleMessage{
						Hello: "Hello 3!",
					},
				)

				// Wait for the framework generated receipt.
				receipt := <-c.Receipt()

				// ETag provided by the framework.
				// A hash of all message bodies.
				// fmt.Println("Receipt:", receipt.ETag)

				// Modify if needed.
				receipt.Size = uint32(123)
				receipt.Text = "echoed: " + c.Request.Text

				// Close the message stream and send the receipt.
				// Pass true to drop any queued messages,
				// this is only relevant if DelayDelivery is enabled.
				c.Close(false, receipt)
			},
		},
	)
	if err != nil {
		handleErr(err)
	}

	if err := server.Start(); err != nil {
		handleErr(err)
	}
}

func handleErr(err error) {
	log.Fatalf("error: failed to start typed echo server: %s", err)
}

Generate ETag

The server can generate an ETag for the messages. This is a hash of all message bodies.

To enable this:

  1. Provide a GetHasher function to the server options.
  2. Have the Receipt implement the TagProvider interface.

Note that there are three different optional E-interfaces for the Receipt:

  1. TagProvider for the ETag.
  2. SizeProvider for the size.
  3. LastModifiedProvider for the last modified timestamp.

A convenient struct that can be embedded in your Receipt that implements all of these is the Identity.

Status Codes

The status codes in the header between 1 and 99 are reserved for the system. This will typically be used to catch decoding/encoding errors on the server.

execrpc's People

Contributors

bep avatar

Stargazers

Runlong avatar Camilo E. Hidalgo Estevez avatar tsingson avatar astrolemonade avatar Sven Greb avatar  avatar Shohei Ueda avatar Vlad Oros avatar Marcondes Viana avatar Ayomide AJAYI avatar  avatar Takeshi Sato avatar Abanoub Hanna avatar

Watchers

 avatar  avatar Runlong avatar  avatar

execrpc's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.