fix(tinykv): remove sliding feature

This commit is contained in:
Alexis Couvreur
2022-10-03 21:45:22 +00:00
parent b6ea948351
commit b220bc4bf7
2 changed files with 3 additions and 124 deletions

View File

@@ -10,35 +10,19 @@ import (
type timeout struct {
expiresAt time.Time
expiresAfter time.Duration
isSliding bool
key string
}
func newTimeout(
key string,
expiresAfter time.Duration,
isSliding bool) *timeout {
expiresAfter time.Duration) *timeout {
return &timeout{
expiresAt: time.Now().Add(expiresAfter),
expiresAfter: expiresAfter,
isSliding: isSliding,
key: key,
}
}
func (to *timeout) slide() {
if to == nil {
return
}
if !to.isSliding {
return
}
if to.expiresAfter <= 0 {
return
}
to.expiresAt = time.Now().Add(to.expiresAfter)
}
func (to *timeout) expired() bool {
if to == nil {
return false
@@ -90,7 +74,6 @@ type KV[T any] interface {
type putOpt struct {
expiresAfter time.Duration
isSliding bool
cas func(interface{}, bool) bool
}
@@ -104,13 +87,6 @@ func ExpiresAfter(expiresAfter time.Duration) PutOption {
}
}
// IsSliding sets if the entry would get expired in a sliding manner
func IsSliding(isSliding bool) PutOption {
return func(opt *putOpt) {
opt.isSliding = isSliding
}
}
// CAS for performing a compare and swap
func CAS(cas func(oldValue interface{}, found bool) bool) PutOption {
return func(opt *putOpt) {
@@ -173,7 +149,6 @@ func (kv *store[T]) Get(k string) (T, bool) {
if !ok {
return zero, ok
}
e.slide()
if e.expired() {
go notifyExpirations(map[string]T{k: e.value}, kv.onExpire)
delete(kv.kv, k)
@@ -217,7 +192,6 @@ func (kv *store[T]) Entries() (entries map[string]entry[T]) {
t := &timeout{
expiresAt: v.expiresAt,
expiresAfter: v.expiresAfter,
isSliding: v.isSliding,
key: k,
}
e.timeout = t
@@ -239,7 +213,7 @@ func (kv *store[T]) Put(k string, v T, options ...PutOption) error {
kv.mx.Lock()
defer kv.mx.Unlock()
if opt.expiresAfter > 0 {
e.timeout = newTimeout(k, opt.expiresAfter, opt.isSliding)
e.timeout = newTimeout(k, opt.expiresAfter)
timeheapPush(&kv.heap, e.timeout)
}
if opt.cas != nil {
@@ -261,12 +235,10 @@ func (e *entry[T]) MarshalJSON() ([]byte, error) {
Value T `json:"value"`
ExpiresAt time.Time `json:"expiresAt"`
ExpiresAfter time.Duration `json:"expiresAfter"`
IsSliding bool `json:"isSliding"`
}{
Value: e.value,
ExpiresAt: e.expiresAt,
ExpiresAfter: e.expiresAfter,
IsSliding: e.isSliding,
})
} else {
return json.Marshal(&struct {
@@ -290,7 +262,6 @@ func (kv *store[T]) UnmarshalJSON(b []byte) error {
json.Unmarshal([]byte(b), &result)
for k, v := range result {
// TODO: Handle sliding...
kv.Put(k, v.Value, ExpiresAfter(v.ExpiresAfter))
}
@@ -311,8 +282,6 @@ func (e *minimalEntry[T]) UnmarshalJSON(b []byte) error {
e.Value = result.Value
e.ExpiresAfter = time.Until(result.ExpiresAt)
}
// TODO: Handle sliding...
return nil
}
@@ -332,7 +301,6 @@ func (kv *store[T]) cas(k string, e *entry[T], casFunc func(interface{}, bool) b
old.value = e.value
e = old
}
e.slide()
kv.kv[k] = e
return nil
}

View File

@@ -115,7 +115,7 @@ func TestMarshalJSON(t *testing.T) {
jsonb, err := json.Marshal(rg)
assert.Nil(err)
json := string(jsonb)
assert.Regexp("{\"1\":{\"value\":1},\"2\":{\"value\":2},\"3\":{\"value\":3,\"expiresAt\":\"\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d.\\d\\d\\d\\d\\d\\d\\d\\d\\dZ\",\"expiresAfter\":3000000000000,\"isSliding\":false}}", json)
assert.Regexp("{\"1\":{\"value\":1},\"2\":{\"value\":2},\"3\":{\"value\":3,\"expiresAt\":\"\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d.\\d\\d\\d\\d\\d\\d\\d\\d\\dZ\",\"expiresAfter\":3000000000000}}", json)
}
func TestUnmarshalJSON(t *testing.T) {
@@ -168,36 +168,6 @@ OUT01:
}
}
func Test02(t *testing.T) {
assert := assert.New(t)
rg := New[int](time.Millisecond * 30)
rg.Put("1", 1)
v, ok := rg.Get("1")
assert.True(ok)
assert.Equal(1, v)
rg.Put("1", 1, ExpiresAfter(time.Millisecond*50), IsSliding(true))
<-time.After(time.Millisecond * 40)
v, ok = rg.Get("1")
assert.True(ok)
assert.Equal(1, v)
<-time.After(time.Millisecond * 10)
v, ok = rg.Get("1")
assert.True(ok)
assert.Equal(1, v)
<-time.After(time.Millisecond * 10)
v, ok = rg.Get("1")
assert.True(ok)
assert.Equal(1, v)
<-time.After(time.Millisecond * 100)
v, ok = rg.Get("1")
assert.False(ok)
assert.NotEqual(1, v)
}
func Test03(t *testing.T) {
assert := assert.New(t)
var putAt time.Time
@@ -261,30 +231,6 @@ func Test05(t *testing.T) {
}
}
func Test06(t *testing.T) {
assert := assert.New(t)
kv := New(
time.Millisecond,
func(k string, v interface{}) {
t.Fail()
})
err := kv.Put("1", 1, ExpiresAfter(10*time.Millisecond), IsSliding(true))
assert.NoError(err)
for i := 0; i < 100; i++ {
_, ok := kv.Get("1")
assert.True(ok)
<-time.After(time.Millisecond)
}
kv.Delete("1")
<-time.After(time.Millisecond * 30)
_, ok := kv.Get("1")
assert.False(ok)
}
func Test07(t *testing.T) {
assert := assert.New(t)
@@ -345,41 +291,6 @@ func Test09IgnoreTimeoutParamsOnCAS(t *testing.T) {
assert.False(ok)
}
func Test10(t *testing.T) {
assert := assert.New(t)
key := "QQG"
kv := New[interface{}](time.Millisecond)
err := kv.Put(
key, "G",
CAS(func(interface{}, bool) bool { return true }),
IsSliding(true),
ExpiresAfter(time.Millisecond*15))
assert.NoError(err)
<-time.After(time.Millisecond * 12)
v, ok := kv.Get(key)
assert.True(ok)
assert.Equal("G", v)
<-time.After(time.Millisecond * 12)
err = kv.Put(key, "OK",
CAS(func(currentValue interface{}, found bool) bool {
assert.True(found)
assert.Equal("G", currentValue)
return true
}))
assert.NoError(err)
<-time.After(time.Millisecond * 12)
_, ok = kv.Get(key)
assert.True(ok)
}
func Test11(t *testing.T) {
assert := assert.New(t)