eznode

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Dec 9, 2022 License: MIT Imports: 13 Imported by: 2

README

eznode

Load balancing and failed requests recovery with respecting to node request rate limit for blockchain nodes.

Why

When working with a blockchain application, you need to read the blockchain data and process it. blockchain nodes doens't always respond to requests or doesn't respond properly. Sometimes there is two public node but they have request rate limit.

For application, it's important to know the node that is responding to the request. With eznode you improve your application SLA, load balancing between nodes and using public node without thinking about rate limit (you may still face rate limit if you request more than nodes can handle).

Features

  • Load Balance
  • Failed Request Recovery
  • Node Request Rate Limit
  • Disable/Enable Nodes
  • Prioritize Nodes
  • Node Performance Statistics

Usage

Install eznode:

go get github.com/amovah/eznode

Create a go file then:

package main

import (
	"fmt"
	"github.com/amovah/eznode"
	"time"
	"net/http"
)

func main() {
	node1 := eznode.NewChainNode(eznode.ChainNodeData{
		Name: "node 1",
		Url:  "https://example.com",
		Limit: eznode.ChainNodeLimit{
			Count: 10,
			Per:   5 * time.Second,
		},
		RequestTimeout: 10 * time.Second,
		Priority:       1,
		Middleware:     nil, // optional
	})

	node2 := eznode.NewChainNode(eznode.ChainNodeData{
		Name: "node 2",
		Url:  "https://example.com",
		Limit: eznode.ChainNodeLimit{
			Count: 10,
			Per:   5 * time.Second,
		},
		RequestTimeout: 10 * time.Second,
		Priority:       2,
		Middleware:     nil, // optional
	})

	chain := eznode.NewChain(eznode.ChainData{
		Id: "Ethereum",
		Nodes: []*eznode.ChainNode{
			node1,
			node2,
		},
		CheckTickRate: eznode.CheckTick{
			TickRate:         100 * time.Millisecond,
			MaxCheckDuration: 5 * time.Second,
		},
	})

	createdEzNode := eznode.NewEzNode([]*eznode.Chain{chain})

	// sample http request
	req, _ := http.NewRequest("GET", "/latest-block", nil)
	// target ethereum chain
	// eznode will automatically select the node that has the highest priority
	// then will check the node request rate limit
	// if the node is not responding, eznode will try to recover the request
	// and try to send the request to the another node
	response, _ := createdEzNode.SendRequest("Ethereum", req)
	fmt.Println(response)
}

LICENSE

Apache License Version 2.0

Documentation

Index

Constants

This section is empty.

Variables

DefaultFailureStatusCodes is the default http status code which recognized as failure

Functions

This section is empty.

Types

type ApiCaller

type ApiCaller interface {
	DoRequest(context context.Context, request *http.Request) (*Response, error)
}

ApiCaller is the interface for making API calls

type Chain

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

func NewChain

func NewChain(
	chainData NewChainConfig,
) *Chain

NewChain creates new Chain If FailureStatusCodes is not specified, default list of status codes is used

type ChainNode

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

func NewChainNode

func NewChainNode(
	chainNodeData NewChainNodeConfig,
) *ChainNode

NewChainNode creates a new ChainNode based on the given NewChainParam

type ChainNodeLimit

type ChainNodeLimit struct {
	// Count is max number of request can be sent to this node per Per
	Count uint
	// Per is time period of the limit
	Per time.Duration
}

ChainNodeLimit determine the limit of node, how many request can be sent to one node

type ChainNodeStats

type ChainNodeStats struct {
	Name          string         `json:"name"`
	CurrentHits   uint           `json:"current_hits"`
	TotalHits     uint64         `json:"total_hits"`
	Limits        uint           `json:"limits"`
	ResponseStats map[int]uint64 `json:"response_stats"`
	Priority      int            `json:"priority"`
	Disabled      bool           `json:"disabled"`
	Fails         uint           `json:"fails"`
}

ChainNodeStats is the stats of a chain node

type ChainResponseMetadata

type ChainResponseMetadata struct {
	// ChainId is the chain id of the chain that the response is for
	ChainId string
	// RequestedUrl is the url that was requested
	RequestedUrl string
	// Retry is the number of retries that have been attempted
	Retry int
	// Trace is request to response trace
	Trace []NodeTrace
}

ChainResponseMetadata is a structure that contains metadata about the response

type ChainStats

type ChainStats struct {
	Id    string           `json:"id"`
	Nodes []ChainNodeStats `json:"nodes"`
}

ChainStats is the stats of a chain

type CheckTick

type CheckTick struct {
	// TickRate is the interval of checking nodes availability
	TickRate time.Duration
	// MaxCheckDuration is the maximum duration of checking nodes availability
	MaxCheckDuration time.Duration
}

CheckTick determines interval of checking nodes availability

type EzNode

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

func NewEzNode

func NewEzNode(chains []*Chain, options ...Option) *EzNode

NewEzNode creates a new EzNode

func (*EzNode) DisableNode

func (e *EzNode) DisableNode(chainId string, nodeName string)

DisableNode disables a node from a chain

func (*EzNode) DisableNodeWithTime

func (e *EzNode) DisableNodeWithTime(chainId string, nodeName string, duration time.Duration)

DisableNodeWithTime disables a node from a chain for a given time

func (*EzNode) EnableNode

func (e *EzNode) EnableNode(chainId string, nodeName string)

EnableNode enables a node from a chain

func (*EzNode) GetStats

func (e *EzNode) GetStats() []ChainStats

GetStats returns the stats of chains

func (*EzNode) LoadStats

func (e *EzNode) LoadStats(loadedStats []ChainStats)

LoadStats loads stats and sync stats to eznode core

func (*EzNode) SendRequest

func (e *EzNode) SendRequest(chainId string, request *http.Request) (*Response, error)

SendRequest send your request to specific chain If chain not found, return error Note: make sure which your request should not have host, schema and port

func (*EzNode) SendRequestSpecific

func (e *EzNode) SendRequestSpecific(chainId string, request *http.Request, includeNodeList []string) (*Response, error)

SendRequestSpecific send your request with specifying which node you want to use if your node rely on specific node (usually node which has more history) you can use this function to ensure your request will be responded by this node

type EzNodeError

type EzNodeError struct {
	// Message is the error message
	Message string
	// Metadata is the error metadata
	Metadata ChainResponseMetadata
}

EzNodeError is the error type for EzNode

func (EzNodeError) Error

func (e EzNodeError) Error() string

type NewChainConfig

type NewChainConfig struct {
	// Id of the chain
	Id string
	// List of nodes in the chain
	Nodes []*ChainNode
	// tick rate for checking nodes availability
	CheckTickRate CheckTick
	// list of http status codes which recognized as failure
	FailureStatusCodes []int
	// number of retries for failed requests
	RetryCount int
}

type NewChainNodeConfig

type NewChainNodeConfig struct {
	// Name of the node
	Name string
	// Url of the node
	Url string
	// Limit of the node
	Limit ChainNodeLimit
	// Timeout of a request, if a request timeout, another node will be used
	RequestTimeout time.Duration
	// Priority of the node, higher priority will be used first
	Priority int
	// Middleware will be used before sending request to the node
	// you can set up authentication middleware, etc
	// Middleware is optional
	Middleware RequestMiddleware
}

NewChainNodeConfig is parameter to pass to NewChainNode function

type NodeTrace

type NodeTrace struct {
	// NodeName is the node that the request was sent to
	NodeName string
	// StatusCode is the status code of the response
	StatusCode int
	// Err is the error that occurred
	Err error
	// Time is the time that the request was sent
	Time time.Time
}

NodeTrace is a structure that contains the trace of a request

type Option

type Option func(*EzNode)

Option is a functional parameter for NewEzNode

func WithApiClient

func WithApiClient(apiCaller ApiCaller) Option

WithApiClient sets the api client

func WithSyncInterval

func WithSyncInterval(
	interval time.Duration,
) Option

WithSyncInterval sets the sync interval for calling sync stats function

type RequestMiddleware

type RequestMiddleware func(*http.Request) *http.Request

RequestMiddleware is a function that is called before the request is processed.

type Response

type Response struct {
	// StatusCode is the HTTP status code of the response
	StatusCode int
	// Body is the response body
	Body []byte
	// Headers is the response headers
	Headers *http.Header
	// Metadata is the response metadata, it includes trace of request which it takes to get the response
	// also it includes the error and which node it was sent to
	Metadata ChainResponseMetadata
}

Response is the response from an API call (eznode final result)

Jump to

Keyboard shortcuts

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