Skip to content

Commit

Permalink
set returns bool
Browse files Browse the repository at this point in the history
instead of error, so it's not necessary to check
  • Loading branch information
parMaster committed Nov 27, 2024
1 parent a115308 commit 25c0f06
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 30 deletions.
11 changes: 4 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ See the [examples](https://github.com/parMaster/mcache/tree/main/examples) direc
The `Cacher` interface is used to define the cache operations:
```go
type Cacher[T any] interface {
Set(key string, value T, ttl time.Duration) error
Set(key string, value T, ttl time.Duration) bool
Get(key string) (T, error)
Has(key string) (bool, error)
Del(key string) error
Expand All @@ -70,15 +70,12 @@ if err != nil {
}
```

If the key already exists and is not expired, an error `mcache.ErrKeyExists` will be returned. If the key exists but is expired, the value will be updated.
If the key already exists and is not expired, `false` will be returned. If the key exists but is expired, the value will be updated.

You can also set a key-value pair with an expiration time (in seconds):

```go
err := cache.Set("key", "value", time.Minute)
if err != nil {
// handle error
}
cache.Set("key", "value", time.Minute)
```

The value will automatically expire after the specified duration.
Expand All @@ -96,7 +93,7 @@ if err != nil {

If the key does not exist, an error `mcache.ErrKeyNotFound` will be returned. If the key exists but is expired, an error `mcache.ErrExpired` will be returned, and the key-value pair will be deleted.

Either error or value could be checked to determine if the key exists.
Either error or value could be checked to determine if the key exists. Error is easier to check when the value is a zero value.

### Has

Expand Down
9 changes: 4 additions & 5 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
// Errors for cache
var (
ErrKeyNotFound = errors.New("key not found")
ErrKeyExists = errors.New("key already exists")
ErrExpired = errors.New("key expired")
)

Expand All @@ -30,7 +29,7 @@ type Cache[T any] struct {

// Cacher is an interface for cache.
type Cacher[T any] interface {
Set(key string, value T, ttl time.Duration) error
Set(key string, value T, ttl time.Duration) bool
Get(key string) (T, error)
Has(key string) (bool, error)
Del(key string) error
Expand Down Expand Up @@ -64,13 +63,13 @@ func (cacheItem CacheItem[T]) expired() bool {
// If key already exists, but it's expired, set new value and return nil.
// If key doesn't exist, set new value and return nil.
// If ttl is 0, set value without expiration.
func (c *Cache[T]) Set(key string, value T, ttl time.Duration) error {
func (c *Cache[T]) Set(key string, value T, ttl time.Duration) bool {
c.Lock()
defer c.Unlock()
cached, ok := c.data[key]
if ok {
if !cached.expired() {
return ErrKeyExists
return false
}
}

Expand All @@ -84,7 +83,7 @@ func (c *Cache[T]) Set(key string, value T, ttl time.Duration) error {
value: value,
expiration: expiration,
}
return nil
return true
}

// Get is a method for getting value by key.
Expand Down
35 changes: 17 additions & 18 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ func Test_SimpleTest_Mcache(t *testing.T) {
noSuchKey := "noSuchKey"

for _, item := range testItems {
err := c.Set(item.key, item.value, item.ttl)
assert.NoError(t, err)
result := c.Set(item.key, item.value, item.ttl)
assert.True(t, result)
}

for _, item := range testItems {
Expand Down Expand Up @@ -86,22 +86,21 @@ func Test_SimpleTest_Mcache(t *testing.T) {

c.Set("key", "value", 100*time.Millisecond)
time.Sleep(200 * time.Millisecond)
err = c.Set("key", "newvalue", 100*time.Millisecond)
assert.NoError(t, err)
result := c.Set("key", "newvalue", 100*time.Millisecond)
assert.True(t, result)

// old value should be rewritten
value, err := c.Get("key")
assert.NoError(t, err)
assert.Equal(t, "newvalue", value)

err = c.Set("key", "not a newer value", 1)
if err != nil {
assert.ErrorIs(t, ErrKeyExists, err)
}
result = c.Set("key", "not a newer value", 1)
assert.False(t, result)

time.Sleep(200 * time.Millisecond)
err = c.Set("key", "even newer value", 100*time.Millisecond)
result = c.Set("key", "even newer value", 100*time.Millisecond)
// key should be silently rewritten
assert.NoError(t, err)
assert.True(t, result)
value, err = c.Get("key")
assert.NoError(t, err)
assert.Equal(t, "even newer value", value)
Expand Down Expand Up @@ -135,9 +134,9 @@ func TestConcurrentSetAndGet(t *testing.T) {
key := fmt.Sprintf("key-%d", index)
value := fmt.Sprintf("value-%d", index)

err := cache.Set(key, value, 0)
if err != nil {
t.Errorf("Error setting value for key %s: %s", key, err)
res := cache.Set(key, value, 0)
if res == false {
t.Errorf("Error setting value for key %s", key)
}

result, err := cache.Get(key)
Expand Down Expand Up @@ -177,13 +176,13 @@ func TestWithCleanup(t *testing.T) {
cache := NewCache(WithCleanup[string](time.Millisecond * 100))

// Set a value with a TTL of 1 second
err := cache.Set("key", "value", 1)
assert.NoError(t, err, "Expected no error setting value for key")
res := cache.Set("key", "value", 1)
assert.True(t, res, "Expected successfuly set value for key")

time.Sleep(time.Millisecond * 200)

// Check that the value expired
_, err = cache.Get("key")
_, err := cache.Get("key")
assert.Error(t, err, "Expected the key to expire and be deleted")
}

Expand All @@ -210,8 +209,8 @@ func TestWithSize(t *testing.T) {
key := fmt.Sprintf("key-%d", i)
value := fmt.Sprintf("value-%d", i)

err := cache.Set(key, value, 100*time.Millisecond)
assert.NoError(t, err)
res := cache.Set(key, value, 100*time.Millisecond)
assert.True(t, res, "Expected successfuly set value for key")
}
printAlloc("After Set " + strconv.Itoa(size) + " entries")

Expand Down

0 comments on commit 25c0f06

Please sign in to comment.