Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

github.com/emar-kar/cache

Package Overview
Dependencies
Alerts
File Explorer
Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

github.com/emar-kar/cache

  • v1.1.0
  • Source
  • Go
  • Socket score

Version published
Created
Source

Simple cache package

This package is a simple in-memory key-value storage based on golang map type. Check docs for more details.

Data is stored as any interface inside a unit struct, which carries additional metadata.

Import

import "github.com/emar-kar/cache"

Cache options

  • WithDefaultLifetime - sets default lifetime of every key added into the cache
  • WithCleanupInteval - sets janitor run interval
  • WithMaxUnits - sets max number of keys in cache
  • WithMaxSize - sets max size of stored data in bytes
  • WithOnEvictionFn - sets custom function which is triggered on key removal by janitor or manually
  • WithoutJanitorEviction - defines janitor behavior if it should trigger on eviction function on clean up
  • WithDataSizeFn - sets custom function to define size of the data

Keys set options

  • WithLifetime - sets custom lifetime for cache key
  • WithSize - sets custom size for key data. If set, cache will ignore size calculation and use passed value. Adds default metadata size

In addition to global cache options, user can set individual lifetime per key or set data size to omit auto calculations.

Available functionality

FuncWhat it does
GetReturns data of the given key
ScanScans current snapshot of the cache data and returns key-value map if key contains given sub-string
ScanFuncScans current snapshot of the cache and returns key-value map if given func returns true for a key
SetSaves data in cache with given key and options. If key already exists it will be replaced without warnings
AddSets data in cache if given key does not exist
ReplaceReplaces data of the given key only if this key exists in cache and is not expired
RenameRenames old key with a new name only if given key exists in cache and is not expired
RemoveRemoves key with given name from cache. Do nothing if key does not exist. Does not apply on eviction function even if it was set
RemoveAllRemoves all keys from cache. Does not apply on eviction function even if it was set. Runs GC to collect released memory
RemoveExpiredRemoves only expired keys. Does not apply on eviction function even if it was set
DeleteRemoves key with given name from cache. Do nothing if key does not exist. Applies on eviction function if it was set
DeleteAllRemoves all keys from cache applying on eviction function if it was set
DeleteExpiredRemoves only expired keys applying on eviction function if it was set
AliveCreates copy of the cache with not expired keys data
SnapshotCreates copy of the cache with all keys data
ReviveProlongs lifetime of the key with default value from cache options
ReviveUntilProlongs lifetime of the key with specified value
LengthReturns number of keys in cache
SizeReturns current size of the cache in bytes
ChangeMaxSizeUpdates cache default options with new cache max size in bytes
ChangeMaxLengthUpdates cache default options with new max number of keys
StopCleaningStops current janitor if it was set. This function waits until janitor is unlocked if it is in cleaning progress
ChangeDefaultLifeTimeUpdates cache default options with new default lifetime for key
ChangeSizeFnUpdates cache default options with new function to define data size
ChangeOnEvictionFnUpdates cache default options with new function which runs when key is being cleaned after expiration. If janitor is cleaning cache, this function will wait until it finishes, before changing on eviction function
OrderCleaningStops current janitor if it was set and starts a new one with cache default cleanup interval
RescheduleCleaningStops current janitor if it was set, updates cache default cleanup interval with given duration and starts a new janitor
ChangeJanitorOnEvictionUpdates cache default options with new janitor expiried keys removal behavior. Allows to control if janitor should apply on eviction function even if it was set. Restart janitor if it's currently running

Increment/decrement values

Package has two exported functions, which recive Cache as first argument and support increment and decrement of the stored values by given N. It was done this way to support generics with Integer type:

type Integer interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 |
		~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}
func Increment[T Integer](c *Cache, k string, n T) (T, error)

func Decrement[T Integer](c *Cache, k string, n T) (T, error)

Those functions will return error if key does not exist, was expired or it's data type assertion failed.

Eviction with goroutines

Since it was decided to remove explicit goroutine call for eviction functions in Delete* methods, here is the workaround how to implement this anyway:

goEviction := func() func(string, any) {
    return func(str string, a any) {
        go func() {
            // Do something with key and value...
        }()
    }
}

c := New(WithOnEvictionFn(goEviction()))

if err := c.Set("foo", "simple string"); err != nil {
    // Process error...
}

c.Delete("foo")

// Wait until goroutine finish onEviction...

Save/Load

Experimentally there is a support of marshal/unmarshal data to json format. Since data is stored as any interface, it can dump custom formats as well. Those features are experimental and might change in future. Check examples for more details.

c := New(
    WithDefaultLifetime(uint64(time.Hour)),
    WithMaxSize(1028),
)

if err := c.Set("foo", "simple string"); err != nil {
    // Process error...
}

type test struct {
    Str string `json:"str"`
}

testStruct := &test{"string in struct"}

if err := c.Set("foo2", testStruct); err != nil {
    // Process error...
}

if err := c.Set("foo3", []string{"string in slice"}); err != nil {
    // Process error...
}

if err := c.Set("foo4", map[string]string{"bar": "string in map"}); err != nil {
    // Process error...
}

dumpFile := "dump.json"

f, err := os.Create(dumpFile)
if err != nil {
    // Process error...
}

if err := c.Save(f); err != nil {
    f.Close()
    // Process error...
}

f.Close()
c.RemoveAll()

f, err = os.Open(dumpFile)
if err != nil {
    // Process error...
}
defer f.Close()

if err := c.Load(f); err != nil {
    // Process error...
}

str, err := c.Get("foo")
if err != nil {
    // Process error...
}

fmt.Println(str) // Prints: "simple string"

if str, err := c.Get("foo2"); err != nil {
    // Process error...
} else {
    jsonData, err := json.Marshal(str)
    if err != nil {
        // Process error...
    }

    var structData test
    if err := json.Unmarshal(jsonData, &structData); err != nil {
        // Process error...
    }

    // structData.Str == "string in struct".
}

if str, err := c.Get("foo3"); err != nil {
    // Process error...
} else {
    sl := make([]string, len(str.([]any)))
    for i, el := range str.([]any) {
        sl[i] = el.(string)
    }

    // sl[0] == "string in slice".
}

if str, err := c.Get("foo4"); err != nil {
    // Process error...
} else {
    m := make(map[string]string, len(str.(map[string]any)))
    for k, v := range str.(map[string]any) {
        m[k] = v.(string)
    }

    // m["bar"] == "string in map".
}

Some productivity tests:

BenchmarkCacheGetDataWithLifetime-10            30645175                37.39 ns/op            0 B/op          0 allocs/op
BenchmarkCacheGetData-10                        66297579                18.03 ns/op            0 B/op          0 allocs/op
BenchmarkCacheGetExpiredConcurrent-10            8271970               135.1 ns/op             0 B/op          0 allocs/op
BenchmarkCacheGetDataConcurrent-10               9178712               135.5 ns/op             0 B/op          0 allocs/op
BenchmarkCacheSetWithOpts-10                    21413689                56.22 ns/op            0 B/op          0 allocs/op
BenchmarkCacheSetData-10                        35918688                30.92 ns/op            0 B/op          0 allocs/op
BenchmarkCacheIncrement-10                      25929056                45.62 ns/op            7 B/op          0 allocs/op
BenchmarkCacheDecrement-10                      25951790                45.72 ns/op            7 B/op          0 allocs/op

FAQs

Package last updated on 23 Apr 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc