feat: add setnx (if not exists, set kv)

Signed-off-by: rfyiamcool <rfyiamcool@163.com>
This commit is contained in:
rfyiamcool
2023-10-20 10:36:04 +08:00
parent 0f8575167d
commit dd0671989b
4 changed files with 54 additions and 0 deletions

View File

@@ -35,6 +35,22 @@ func (b *bucket[T]) get(key string) *Item[T] {
return b.lookup[key]
}
func (b *bucket[T]) setnx(key string, value T, duration time.Duration, track bool) *Item[T] {
b.Lock()
defer b.Unlock()
item := b.lookup[key]
if item != nil {
return item
}
expires := time.Now().Add(duration).UnixNano()
item = newItem(key, value, expires, track)
b.lookup[key] = item
return item
}
func (b *bucket[T]) set(key string, value T, duration time.Duration, track bool) (*Item[T], *Item[T]) {
expires := time.Now().Add(duration).UnixNano()
item := newItem(key, value, expires, track)

View File

@@ -146,6 +146,11 @@ func (c *Cache[T]) Set(key string, value T, duration time.Duration) {
c.set(key, value, duration, false)
}
// Setnx set the value in the cache for the specified duration if not exists
func (c *Cache[T]) Setnx(key string, value T, duration time.Duration) {
c.setnx(key, value, duration, false)
}
// Replace the value if it exists, does not set if it doesn't.
// Returns true if the item existed an was replaced, false otherwise.
// Replace does not reset item's TTL
@@ -200,6 +205,10 @@ func (c *Cache[T]) set(key string, value T, duration time.Duration, track bool)
return item
}
func (c *Cache[T]) setnx(key string, value T, duration time.Duration, track bool) *Item[T] {
return c.bucket(key).setnx(key, value, duration, track)
}
func (c *Cache[T]) bucket(key string) *bucket[T] {
h := fnv.New32a()
h.Write([]byte(key))

View File

@@ -12,6 +12,27 @@ import (
"github.com/karlseguin/ccache/v3/assert"
)
func Test_Setnx(t *testing.T) {
cache := New(Configure[string]())
defer cache.Stop()
assert.Equal(t, cache.ItemCount(), 0)
cache.Set("spice", "flow", time.Minute)
assert.Equal(t, cache.ItemCount(), 1)
// set if exists
cache.Setnx("spice", "worm", time.Minute)
assert.Equal(t, cache.ItemCount(), 1)
assert.Equal(t, cache.Get("spice").Value(), "flow")
// set if not exists
cache.Delete("spice")
cache.Setnx("spice", "worm", time.Minute)
assert.Equal(t, cache.Get("spice").Value(), "worm")
assert.Equal(t, cache.ItemCount(), 1)
}
func Test_CacheDeletesAValue(t *testing.T) {
cache := New(Configure[string]())
defer cache.Stop()

View File

@@ -122,6 +122,14 @@ cache.Replace("user:4", user)
`Replace` returns true if the item existed (and thus was replaced). In the case where the key was not in the cache, the value *is not* inserted and false is returned.
### Setnx
Set the value if not exists. setnx will first check whether kv exists. If it does not exist, set kv in cache. this operation is atomic.
```go
cache.Set("user:4", user, time.Minute * 10)
```
### GetDropped
You can get the number of keys evicted due to memory pressure by calling `GetDropped`: