feat: add setnx (if not exists, set kv)
Signed-off-by: rfyiamcool <rfyiamcool@163.com>
This commit is contained in:
16
bucket.go
16
bucket.go
@@ -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)
|
||||
|
9
cache.go
9
cache.go
@@ -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))
|
||||
|
@@ -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()
|
||||
|
@@ -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`:
|
||||
|
||||
|
Reference in New Issue
Block a user