Documentation ¶
Overview ¶
Package cachemdw is responsible for caching EVM requests and provides corresponding middleware package can work with any underlying storage which implements simple cache.Cache interface
package provides two different middlewares: - IsCachedMiddleware (should be run before proxy middleware) - CachingMiddleware (should be run after proxy middleware)
IsCachedMiddleware is responsible for setting response in the context if it's in the cache CachingMiddleware is responsible for caching response by taking a value from context (should be set by proxy mdw) and setting in the cache
Index ¶
- Constants
- Variables
- func BuildCacheKey(cachePrefix string, cacheItemType CacheItemType, parts []string) string
- func GetQueryKey(cachePrefix string, req *decode.EVMRPCRequestEnvelope) (string, error)
- func IsCacheHitHeaders(header http.Header) bool
- func IsCacheable(logger *logging.ServiceLogger, req *decode.EVMRPCRequestEnvelope) bool
- func IsRequestCached(ctx context.Context) bool
- func LogCannotCastRequestError(logger *logging.ServiceLogger, r *http.Request)
- type CacheItemType
- type Config
- type JsonRpcError
- type JsonRpcResponse
- type QueryResponse
- type ServiceCache
- func (c *ServiceCache) CacheQueryResponse(ctx context.Context, req *decode.EVMRPCRequestEnvelope, responseInBytes []byte, ...) error
- func (c *ServiceCache) CachingMiddleware(next http.Handler) http.HandlerFunc
- func (c *ServiceCache) GetCachedQueryResponse(ctx context.Context, req *decode.EVMRPCRequestEnvelope) (*QueryResponse, error)
- func (c *ServiceCache) GetTTL(method string) (time.Duration, error)
- func (c *ServiceCache) Healthcheck(ctx context.Context) error
- func (c *ServiceCache) IsCacheEnabled() bool
- func (c *ServiceCache) IsCachedMiddleware(next http.Handler) http.HandlerFunc
Constants ¶
const ( CachedContextKey = "X-KAVA-PROXY-CACHED" ResponseContextKey = "X-KAVA-PROXY-RESPONSE" CacheHeaderKey = "X-Kava-Proxy-Cache-Status" CacheHitHeaderValue = "HIT" CacheMissHeaderValue = "MISS" CachePartialHeaderValue = "PARTIAL" )
Variables ¶
Functions ¶
func BuildCacheKey ¶
func BuildCacheKey(cachePrefix string, cacheItemType CacheItemType, parts []string) string
func GetQueryKey ¶
func GetQueryKey( cachePrefix string, req *decode.EVMRPCRequestEnvelope, ) (string, error)
GetQueryKey calculates cache key for request
func IsCacheHitHeaders ¶
IsCacheHitHeaders returns true when the passed in response headers are for a request that came from the cache.
func IsCacheable ¶
func IsCacheable( logger *logging.ServiceLogger, req *decode.EVMRPCRequestEnvelope, ) bool
IsCacheable checks if EVM request is cacheable. In current implementation we consider request is cacheable if it has specific block height
func IsRequestCached ¶
IsRequestCached returns whether request was cached if returns true it means: - middleware marked that request was cached - value of cached response should be available in context via ResponseContextKey
func LogCannotCastRequestError ¶
func LogCannotCastRequestError(logger *logging.ServiceLogger, r *http.Request)
Types ¶
type CacheItemType ¶
type CacheItemType int
const (
CacheItemTypeEVMRequest CacheItemType = iota + 1
)
func (CacheItemType) String ¶
func (t CacheItemType) String() string
type Config ¶
type Config struct { // TTL for cached evm requests // Different evm method groups may have different TTLs // TTL should be either greater than zero or equal to -1, -1 means cache indefinitely CacheMethodHasBlockNumberParamTTL time.Duration CacheMethodHasBlockHashParamTTL time.Duration CacheStaticMethodTTL time.Duration CacheMethodHasTxHashParamTTL time.Duration }
type JsonRpcError ¶
func (*JsonRpcError) String ¶
func (e *JsonRpcError) String() string
String returns the string representation of the error
type JsonRpcResponse ¶
type JsonRpcResponse struct { Version string `json:"jsonrpc,omitempty"` ID json.RawMessage `json:"id,omitempty"` Result json.RawMessage `json:"result,omitempty"` JsonRpcError *JsonRpcError `json:"error,omitempty"` }
JsonRpcResponse is a EVM JSON-RPC response
func UnmarshalJsonRpcResponse ¶
func UnmarshalJsonRpcResponse(data []byte) (*JsonRpcResponse, error)
UnmarshalJsonRpcResponse unmarshals a JSON-RPC response
func (*JsonRpcResponse) Error ¶
func (resp *JsonRpcResponse) Error() error
Error returns the json-rpc error if any
func (*JsonRpcResponse) IsCacheable ¶
func (resp *JsonRpcResponse) IsCacheable() bool
IsCacheable returns true in case of: - json-rpc response doesn't contain an error - json-rpc response's result isn't empty
func (*JsonRpcResponse) IsFinal ¶
func (resp *JsonRpcResponse) IsFinal(method string) bool
func (*JsonRpcResponse) IsResultEmpty ¶
func (resp *JsonRpcResponse) IsResultEmpty() bool
IsResultEmpty checks if the response's result is empty
func (*JsonRpcResponse) Marshal ¶
func (resp *JsonRpcResponse) Marshal() ([]byte, error)
Marshal marshals a JSON-RPC response to JSON
type QueryResponse ¶
type QueryResponse struct { // JsonRpcResponseResult is an EVM JSON-RPC response's result JsonRpcResponseResult []byte `json:"json_rpc_response_result"` // HeaderMap is a map of HTTP headers which is cached along with the EVM JSON-RPC response HeaderMap map[string]string `json:"header_map"` }
QueryResponse represents the structure which stored in the cache for every cacheable request
type ServiceCache ¶
type ServiceCache struct { *logging.ServiceLogger // contains filtered or unexported fields }
ServiceCache is responsible for caching EVM requests and provides corresponding middleware ServiceCache can work with any underlying storage which implements simple cache.Cache interface
func NewServiceCache ¶
func NewServiceCache( cacheClient cache.Cache, blockGetter decode.EVMBlockGetter, decodedRequestContextKey any, cachePrefix string, cacheEnabled bool, whitelistedHeaders []string, defaultAccessControlAllowOriginValue string, hostnameToAccessControlAllowOriginValueMap map[string]string, config *Config, logger *logging.ServiceLogger, ) *ServiceCache
func (*ServiceCache) CacheQueryResponse ¶
func (c *ServiceCache) CacheQueryResponse( ctx context.Context, req *decode.EVMRPCRequestEnvelope, responseInBytes []byte, headerMap map[string]string, ) error
CacheQueryResponse calculates cache key for request and then saves response to the cache. NOTE: only JSON-RPC response's result is cached. There is no point to cache JSON-RPC response's ID (because it should correspond to request's ID, which constantly changes). Same with JSON-RPC response's Version.
func (*ServiceCache) CachingMiddleware ¶
func (c *ServiceCache) CachingMiddleware( next http.Handler, ) http.HandlerFunc
CachingMiddleware returns kava-proxy-service compatible middleware which works in the following way: - tries to get decoded request from context (previous middleware should set it) - checks few conditions:
- if request isn't already cached
- if request is cacheable
- if response is present in context
- if all above is true - caches the response - calls next middleware
func (*ServiceCache) GetCachedQueryResponse ¶
func (c *ServiceCache) GetCachedQueryResponse( ctx context.Context, req *decode.EVMRPCRequestEnvelope, ) (*QueryResponse, error)
GetCachedQueryResponse calculates cache key for request and then tries to get it from cache. NOTE: only JSON-RPC response's result will be taken from the cache. JSON-RPC response's ID and Version will be constructed on the fly to match JSON-RPC request.
func (*ServiceCache) GetTTL ¶
func (c *ServiceCache) GetTTL(method string) (time.Duration, error)
GetTTL returns TTL for specified EVM method.
func (*ServiceCache) Healthcheck ¶
func (c *ServiceCache) Healthcheck(ctx context.Context) error
func (*ServiceCache) IsCacheEnabled ¶
func (c *ServiceCache) IsCacheEnabled() bool
func (*ServiceCache) IsCachedMiddleware ¶
func (c *ServiceCache) IsCachedMiddleware( next http.Handler, ) http.HandlerFunc
IsCachedMiddleware returns kava-proxy-service compatible middleware which works in the following way: - tries to get decoded request from context (previous middleware should set it) - tries to get response from the cache
- if present sets cached response in context, marks as cached in context and forwards to next middleware
- if not present marks as uncached in context and forwards to next middleware
- next middleware should check whether request was cached and act accordingly: