diff --git a/main.go b/main.go index 81464f6..6ec6462 100644 --- a/main.go +++ b/main.go @@ -8,9 +8,9 @@ import ( // Errors for cache const ( - ErrKeyNotFound = "Key not found" - ErrKeyExists = "Key already exists" - ErrExpired = "Key expired" + ErrKeyNotFound = "key not found" + ErrKeyExists = "key already exists" + ErrExpired = "key expired" ) // CacheItem is a struct for cache item @@ -36,10 +36,16 @@ type Cacher interface { } // NewCache is a constructor for Cache -func NewCache() *Cache { - return &Cache{ +func NewCache(options ...func(*Cache)) *Cache { + c := &Cache{ data: make(map[string]CacheItem), } + + for _, option := range options { + option(c) + } + + return c } // Set is a method for setting key-value pair @@ -143,3 +149,15 @@ func (c *Cache) Cleanup() { } c.mx.Unlock() } + +// WithCleanup is a functional option for setting interval and starting Cleanup goroutine +func WithCleanup(ttl int64) func(*Cache) { + return func(c *Cache) { + go func() { + for { + c.Cleanup() + time.Sleep(time.Duration(ttl) * time.Second) + } + }() + } +} diff --git a/main_test.go b/main_test.go index 26ddf83..76bdc25 100644 --- a/main_test.go +++ b/main_test.go @@ -100,6 +100,7 @@ func Test_SimpleTest_Mcache(t *testing.T) { // key should be deleted has, err = c.Has("key") assert.False(t, has) + assert.Error(t, err) // del should return error if key doesn't exist err = c.Del("noSuchKey") @@ -145,6 +146,26 @@ func TestConcurrentSetAndGet(t *testing.T) { } } +// TestWithCleanup tests that the cleanup goroutine is working +func TestWithCleanup(t *testing.T) { + cache := NewCache(WithCleanup(1)) + + // Set a value with a TTL of 1 second + err := cache.Set("key", "value", 1) + if err != nil { + t.Errorf("Error setting value for key: %s", err) + } + + // Wait for 2 seconds + time.Sleep(2 * time.Second) + + // Check that the value has been deleted + _, err = cache.Get("key") + if err == nil { + t.Errorf("Expected error getting value for key, but got nil") + } +} + func TestMain(m *testing.M) { // Enable the race detector m.Run()