quasizero

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: May 17, 2019 License: Apache-2.0 Imports: 11 Imported by: 0

README

QuasiZero

GoDoc Build Status License

A Go TCP server (and client) implementation, optimised for low latency and pipelined throughput.

Usage

Server:

// define a handler
echoHandler := quasizero.HandlerFunc(func(req *quasizero.Request) (*quasizero.Response, error) {
  return &quasizero.Response{Payload: req.Payload}, nil
})

// init a server
srv := quasizero.NewServer(map[int32]quasizero.Handler{
  1: echoHandler,
}, nil)

// listen and serve
lis, err := net.Listen("tcp", ":11111")
if err != nil {
  // handle error ...
}
defer lis.Close()

if err := srv.Serve(lis); err != nil {
  // handle error ...
}

Client:

client, err := quasizero.NewClient(context.TODO(), "10.0.0.1:11111", nil)
if err != nil {
  // handle error ...
}
defer client.Close()

// send an echo request
res, err := client.Call(&quasizero.Request{Code: 1, Payload: []byte("hello")})
if err != nil {
  // handle error ...
}
fmt.Printf("server responded to ECHO with %q\n", res.Payload)

Documentation

Please see the API documentation for package and API descriptions and examples.

Documentation

Overview

Package quasizero implements a general purpose, ultra-low latency TCP server.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"time"

	"github.com/bsm/quasizero"
)

func main() {
	// start a TCP listener
	lis, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		panic(err)
	}
	defer lis.Close()

	// define command map
	cmds := map[int32]quasizero.Handler{
		// ECHO
		1: quasizero.HandlerFunc(func(req *quasizero.Request, res *quasizero.Response) error {
			res.Set(req.Payload)
			return nil
		}),

		// SHUTDOWN
		9: quasizero.HandlerFunc(func(req *quasizero.Request, res *quasizero.Response) error {
			go func() {
				time.Sleep(time.Second)
				_ = lis.Close()
			}()
			res.SetString("OK")
			return nil
		}),
	}

	// start serving (in background)
	go func() {
		srv := quasizero.NewServer(cmds, nil)
		if err := srv.Serve(lis); err != nil {
			panic(err)
		}
	}()

	// connect client
	clnt, err := quasizero.NewClient(context.TODO(), lis.Addr().String(), nil)
	if err != nil {
		panic(err)
	}
	defer clnt.Close()

	// send an echo request
	res1, err := clnt.Call(&quasizero.Request{Code: 1, Payload: []byte("hello")})
	if err != nil {
		panic(err)
	}
	fmt.Printf("server responded to ECHO with %q\n", res1.Payload)

	// send a shutdown request
	res2, err := clnt.Call(&quasizero.Request{Code: 9})
	if err != nil {
		panic(err)
	}
	fmt.Printf("server responded to SHUTDOWN with %q\n", res2.Payload)

}
Output:

server responded to ECHO with "hello"
server responded to SHUTDOWN with "OK"

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

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

Client holds a pool of connections to a quasizero server instance.

func NewClient

func NewClient(ctx context.Context, addr string, opt *pool.Options) (*Client, error)

NewClient connects a client.

func NewClientDialer

func NewClientDialer(ctx context.Context, d *net.Dialer, addr string, opt *pool.Options) (*Client, error)

NewClientDialer connects a client through a custom dialer.

func (*Client) Call

func (c *Client) Call(req *Request) (*Response, error)

Call executes a single command and returns a response.

func (*Client) Close

func (c *Client) Close() error

Close closes all connections.

func (*Client) Pipeline

func (c *Client) Pipeline() *Pipeline

Pipeline starts a pipeline.

type Handler

type Handler interface {
	// ServeQZ serves a request.
	ServeQZ(*Request, *Response) error
}

Handler instances process commands.

type HandlerFunc

type HandlerFunc func(*Request, *Response) error

HandlerFunc is a Handler short-cut.

func (HandlerFunc) ServeQZ

func (f HandlerFunc) ServeQZ(req *Request, res *Response) error

ServeQZ implements the Handler interface.

type Pipeline

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

Pipeline can execute commands.

func (*Pipeline) Call

func (p *Pipeline) Call(req *Request)

Call adds a call to the pipeline.

func (*Pipeline) Exec

func (p *Pipeline) Exec() (ResponseBatch, error)

Exec executes the pipeline and returns responses.

func (*Pipeline) Reset

func (p *Pipeline) Reset()

Reset resets the pipeline.

type Request

type Request struct {
	// Request/command code.
	Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
	// Custom metadata.
	Metadata map[string]string `` /* 157-byte string literal not displayed */
	// Raw payload.
	Payload              []byte   `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (*Request) Descriptor

func (*Request) Descriptor() ([]byte, []int)

func (*Request) GetCode

func (m *Request) GetCode() int32

func (*Request) GetMetadata

func (m *Request) GetMetadata() map[string]string

func (*Request) GetPayload

func (m *Request) GetPayload() []byte

func (*Request) ProtoMessage

func (*Request) ProtoMessage()

func (*Request) Reset

func (m *Request) Reset()

func (*Request) SetMeta

func (m *Request) SetMeta(key, value string)

SetMeta sets a key/value metadata pair.

func (*Request) String

func (m *Request) String() string

func (*Request) XXX_DiscardUnknown

func (m *Request) XXX_DiscardUnknown()

func (*Request) XXX_Marshal

func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*Request) XXX_Merge

func (m *Request) XXX_Merge(src proto.Message)

func (*Request) XXX_Size

func (m *Request) XXX_Size() int

func (*Request) XXX_Unmarshal

func (m *Request) XXX_Unmarshal(b []byte) error

type Response

type Response struct {
	// Optional error message.
	ErrorMessage string `protobuf:"bytes,1,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"`
	// Custom metadata.
	Metadata map[string]string `` /* 157-byte string literal not displayed */
	// Raw payload.
	Payload              []byte   `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (*Response) Descriptor

func (*Response) Descriptor() ([]byte, []int)

func (*Response) GetErrorMessage

func (m *Response) GetErrorMessage() string

func (*Response) GetMetadata

func (m *Response) GetMetadata() map[string]string

func (*Response) GetPayload

func (m *Response) GetPayload() []byte

func (*Response) ProtoMessage

func (*Response) ProtoMessage()

func (*Response) Release

func (m *Response) Release()

Release releases the message and returns it to the memory pool. You must not use it after calling this function.

func (*Response) Reset

func (m *Response) Reset()

func (*Response) Set

func (m *Response) Set(data []byte)

Set sets the payload efficiently.

func (*Response) SetError

func (m *Response) SetError(err error)

SetError sets an error.

func (*Response) SetErrorf

func (m *Response) SetErrorf(msg string, args ...interface{})

SetErrorf sets a formatted error message.

func (*Response) SetMeta

func (m *Response) SetMeta(key, value string)

SetMeta sets a key/value metadata pair.

func (*Response) SetString

func (m *Response) SetString(data string)

SetString sets the payload efficiently.

func (*Response) String

func (m *Response) String() string

func (*Response) XXX_DiscardUnknown

func (m *Response) XXX_DiscardUnknown()

func (*Response) XXX_Marshal

func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*Response) XXX_Merge

func (m *Response) XXX_Merge(src proto.Message)

func (*Response) XXX_Size

func (m *Response) XXX_Size() int

func (*Response) XXX_Unmarshal

func (m *Response) XXX_Unmarshal(b []byte) error

type ResponseBatch

type ResponseBatch []*Response

ResponseBatch is a slice of individual responses.

func (ResponseBatch) Release

func (b ResponseBatch) Release()

Release releases the response batch and returns it to the memory pool. You must not use the batch or any of the included responses after calling this function.

type Server

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

Server instances can handle client requests.

func NewServer

func NewServer(commands map[int32]Handler, cfg *ServerConfig) *Server

NewServer creates a new server instance.

func (*Server) Serve

func (s *Server) Serve(lis net.Listener) error

Serve accepts incoming connections on a listener, creating a new service goroutine for each.

type ServerConfig

type ServerConfig struct {
	// Timeout represents the per-request socket read/write timeout.
	// Default: 0 (disabled)
	Timeout time.Duration

	// IdleTimeout forces servers to close idle connection once timeout is reached.
	// Default: 0 (disabled)
	IdleTimeout time.Duration

	// If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence
	// of communication. This is useful for two reasons:
	// 1) Detect dead peers.
	// 2) Take the connection alive from the point of view of network
	//    equipment in the middle.
	// On Linux, the specified value (in seconds) is the period used to send ACKs.
	// Note that to close the connection the double of the time is needed.
	// On other kernels the period depends on the kernel configuration.
	// Default: 0 (disabled)
	TCPKeepAlive time.Duration

	// OnError is called on client errors. Use for verbose logging.
	OnError func(error)
}

ServerConfig holds the server configuration

Jump to

Keyboard shortcuts

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