diff --git a/cache.go b/cache.go index ff8f384..77b3ccc 100644 --- a/cache.go +++ b/cache.go @@ -4,9 +4,9 @@ import ( "fmt" "time" - "github.com/akyoto/cache" fiber "github.com/gofiber/fiber/v2" "github.com/gookit/goutil/strutil" + libpack_cache "github.com/lukaszraczylo/graphql-monitoring-proxy/cache" ) func calculateHash(c *fiber.Ctx) string { @@ -14,19 +14,14 @@ func calculateHash(c *fiber.Ctx) string { } func enableCache() { - var err error - cfg.Cache.CacheClient = cache.New(time.Duration(cfg.Cache.CacheTTL) * time.Second * 2) - if err != nil { - cfg.Logger.Critical("Can't create cache client", map[string]interface{}{"error": err.Error()}) - panic(err) - } + cfg.Cache.CacheClient = libpack_cache.New(time.Duration(cfg.Cache.CacheTTL) * time.Second * 2) } func cacheLookup(hash string) []byte { if cfg.Cache.CacheClient != nil { obj, found := cfg.Cache.CacheClient.Get(hash) if found { - return obj.([]byte) + return obj } } return nil diff --git a/cache/cache.go b/cache/cache.go new file mode 100644 index 0000000..3d2e192 --- /dev/null +++ b/cache/cache.go @@ -0,0 +1,87 @@ +package libpack_cache + +import ( + "sync" + "time" +) + +type CacheEntry struct { + Value []byte + ExpiresAt time.Time +} + +type Cache struct { + sync.Mutex + entries map[string]CacheEntry + globalTTL time.Duration + ticker *time.Ticker +} + +func New(globalTTL time.Duration) *Cache { + cache := &Cache{ + entries: make(map[string]CacheEntry), + globalTTL: globalTTL, + ticker: time.NewTicker(globalTTL / 2), + } + + // Start the cache. + cache.Start() + return cache +} + +func (c *Cache) Start() { + go func() { + for { + <-c.ticker.C + c.CleanExpiredEntries() + } + }() +} + +func (c *Cache) Set(key string, value []byte, ttl time.Duration) { + c.Lock() + defer c.Unlock() + + now := time.Now() + expiresAt := now.Add(ttl) + if expiresAt.After(now.Add(c.globalTTL)) { + expiresAt = now.Add(c.globalTTL) + } + + c.entries[key] = CacheEntry{ + Value: value, + ExpiresAt: expiresAt, + } +} + +func (c *Cache) Get(key string) ([]byte, bool) { + c.Lock() + defer c.Unlock() + + entry, ok := c.entries[key] + if !ok || entry.ExpiresAt.Before(time.Now()) { + return nil, false + } + + return entry.Value, true +} + +func (c *Cache) Delete(key string) { + c.Lock() + defer c.Unlock() + + delete(c.entries, key) +} + +func (c *Cache) CleanExpiredEntries() { + now := time.Now() + + c.Lock() + defer c.Unlock() + + for key, entry := range c.entries { + if entry.ExpiresAt.Before(now) { + delete(c.entries, key) + } + } +} diff --git a/go.mod b/go.mod index a4fce38..14ef831 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,9 @@ go 1.21 require ( github.com/VictoriaMetrics/metrics v1.24.0 - github.com/akyoto/cache v1.0.6 github.com/buger/jsonparser v1.1.1 github.com/gofiber/fiber/v2 v2.49.2 - github.com/gookit/goutil v0.6.12 + github.com/gookit/goutil v0.6.13 github.com/graphql-go/graphql v0.8.1 github.com/json-iterator/go v1.1.12 github.com/lukaszraczylo/ask v0.0.0-20230927103145-2ff1123b4415 @@ -19,6 +18,7 @@ require ( ) require ( + github.com/akyoto/cache v1.0.6 // indirect github.com/andybalholm/brotli v1.0.5 // indirect github.com/avast/retry-go/v4 v4.5.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/go.sum b/go.sum index d051481..534347b 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +21,8 @@ github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= -github.com/gookit/goutil v0.6.12 h1:73vPUcTtVGXbhSzBOFcnSB1aJl7Jq9np3RAE50yIDZc= -github.com/gookit/goutil v0.6.12/go.mod h1:g6krlFib8xSe3G1h02IETowOtrUGpAmetT8IevDpvpM= +github.com/gookit/goutil v0.6.13 h1:ttg7yMda6Q9fkE4P+YTwozd2wH1Le0CQldTAtOFBr7o= +github.com/gookit/goutil v0.6.13/go.mod h1:YyDBddefmjS+mU2PDPgCcjVzTDM5WgExiDv5ZA/b8I8= github.com/graphql-go/graphql v0.8.1 h1:p7/Ou/WpmulocJeEx7wjQy611rtXGQaAcXGqanuMMgc= github.com/graphql-go/graphql v0.8.1/go.mod h1:nKiHzRM0qopJEwCITUuIsxk9PlVlwIiiI8pnJEhordQ= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= diff --git a/struct_config.go b/struct_config.go index ce2bec6..b357955 100644 --- a/struct_config.go +++ b/struct_config.go @@ -1,8 +1,8 @@ package main import ( - "github.com/akyoto/cache" graphql "github.com/lukaszraczylo/go-simple-graphql" + libpack_cache "github.com/lukaszraczylo/graphql-monitoring-proxy/cache" libpack_logging "github.com/lukaszraczylo/graphql-monitoring-proxy/logging" libpack_monitoring "github.com/lukaszraczylo/graphql-monitoring-proxy/monitoring" "github.com/valyala/fasthttp" @@ -36,7 +36,7 @@ type config struct { Cache struct { CacheEnable bool CacheTTL int - CacheClient *cache.Cache + CacheClient *libpack_cache.Cache } Security struct {