diff --git a/bigcache.go b/bigcache.go index b3aa37b..c4eb38a 100644 --- a/bigcache.go +++ b/bigcache.go @@ -232,6 +232,13 @@ func (c *BigCache) Iterator() *EntryInfoIterator { return newIterator(c) } +// Contains returns whether the given key exists in cache +func (c *BigCache) Contains(key string) bool { + hashedKey := c.hash.Sum64(key) + shard := c.getShard(hashedKey) + return shard.contains(key, hashedKey) +} + func (c *BigCache) onEvict(oldestEntry []byte, currentTimestamp uint64, evict func(reason RemoveReason) error) bool { oldestTimestamp := readTimestampFromEntry(oldestEntry) if currentTimestamp < oldestTimestamp { diff --git a/bigcache_test.go b/bigcache_test.go index 2f86a6d..5a21de5 100644 --- a/bigcache_test.go +++ b/bigcache_test.go @@ -1389,3 +1389,31 @@ func TestRemoveNonExpiredData(t *testing.T) { noError(t, err) } } + +func TestContainsExists(t *testing.T) { + t.Parallel() + + // given + cache, _ := New(context.Background(), DefaultConfig(5*time.Second)) + value := []byte("value") + + // when + cache.Set("key", value) + exists := cache.Contains("key") + + // then + assertEqual(t, true, exists) +} + +func TestContainsNotExists(t *testing.T) { + t.Parallel() + + // given + cache, _ := New(context.Background(), DefaultConfig(5*time.Second)) + + // when + exists := cache.Contains("key") + + // then + assertEqual(t, false, exists) +} diff --git a/shard.go b/shard.go index 4f03b53..fc922e4 100644 --- a/shard.go +++ b/shard.go @@ -117,6 +117,18 @@ func (s *cacheShard) getValidWrapEntry(key string, hashedKey uint64) ([]byte, er return wrappedEntry, nil } +func (s *cacheShard) contains(key string, hashedKey uint64) bool { + s.lock.RLock() + wrappedEntry, err := s.getWrappedEntry(hashedKey) + if err != nil { + s.lock.RUnlock() + return false + } + entryKey := readKeyFromEntry(wrappedEntry) + s.lock.RUnlock() + return key == entryKey +} + func (s *cacheShard) set(key string, hashedKey uint64, entry []byte) error { currentTimestamp := uint64(s.clock.Epoch())