care

package module
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2022 License: MIT Imports: 15 Imported by: 0

README

go-care

A library for gRPC response memoization in Go, aimed to improve common performance of a project having made real response computation lower cost.

go-care is an abbreviation of the 'Cached Response in Go'.

Introduction

Having faced an issue of lack of the memoization in grpc this library has been written as a solution. Maybe there was a solution, but I had not been searching for the one enough well. Tricky question... Nonetheless, let's say a bit about the go-care package.

The package aims to improve performance via caching response for respective request params. Having included additional information from incoming data there is a possibility to make the most unique key for the cached response.

Essential gist of the approach is to make an interceptor wherein compute the key --a hash of the incoming data-- and memorize/restore the responses, having been making the lower computation cost at the expense of the decreased number of the real computation.

The package can be used with built-in LRU cache or with an external cache like Redis, Memcached, or something else. In order to use an external cache there is only the need to implement a caching interface.

Features

  • server- and client-side response memoization
  • flexibility and room space for customization
  • loosely coupled architecture
  • thread safety
  • easy to use :)

Note The built-in implementation of the in-memory cache doesn't support eviction by the TTL. It has developed only for demo and small MVP. In production you need to use go-care with Redis, Memcached, or other cache. That might be done by implementing the 'Cache' interface and providing the one via 'Options'.

Usage

  1. Add the package to the project
  2. On the server-side it might be articulated like below in pseudocode
package main

import (
  ...
  care "github.com/tdv/go-care"
  ...
)

// Your server implementation
// type server struct {
//   api.UnimplementedYourServerServiceServer
// }

// ...

func main() {
  // Other your code
  ...

  // Creating the options
  opts, err := care.NewDefaultOptions()
  if err != nil {
    log.Fatalf...
  }

  // Adding methods for the memoization. 
  // You need to define the methods pool 
  // for response memoization.
  opts.Methods.Add("/api.GreeterService/SayHello", time.Second*60)

  // Other customization might be done via the opts variable.
  // See the examples.

  // Creating the server-side interceptor.
  unary, err := care.NewServerUnaryInterceptor(opts)
  if err != nil {
    log.Fatalf...
  }

  // Providing / applying the interceptor
  grpcsrv := grpc.NewServer(unary)
  // Other your code

  ...
}
  1. On the client-side the similar way
package main

import (
 ...
 care "github.com/tdv/go-care"
 ...
)

func main() {
 ...

 opts, err := care.NewDefaultOptions()
 if err != nil {
   log.Fatalf...
 }

 opts.Methods.Add("/api.GreeterService/SayHello", time.Second*60)

 unary, err := care.NewClientUnaryInterceptor(opts)
 if err != nil {
   log.Fatalf...
 }

 conn, err := grpc.Dial(
   fmt.Sprintf("%s:%d", *host, *port),
   grpc.WithTransportCredentials(insecure.NewCredentials()),
   unary,
 )

 if err != nil {
   log.Fatalf...
 }

 defer conn.Close()

   ...
}

More details you'll find among the examples

Examples

The examples demonstrate go-care package's features. Having run server and client with different param-set you can try the ones.

Compiler and OS

The package had developed and tested in Go 1.19 within Ubuntu 20.04. Hopefully, many other OS and compiler versions will be appropriate quite well.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewClientUnaryInterceptor

func NewClientUnaryInterceptor(opts *Options) (grpc.DialOption, error)

func NewServerUnaryInterceptor

func NewServerUnaryInterceptor(opts *Options) (grpc.ServerOption, error)

Types

type Cache

type Cache interface {
	Put(key string, val []byte, ttl time.Duration) error
	Get(key string) ([]byte, error)
}

func NewInMemoryCache

func NewInMemoryCache(capacity uint) Cache

type Hash

type Hash interface {
	Calc(key string) (string, error)
}

type Headers

type Headers struct {
	Allowed    []string
	Disallowed []string
}

type MetaFilter

type MetaFilter interface {
	Allowed(key string, val []string) bool
}

func NewMetaFilter

func NewMetaFilter(headers Headers) MetaFilter

func NewZeroMetaFilter

func NewZeroMetaFilter() MetaFilter

type Methods

type Methods interface {
	Cacheable(method string) (bool, time.Duration)

	Add(method string, ttl time.Duration) Methods
	Remove(method string)
	Clean()
}

type Options

type Options struct {
	Switch     Switch
	Methods    Methods
	MetaFilter MetaFilter
	Hash       Hash
	Cache      Cache
}

func NewDefaultOptions

func NewDefaultOptions() (*Options, error)

type Switch

type Switch interface {
	TurnOn()
	TurnOff()

	IsTurnedOn() bool
}

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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