Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache/purgebykey #94

Merged
merged 1 commit into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions datastructures/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const (
type SimpleLRU[K comparable, V any] interface {
Get(key K) (V, error)
Set(key K, value V) error
FlushKey(key K)
}

// SimpleLRUImpl implements the Simple interface
Expand Down Expand Up @@ -98,16 +99,31 @@ func (c *SimpleLRUImpl[K, V]) Set(key K, value V) error {
return nil
}

// FlushKey removes an entry form the cache if it exists. Does nothing otherwise
func (c *SimpleLRUImpl[K, V]) FlushKey(key K) {
c.mutex.Lock()
defer c.mutex.Unlock()

if node, ok := c.items[key]; ok {
c.lru.MoveToBack(node)
delete(c.items, key)
if c.ttls != nil {
delete(c.ttls, key)
}
c.lru.Remove(c.lru.Back())
}
}

// NewSimple returns a new Simple instance of the specified size and TTL
func NewSimpleLRU[K comparable, V any](maxSize int, ttl time.Duration) (*SimpleLRUImpl[K, V], error) {
if maxSize <= 0 {
return nil, fmt.Errorf("Cache size should be > 0. Is: %d", maxSize)
}
var ttls map[K]time.Time = nil
if ttl != NoTTL {
ttls = make(map[K]time.Time)
}

var ttls map[K]time.Time = nil
if ttl != NoTTL {
ttls = make(map[K]time.Time)
}

return &SimpleLRUImpl[K, V]{
maxLen: maxSize,
Expand Down
29 changes: 21 additions & 8 deletions datastructures/cache/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@ func TestSimpleCache(t *testing.T) {
assert.Equal(t, asExpired.When, ttl.Add(cache.ttl))

}

assert.Nil(t, cache.Set("lala", 123))
v, err := cache.Get("lala")
assert.Nil(t, err)
assert.Equal(t, 123, v)

cache.FlushKey("lala")
v, err = cache.Get("lala")
assert.NotNil(t, err)
assert.Equal(t, 0, v)

var exp *Miss
assert.ErrorAs(t, err, &exp)
}

func TestSimpleCacheHighConcurrency(t *testing.T) {
Expand Down Expand Up @@ -103,25 +116,25 @@ func TestInt64Cache(t *testing.T) {

for i := int64(1); i <= 5; i++ {
val, err := c.Get(i)
assert.Nil(t, err)
assert.Equal(t, i, val)
assert.Nil(t, err)
assert.Equal(t, i, val)
}

c.Set(6, 6)

// Oldest item (1) should have been removed
val, err := c.Get(1)
assert.NotNil(t, err)
assert.NotNil(t, err)
_, ok := err.(*Miss)
assert.True(t, ok)
assert.Equal(t, int64(0), val)
assert.True(t, ok)
assert.Equal(t, int64(0), val)

// 2-6 should be available
for i := int64(2); i <= 6; i++ {
val, err := c.Get(i)
assert.Nil(t, err)
assert.Equal(t, i, val)
assert.Nil(t, err)
assert.Equal(t, i, val)
}

assert.Equal(t, 5, len(c.items))
assert.Equal(t, 5, len(c.items))
}
2 changes: 1 addition & 1 deletion datastructures/cache/multilevel.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (c *MultiLevelCacheImpl[K, V]) Get(ctx context.Context, key K) (V, error) {
}
}

var empty V
var empty V
if item == empty || err != nil {
return empty, &Miss{Where: "ALL_LEVELS", Key: key}
}
Expand Down
Loading