encache

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: May 18, 2024 License: MIT Imports: 10 Imported by: 0

README

encache

Go Reference Go Report Card

encache is a Go package that provides a caching mechanism for function calls. It allows you to cache the results of expensive function calls and retrieve them from the cache instead of recomputing them. This can greatly improve the performance of your application, especially when dealing with computationally intensive or I/O-bound operations.

Features

  • Support for in-memory and Redis caching
  • Automatic cache expiration and periodic expiration of stale entries
  • Locking mechanisms to ensure thread-safety
  • Customizable cache key generation
  • Option to cache function results even when errors occur

Installation

go get github.com/forkbikash/encache

Usage

Here's a simple example of how to use the encache package:

package main

import (
	"fmt"
	"time"

	"github.com/forkbikash/encache"
)

func expensiveOperation(a, b int) (int, error) {
	// Simulate an expensive operation
	time.Sleep(2 * time.Second)
	return a + b, nil
}

func main() {
	// Create a new in-memory cache implementation
	mapCache := encache.NewMapCacheImpl()
	cacheKeyImpl := encache.NewDefaultCacheKeyImpl()
	lockImpl := encache.NewMuLockImpl()

	// Create a new encache instance
	encache := encache.NewEncache(lockImpl, mapCache, cacheKeyImpl, false, time.Minute)

	// Wrap the expensive function with caching
	cachedExpensiveOperation := encache.CachedFunc(expensiveOperation, encache, time.Minute)

	// Call the cached function
	result, err := cachedExpensiveOperation(2, 3)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Result:", result)

	// Subsequent calls will retrieve the result from the cache
	result, err = cachedExpensiveOperation(2, 3)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Result (cached):", result)
}

This example demonstrates how to create a new encache instance with an in-memory cache (MapCacheImpl), a default cache key implementation (DefaultCacheKeyImpl), and a mutex-based lock implementation (MuLockImpl). It then wraps the expensiveOperation function with the CachedFunc function, which returns a new function that will cache the results of expensiveOperation.

Contributing

Contributions are welcome! Please open an issue or submit a pull request if you have any improvements, bug fixes, or new features to propose.

Future developments

  • Cache invalidation strategies: Aside from the simple expiration-based cache invalidation, we can add support for other strategies like manual invalidation, LRU (Least Recently Used) eviction, or event-based invalidation (e.g., invalidating the cache when the underlying data changes).
  • Monitoring and metrics: Provide metrics and monitoring capabilities to help users understand the cache's performance, hit/miss rates, and other relevant statistics.
  • Adaptive caching: Implement an adaptive caching mechanism that can automatically adjust the cache size, eviction policy, or other parameters based on the workload and usage patterns.
  • Asynchronous cache updates: Provide an asynchronous cache update mechanism to allow for non-blocking cache population and update operations.
  • Change package structure
caching/
├── backend/
│   ├── memory/
│   ├── redis/
│   └── memcached/
├── policy/
│   ├── expiration/
│   ├── lru/
│   └── invalidation/
├── serializer/
│   ├── json/
│   ├── gob/
│   └── msgpack/
├── cache.go
├── options.go
├── metrics.go
└── utils.go

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CachedFunc

func CachedFunc[T any](f T, encache Encache, expiry time.Duration) T

closure = returned anonymous inner function + outer context(variables defined outside of inner function) get the instance of function f with caching logic

func Expire

func Expire(encache Encache, key string, expiry time.Duration) error

change expiration or expire immediately to expire immediately, pass 0 as expiry

Types

type CacheKeyImpl

type CacheKeyImpl struct{}

func NewDefaultCacheKeyImpl

func NewDefaultCacheKeyImpl() *CacheKeyImpl

func (*CacheKeyImpl) Key

func (cacheImpl *CacheKeyImpl) Key(fName string, args []reflect.Value) string

type CacheKeyType

type CacheKeyType interface {
	Key(string, []reflect.Value) string
}

type CacheType

type CacheType interface {
	Get(string, reflect.Type) ([]reflect.Value, bool, error)
	Set(string, []reflect.Value, time.Duration) error
	Serialize([]reflect.Value) (string, error)
	Deserialize(string, reflect.Type) ([]reflect.Value, error)
	PeriodicExpire(time.Duration)
	Expire(string, time.Duration) error
}

type Encache

type Encache struct {
	LockImpl      LockType
	CacheImpl     CacheType
	CacheKeyImpl  CacheKeyType
	SetCacheOnErr bool
}

func NewEncache

func NewEncache(LockImpl LockType, CacheImpl CacheType, CacheKeyImpl CacheKeyType, setCacheOnErr bool, staleRemovalPeriod time.Duration) Encache

type LockType

type LockType interface {
	// contains filtered or unexported methods
}

type MapCacheImpl

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

func NewMapCacheImpl

func NewMapCacheImpl(size ...int) *MapCacheImpl

for map size[0] is the size

func (*MapCacheImpl) Deserialize

func (cacheImpl *MapCacheImpl) Deserialize(serializedResult string, fType reflect.Type) ([]reflect.Value, error)

just to satisfy the interface

func (*MapCacheImpl) Expire

func (cacheImpl *MapCacheImpl) Expire(key string, expiry time.Duration) error

expire after a certain duration

func (*MapCacheImpl) Get

func (cacheImpl *MapCacheImpl) Get(key string, _ reflect.Type) ([]reflect.Value, bool, error)

func (*MapCacheImpl) PeriodicExpire

func (cacheImpl *MapCacheImpl) PeriodicExpire(runOnDuration time.Duration)

start a goroutine to periodically check and remove expired cache entries

func (*MapCacheImpl) Serialize

func (cacheImpl *MapCacheImpl) Serialize(res []reflect.Value) (string, error)

just to satisfy the interface

func (*MapCacheImpl) Set

func (cacheImpl *MapCacheImpl) Set(key string, value []reflect.Value, expiry time.Duration) error

type MuLockImpl

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

func NewMuLockImpl

func NewMuLockImpl() *MuLockImpl

type NoLockImpl

type NoLockImpl struct{}

func NewNoLockImpl

func NewNoLockImpl() *NoLockImpl

type RedisCacheImpl

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

func NewRedisCacheImpl

func NewRedisCacheImpl(client redis.UniversalClient) *RedisCacheImpl

func (*RedisCacheImpl) Deserialize

func (cacheImpl *RedisCacheImpl) Deserialize(serializedResult string, fType reflect.Type) ([]reflect.Value, error)

func (*RedisCacheImpl) Expire

func (cacheImpl *RedisCacheImpl) Expire(key string, expiry time.Duration) error

func (*RedisCacheImpl) Get

func (cacheImpl *RedisCacheImpl) Get(key string, fType reflect.Type) ([]reflect.Value, bool, error)

func (*RedisCacheImpl) PeriodicExpire

func (cacheImpl *RedisCacheImpl) PeriodicExpire(_ time.Duration)

just to satisfy the interface as expirations happens automatically

func (*RedisCacheImpl) Serialize

func (cacheImpl *RedisCacheImpl) Serialize(res []reflect.Value) (string, error)

func (*RedisCacheImpl) Set

func (cacheImpl *RedisCacheImpl) Set(key string, value []reflect.Value, expiry time.Duration) error

type RedisLockImpl

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

func NewRedisLockImpl

func NewRedisLockImpl(client redis.UniversalClient, lockTimeout time.Duration) *RedisLockImpl

Jump to

Keyboard shortcuts

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