ronykit

package module
v0.6.21 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2022 License: BSD-3-Clause Imports: 21 Imported by: 3

README

Go Report Card GitHub release (latest by date including pre-releases) Codecov Status

RonyKit

RonyKit is a library written in Go (Golang), provides the abstraction layer for creating an API server. By defining separate components for each task, you are almost free to develop your API server using RPC (Proto/JSON/...), REST, GraphQL or even with your in-house defined protocol. However, some components are implemented in the 'std' which make it easy to use RonyKit out of the box. In RonyKIT, I wanted to make it more flexible but still very performant. I will maintain two bundles one based on fasthttp and the other provides only rpc over websocket based on two very fast libraries gobwas and gnet, however you are not limited to use those, and can build your own Bundles. To have a better understanding of how it is going to work please check examples folder. in simple-rest-server it shows a very simple hello world app. in mixed-jsonrpc-rest it shows how you can write your services once but use them with multiple formats like REST or RPC.

Contents

Installation

To install RonyKIT package, you need to install Go and set your Go workspace first.

  1. The first need Go installed (version 1.17+ is required), then you can use the below Go command to install RonyKIT.
$ go get -u github.com/clubpay/ronykit/...
  1. Import it in your code:
package main

import "github.com/clubpay/ronykit"
  1. (Optional) You might also need to import some standard bundles provided in the main repo.
package main

import (
	"github.com/clubpay/ronykit/std/gateway/fasthttp"
	"github.com/clubpay/ronykit/std/gateway/fastws"
)

Quick start

You can find some sample codes in the Examples folder.

Define Services and Contracts

In RonyKIT you better to define the description of your services and their contracts using desc package, and it provides you many helper methods. Although you can create your concrete implementations of ronykit.Service and ronykit.Contract, but we strongly recommend you to use desc package.

Define Service Descriptor

The following code demonstrates the steps you need to take to register your service.

package main

import (
	"context"
	"encoding/json"
	"syscall"

	"github.com/clubpay/ronykit"
	"github.com/clubpay/ronykit/desc"
	"github.com/clubpay/ronykit/std/gateway/fasthttp"
)

type echoRequest struct {
	RandomID int64 `json:"randomId"`
}

var serviceDesc = desc.NewService("yourServiceUniqueName").
	AddContract(
		desc.NewContract().
			// Add the selector which this contract will be selected based of. Every bundle have its own selector
			// and here we use our std/fasthttp package.
			AddSelector(
				fasthttp.Selector{
					Method: fasthttp.MethodGet,
					Path:   "/echo/:randomId",
				},
			).
			// Define the input message, it defines the message your handler expects to receive.
			SetInput(&echoRequest{}).
			// Define the output message, it defines the message your handler expects to return.
			SetOutput(&echoResponse{}).
			// Set the handler which is going to handle this request.
			SetHandler(echoHandler),
	)

func main() {
	app := ronykit.NewServer(
		desc.Register(serviceDesc),
	)

	// Start the server
	app.Start(context.Background())

	// Wait for signal to shut down
	app.Shutdown(context.Background(), syscall.SIGHUP)
}

Documentation

Index

Constants

View Source
const (
	CtxServiceName = "__ServiceName__"
	CtxContractID  = "__ContractID__"
	CtxRoute       = "__Route__"
)

Variables

View Source
var (
	ErrNoHandler                   = errors.New("handler is not set for request")
	ErrWriteToClosedConn           = errors.New("write to closed connection")
	ErrDecodeIncomingMessageFailed = errors.New("decoding the incoming message failed")
	ErrEncodeOutgoingMessageFailed = errors.New("encoding the outgoing message failed")
	ErrDispatchFailed              = errors.New("dispatch failed")
)
View Source
var (
	Undefined = Encoding{}
	JSON      = Encoding{/* contains filtered or unexported fields */}
	Proto     = Encoding{/* contains filtered or unexported fields */}
	MSG       = Encoding{/* contains filtered or unexported fields */}
)
View Source
var NoExecuteArg = ExecuteArg{}

Functions

func MarshalMessage added in v0.5.0

func MarshalMessage(m Message) ([]byte, error)

func UnmarshalMessage added in v0.5.0

func UnmarshalMessage(data []byte, m Message) error

Types

type Bundle

type Bundle interface {
	// Start starts the gateway to accept connections.
	Start(ctx context.Context) error
	// Shutdown shuts down the gateway gracefully.
	Shutdown(ctx context.Context) error
	// Register registers the route in the Bundle. This is how Bundle get information
	// about the services and their contracts.
	Register(
		serviceName, contractID string, enc Encoding, sel RouteSelector, input Message,
	)
}

Bundle is the pluggable component of the EdgeServer.

type Cluster

type Cluster interface {
	Bundle
	Members(ctx context.Context) ([]ClusterMember, error)
	MemberByID(ctx context.Context, id string) (ClusterMember, error)
	Me() ClusterMember
	Subscribe(d ClusterDelegate)
}

Cluster identifies all instances of our EdgeServer. The implementation of the Cluster is not forced by the architecture. However, we can break down Cluster implementations into two categories: shared store, or gossip based clusters. In our std package, we provide a store based cluster, which could be integrated with other services with the help of implementing ClusterStore.

type ClusterChannel added in v0.5.0

type ClusterChannel interface {
	RoundTrip(ctx context.Context, targetID string, sendData []byte) (receivedData []byte, err error)
}

type ClusterDelegate

type ClusterDelegate interface {
	OnError(err error)
	OnJoin(members ...ClusterMember)
	OnLeave(memberIDs ...string)
	// OnMessage must be called whenever a new message arrives.
	OnMessage(c Conn, msg []byte)
}

ClusterDelegate is the delegate that connects the Cluster to the rest of the system.

type ClusterMember

type ClusterMember interface {
	ServerID() string
	AdvertisedURL() []string
	RoundTrip(ctx context.Context, sendData []byte) (receivedData []byte, err error)
}

ClusterMember represents an EdgeServer instance in the Cluster.

type ClusterStore added in v0.4.5

type ClusterStore interface {
	// SetMember call whenever the node has changed its state or metadata.
	SetMember(ctx context.Context, clusterMember ClusterMember) error
	// GetMember returns the ClusterMember by its ID.
	GetMember(ctx context.Context, serverID string) (ClusterMember, error)
	// SetLastActive is called periodically and implementor must keep track of last active timestamps
	// of all members and return the correct set in GetActiveMembers.
	SetLastActive(ctx context.Context, serverID string, ts int64) error
	// GetActiveMembers must return a list of ClusterMembers that their last active is larger
	// than the lastActive input.
	GetActiveMembers(ctx context.Context, lastActive int64) ([]ClusterMember, error)
}

ClusterStore is the abstraction of the store for store based cluster.

type Conn

type Conn interface {
	ConnID() uint64
	ClientIP() string
	Write(data []byte) (int, error)
	Stream() bool
	Walk(func(key string, val string) bool)
	Get(key string) string
	Set(key string, val string)
}

Conn represents a connection between EdgeServer and client.

type Context

type Context struct {
	utils.SpinLock
	// contains filtered or unexported fields
}

func (*Context) AddModifier added in v0.3.3

func (ctx *Context) AddModifier(modifiers ...Modifier)

AddModifier adds one or more modifiers to the context which will be executed on each outgoing Envelope before writing it to the wire.

func (*Context) Conn

func (ctx *Context) Conn() Conn

Conn returns the underlying connection

func (*Context) Context

func (ctx *Context) Context() context.Context

Context returns a context.WithCancel which can be used a reference context for other context aware function calls. This context will be canceled at the end of Context lifetime.

func (*Context) ContractID added in v0.4.7

func (ctx *Context) ContractID() string

func (*Context) Error

func (ctx *Context) Error(err error) bool

Error is useful for some kind of errors which you are not going to return it to the connection, or you want to use its side effect for logging, monitoring etc. This will call your ErrHandler. The boolean result indicates if 'err' was an actual error.

func (*Context) Exists

func (ctx *Context) Exists(key string) bool

func (*Context) Get

func (ctx *Context) Get(key string) interface{}

func (*Context) GetBytes

func (ctx *Context) GetBytes(key string, defaultValue []byte) []byte

func (*Context) GetInt32

func (ctx *Context) GetInt32(key string, defaultValue int32) int32

func (*Context) GetInt64

func (ctx *Context) GetInt64(key string, defaultValue int64) int64

func (*Context) GetStatusCode added in v0.4.8

func (ctx *Context) GetStatusCode() int

func (*Context) GetStatusText added in v0.4.8

func (ctx *Context) GetStatusText() string

func (*Context) GetString

func (ctx *Context) GetString(key string, defaultValue string) string

func (*Context) GetUint32

func (ctx *Context) GetUint32(key string, defaultValue uint32) uint32

func (*Context) GetUint64

func (ctx *Context) GetUint64(key string, defaultValue uint64) uint64

func (*Context) HasError added in v0.4.5

func (ctx *Context) HasError() bool

HasError returns true if there is an error set by calling Error method.

func (*Context) In

func (ctx *Context) In() Envelope

In returns the incoming Envelope which received from the connection. You **MUST NOT** call Send method of this Envelope. If you want to return a message/envelope to connection use Out or OutTo methods of the Context

func (*Context) Limited added in v0.4.11

func (ctx *Context) Limited() *LimitedContext

Limited returns a LimitedContext. This is useful when you don't want to give all capabilities of the Context to some other function/method.

func (*Context) Next

func (ctx *Context) Next()

Next sets the next handler which will be called after the current handler.

func (*Context) Out

func (ctx *Context) Out() Envelope

Out generate a new Envelope which could be used to send data to the connection.

func (*Context) OutTo

func (ctx *Context) OutTo(c Conn) Envelope

OutTo is similar to Out except that it lets you send your envelope to other connection. This is useful for scenarios where you want to send cross-client message. For example, in a fictional chat server, you want to pass a message from client A to client B.

func (*Context) PresetHdr added in v0.6.5

func (ctx *Context) PresetHdr(k, v string)

PresetHdr sets the common header key-value pairs so in Out method we don't need to repeatedly set those. This method is useful for some cases if we need to update the header in some middleware before the actual response is prepared. If you only want to set the header for an envelope, you can use Envelope.SetHdr method instead.

func (*Context) PresetHdrMap added in v0.6.5

func (ctx *Context) PresetHdrMap(hdr map[string]string)

PresetHdrMap sets the common header key-value pairs so in Out method we don't need to repeatedly set those. Please refer to PresetHdr for more details

func (*Context) Route

func (ctx *Context) Route() string

func (*Context) ServiceName

func (ctx *Context) ServiceName() string

func (*Context) Set

func (ctx *Context) Set(key string, val interface{}) *Context

func (*Context) SetStatusCode

func (ctx *Context) SetStatusCode(code int)

SetStatusCode set the connection status. It **ONLY** works if the underlying connection is a REST connection.

func (*Context) SetUserContext

func (ctx *Context) SetUserContext(userCtx context.Context)

func (*Context) StopExecution

func (ctx *Context) StopExecution()

StopExecution stops the execution of the next handlers, in other words, when you call this in your handler, any other middleware that are not executed will yet will be skipped over.

func (*Context) Walk

func (ctx *Context) Walk(f func(key string, val interface{}) bool)

type Contract

type Contract interface {
	// ID identifies the contract. This MUST be unique per Service. This MUST NOT be a runtime
	// random number. Since this is used in RemoteExecute method of ClusterMember to execute the
	// right set of handlers on remote EdgeServer.
	ID() string
	// RouteSelector returns a RouteSelector function which selects this Contract based on the
	// client requests.
	RouteSelector() RouteSelector
	// EdgeSelector returns an EdgeSelectorFunc function which selects the EdgeServer instance
	// that the request should forward to for execution.
	EdgeSelector() EdgeSelectorFunc
	Encoding() Encoding
	Input() Message
	Handlers() []HandlerFunc
	Modifiers() []Modifier
}

Contract defines the set of Handlers based on the Query. Query is different per bundles, hence, this is the implementor's task to make sure return correct value based on 'q'. In other words, Contract 'r' must return valid response for 'q's required by Gateway 'gw' in order to be usable by Gateway 'gw' otherwise it panics.

func WrapContract added in v0.3.1

func WrapContract(c Contract, wrappers ...ContractWrapper) Contract

WrapContract wraps a contract, this is useful for adding middlewares to the contract. Some middlewares like OpenTelemetry, Logger, ... could be added to the contract using this function.

type ContractWrapper

type ContractWrapper interface {
	Wrap(Contract) Contract
}

ContractWrapper is like an interceptor which can add Pre- and Post- handlers to all the Contracts of the Contract.

type ContractWrapperFunc

type ContractWrapperFunc func(Contract) Contract

ContractWrapperFunc implements ContractWrapper interface.

func (ContractWrapperFunc) Wrap

func (sw ContractWrapperFunc) Wrap(svc Contract) Contract

type EdgeSelectorFunc added in v0.5.0

type EdgeSelectorFunc func(ctx *LimitedContext) (ClusterMember, error)

EdgeSelectorFunc returns the target EdgeServer in the Cluster. If you have multiple instances of the EdgeServer, and you want to forward some requests to a specific instance, you can set up this function in desc.Contract's SetCoordinator method, then, the receiving EdgeServer will detect the target instance by calling this function and forwards the request to the returned instance. From the external client point of view this forwarding request is not observable.

type EdgeServer

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

EdgeServer is the main component of the ronykit. It glues all other components of the app to each other.

func NewServer

func NewServer(opts ...Option) *EdgeServer

func (*EdgeServer) PrintRoutes added in v0.4.5

func (s *EdgeServer) PrintRoutes(w io.Writer) *EdgeServer

func (*EdgeServer) RegisterBundle

func (s *EdgeServer) RegisterBundle(b Bundle) *EdgeServer

RegisterBundle registers a Bundle to our server. Currently, two types of Bundles are supported: Gateway and Cluster

func (*EdgeServer) RegisterService

func (s *EdgeServer) RegisterService(svc Service) *EdgeServer

RegisterService registers a Service to our server. We need to define the appropriate RouteSelector in each desc.Contract.

func (*EdgeServer) Shutdown

func (s *EdgeServer) Shutdown(ctx context.Context, signals ...os.Signal)

func (*EdgeServer) Start

func (s *EdgeServer) Start(ctx context.Context) *EdgeServer

Start registers services in the registered bundles and start the bundles.

type Encoding added in v0.3.5

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

Encoding defines the encoding of the messages which will be sent/received. Gateway implementor needs to call correct method based on the encoding value.

func CustomEncoding added in v0.6.0

func CustomEncoding(tag string) Encoding

func (Encoding) Tag added in v0.6.0

func (enc Encoding) Tag() string

type Envelope

type Envelope interface {
	SetHdr(key, value string) Envelope
	SetHdrWalker(walker Walker) Envelope
	SetHdrMap(kv map[string]string) Envelope
	GetHdr(key string) string
	WalkHdr(f func(key, val string) bool) Envelope
	SetMsg(msg Message) Envelope
	GetMsg() Message
	// Send writes the envelope to the connection based on the Gateway specification.
	// You **MUST NOT** use the Envelope after calling this method.
	// You **MUST NOT** call this function more than once.
	// You **MUST NOT** call this method on incoming envelopes. i.e. the Envelope that you
	// get from Context.In
	Send()
}

Envelope is an envelope around Message in RonyKIT. Envelopes are created internally by the RonyKIT framework, and provide the abstraction which Bundle implementations could take advantage of. For example in std/fasthttp Envelope headers translate from/to http request/response headers.

type EnvelopeHdr added in v0.4.4

type EnvelopeHdr map[string]string

type ErrHandler

type ErrHandler func(ctx *Context, err error)

ErrHandler is called when an error happens in internal layers. NOTICE: ctx could be nil, make sure you do nil-check before calling its methods.

type ErrorMessage

type ErrorMessage interface {
	GetCode() int
	GetItem() string
	Message
	error
}

ErrorMessage is a special kind of Message which is also an error.

type ExecuteArg added in v0.4.5

type ExecuteArg struct {
	ServiceName string
	ContractID  string
	Route       string
}

type ExecuteFunc

type ExecuteFunc func(arg ExecuteArg)

type Gateway

type Gateway interface {
	Bundle
	// Subscribe will be called by the EdgeServer. These delegate functions
	// must be called by the Gateway implementation. In other words, Gateway communicates
	// with EdgeServer through the GatewayDelegate methods.
	//
	// NOTE: This func will be called only once and before calling Start function.
	Subscribe(d GatewayDelegate)
	// Dispatch receives the messages from external clients and runs the execFunc with appropriate
	// arguments. The user of the Gateway does not need to implement this. If you are using some
	// standard bundles like std/gateway/fasthttp or std/gateway/fastws then all the implementation
	// is taken care of.
	Dispatch(ctx *Context, in []byte) (ExecuteArg, error)
}

Gateway is main component of the EdgeServer. Without Gateway, the EdgeServer is not functional. You can use some standard bundles in std/bundle path. However, if you need special handling of communication between your server and the clients you are free to implement your own Gateway.

type GatewayDelegate

type GatewayDelegate interface {
	// OnOpen must be called whenever a new connection is established.
	OnOpen(c Conn)
	// OnClose must be called whenever the connection is gone.
	OnClose(connID uint64)
	// OnMessage must be called whenever a new message arrives.
	OnMessage(c Conn, wf WriteFunc, msg []byte)
}

GatewayDelegate is the delegate that connects the Gateway to the rest of the system.

type HandlerFunc added in v0.3.2

type HandlerFunc func(ctx *Context)

type HandlerFuncChain added in v0.3.2

type HandlerFuncChain []HandlerFunc

type IncomingRPCContainer added in v0.3.5

type IncomingRPCContainer interface {
	// Unmarshal deserialize the received payload.
	Unmarshal(data []byte) error
	// Fill the actual message which will be later used from Context method In().GetMsg().
	Fill(m Message) error
	// GetHdr to read header. This method is used by RonyKIT to fill Envelope's header fields.
	GetHdr(key string) string
	// GetHdrMap returns all the header key-values.
	GetHdrMap() map[string]string
}

IncomingRPCContainer defines the behavior of RPC message envelopes. Basically in RPC communication the actual message should be contained in some kind of container. This interface defines a set of guidelines for the implementation of those containers. The user of the RonyKIT does not need to use this, and it is basically useful for Bundle developers. Although even Bundle developers are not forced to use this interface in their implementation, but they are encouraged to.

Example implementations: common.SimpleIncomingJSONRPC

type IncomingRPCFactory added in v0.3.5

type IncomingRPCFactory func() IncomingRPCContainer

type JSONMarshaler added in v0.5.0

type JSONMarshaler interface {
	MarshalJSON() ([]byte, error)
}

type JSONUnmarshaler added in v0.5.0

type JSONUnmarshaler interface {
	UnmarshalJSON([]byte) error
}

type LimitedContext added in v0.4.5

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

LimitedContext is a wrapper around Context, which limit the capabilities of the original Context. This is useful in cases where we need to pass the Context, but we do not want to give access to all the exposed methods. For example this is used in EdgeSelectorFunc.

func (*LimitedContext) Conn added in v0.4.5

func (ctx *LimitedContext) Conn() Conn

Conn returns the underlying connection

func (*LimitedContext) Context added in v0.4.5

func (ctx *LimitedContext) Context() context.Context

Context returns a context.WithCancel which can be used a reference context for other context aware function calls. This context will be canceled at the end of Context lifetime.

func (*LimitedContext) In added in v0.4.5

func (ctx *LimitedContext) In() Envelope

In returns the incoming Envelope which contains the client's request.

func (*LimitedContext) Route added in v0.4.5

func (ctx *LimitedContext) Route() string

func (*LimitedContext) ServiceName added in v0.4.5

func (ctx *LimitedContext) ServiceName() string

func (*LimitedContext) SetHdr added in v0.4.5

func (ctx *LimitedContext) SetHdr(k, v string)

SetHdr sets the common header key-value pairs so in Out method we don't need to repeatedly set those. If you only want to set the header for an envelope, you can use Envelope.SetHdr method instead.

func (*LimitedContext) SetHdrMap added in v0.4.5

func (ctx *LimitedContext) SetHdrMap(hdr map[string]string)

SetHdrMap sets the common header key-value pairs so in Out method we don't need to repeatedly set those.

type Logger

type Logger interface {
	Debug(args ...interface{})
	Debugf(format string, args ...interface{})
	Error(args ...interface{})
	Errorf(format string, args ...interface{})
}

type Marshaler added in v0.5.0

type Marshaler interface {
	Marshal() ([]byte, error)
}

type Message

type Message interface{}

type MessageFactoryFunc

type MessageFactoryFunc func() Message

func CreateMessageFactory

func CreateMessageFactory(in Message) MessageFactoryFunc

type Modifier

type Modifier func(envelope Envelope)

Modifier is a function which can modify the outgoing Envelope before sending it to the client. Modifier only applies to outgoing envelopes.

type Option

type Option func(s *EdgeServer)

func RegisterBundle

func RegisterBundle(bundles ...Bundle) Option

RegisterBundle lets you register a bundle in constructor of the EdgeServer. However, you still can EdgeServer.RegisterBundle method after the constructor. But you must be noticed that this is method is not concurrent safe.

func RegisterService

func RegisterService(services ...Service) Option

func WithErrorHandler

func WithErrorHandler(h ErrHandler) Option

WithErrorHandler registers a global error handler to catch any error that happens before EdgeServer can deliver incoming message to the handler, or delivering the outgoing message to the client. Internal errors are usually wrapped and could be checked for better error handling. You can check with errors.Is function to see if the error is one of the following: ErrDispatchFailed, ErrWriteToClosedConn, ErrNoHandler ErrDecodeIncomingMessageFailed,, ErrEncodeOutgoingMessageFailed

func WithLogger

func WithLogger(l Logger) Option

func WithShutdownTimeout added in v0.6.16

func WithShutdownTimeout(d time.Duration) Option

WithShutdownTimeout sets the maximum time to wait until all running request to finish. Default is to wait forever.

type OutgoingRPCContainer added in v0.3.5

type OutgoingRPCContainer interface {
	// Marshal serializes the contained message
	Marshal() ([]byte, error)
	// SetHdr set the header.
	SetHdr(k, v string)
	// SetPayload set the body/payload of the container with the actual Message.
	SetPayload(m Message)
}

OutgoingRPCContainer define the behavior of RPC message envelope. Similar to IncomingRPCContainer but in another direction.

Example implementations: common.SimpleOutgoingJSONRPC

type OutgoingRPCFactory added in v0.3.5

type OutgoingRPCFactory func() OutgoingRPCContainer

type ProtoMarshaler added in v0.5.0

type ProtoMarshaler interface {
	MarshalProto() ([]byte, error)
}

type ProtoUnmarshaler added in v0.5.0

type ProtoUnmarshaler interface {
	UnmarshalProto([]byte) error
}

type RESTConn

type RESTConn interface {
	Conn
	GetMethod() string
	GetHost() string
	// GetRequestURI returns uri without Method and Host
	GetRequestURI() string
	// GetPath returns uri without Method, Host and Query parameters.
	GetPath() string
	Form() (*multipart.Form, error)
	SetStatusCode(code int)
	Redirect(code int, url string)
}

RESTConn could be implemented by Gateway, so in Dispatcher user can check if Conn also implements RESTConn then it has more information about the RESTConn request.

type RESTRouteSelector

type RESTRouteSelector interface {
	RouteSelector
	GetMethod() string
	GetPath() string
}

RESTRouteSelector defines the RouteSelector which could be used in REST operations Gateway implementation which handle REST requests could check the selector if it supports REST.

type RPCRouteSelector

type RPCRouteSelector interface {
	RouteSelector
	GetPredicate() string
}

RPCRouteSelector defines the RouteSelector which could be used in RPC operations. Gateway implementation which handle RPC requests could check the selector if it supports RPC

type RawMessage

type RawMessage []byte

RawMessage is a bytes slice which could be used as Message. This is helpful for raw data messages.

func (*RawMessage) Copy added in v0.5.4

func (rm *RawMessage) Copy(in []byte)

func (RawMessage) Marshal

func (rm RawMessage) Marshal() ([]byte, error)

type RouteSelector

type RouteSelector interface {
	Query(q string) interface{}
	GetEncoding() Encoding
}

RouteSelector holds information about how this Contract is going to be selected. Each Gateway may need different information to route the request to the right Contract. RouteSelector is actually a base interface and Gateway implementors usually implement either RESTRouteSelector, RPCRouteSelector or both.

type Service

type Service interface {
	// Name of the service which must be unique per EdgeServer.
	Name() string
	// Contracts returns a list of APIs which this service provides.
	Contracts() []Contract
}

Service defines a set of RPC handlers which usually they are related to one service. Name must be unique per each Gateway.

func WrapService

func WrapService(svc Service, wrappers ...ServiceWrapper) Service

WrapService wraps a service, this is useful for adding middlewares to the service. Some middlewares like OpenTelemetry, Logger, ... could be added to the service using this function.

func WrapServiceContracts added in v0.4.5

func WrapServiceContracts(svc Service, wrapper ...ContractWrapper) Service

type ServiceWrapper

type ServiceWrapper interface {
	Wrap(Service) Service
}

ServiceWrapper lets you add customizations to your service. A specific case of it is serviceInterceptor which can add Pre- and Post- handlers to all the Contracts of the Service.

type ServiceWrapperFunc

type ServiceWrapperFunc func(Service) Service

func (ServiceWrapperFunc) Wrap

func (sw ServiceWrapperFunc) Wrap(svc Service) Service

type TestContext added in v0.4.4

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

TestContext is useful for writing end-to-end tests for your Contract handlers.

func NewTestContext added in v0.4.4

func NewTestContext() *TestContext

func (*TestContext) Input added in v0.4.4

func (testCtx *TestContext) Input(m Message, hdr EnvelopeHdr) *TestContext

func (*TestContext) Receiver added in v0.6.4

func (testCtx *TestContext) Receiver(f func(out ...Envelope) error) *TestContext

func (*TestContext) Run added in v0.4.4

func (testCtx *TestContext) Run(stream bool) error

func (*TestContext) RunREST added in v0.4.5

func (testCtx *TestContext) RunREST() error

func (*TestContext) SetClientIP added in v0.4.5

func (testCtx *TestContext) SetClientIP(ip string) *TestContext

func (*TestContext) SetHandler added in v0.4.4

func (testCtx *TestContext) SetHandler(h ...HandlerFunc) *TestContext

type Unmarshaler added in v0.5.0

type Unmarshaler interface {
	Unmarshal([]byte) error
}

type Walker

type Walker interface {
	Walk(f func(k, v string) bool)
}

type WriteFunc

type WriteFunc func(conn Conn, e Envelope) error

Jump to

Keyboard shortcuts

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