Skip to content

Commit

Permalink
Add simple cache value
Browse files Browse the repository at this point in the history
  • Loading branch information
cuigh committed Nov 29, 2017
1 parent c3c27a0 commit 6f60e2d
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
57 changes: 57 additions & 0 deletions cache/value.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package cache

import (
"sync"
"time"
)

// Value is a simple auto refresh cache hold.
type Value struct {
locker sync.Mutex
value interface{}
next time.Time
TTL time.Duration
Load func() (interface{}, error)
}

// Get return cached value, it will return expired value if dirty is true and loading failed.
func (v *Value) Get(dirty ...bool) (value interface{}, err error) {
if v.value != nil && time.Now().Before(v.next) {
return v.value, nil
}

v.locker.Lock()
defer v.locker.Unlock()

if v.value != nil && time.Now().Before(v.next) {
return v.value, nil
}

value, err = v.Load()
if err == nil {
ttl := v.TTL
if ttl == 0 {
ttl = time.Hour
}
v.value, v.next = value, time.Now().Add(ttl)
} else {
if v.value != nil && (len(dirty) > 0 && dirty[0]) {
return v.value, nil
}
}
return
}

// MustGet return cached value, it panics if error occurs.
func (v *Value) MustGet(dirty ...bool) (value interface{}) {
value, err := v.Get(dirty...)
if err != nil {
panic(err)
}
return value
}

// Reset clears internal cache value.
func (v *Value) Reset() {
v.value = nil
}
41 changes: 41 additions & 0 deletions cache/value_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package cache_test

import (
"testing"
"time"

"errors"

"github.com/cuigh/auxo/cache"
"github.com/cuigh/auxo/test/assert"
)

func TestValue(t *testing.T) {
i := 0
v := cache.Value{
TTL: 100 * time.Millisecond,
Load: func() (interface{}, error) {
if i == 0 {
i++
return &struct{}{}, nil
}
return nil, errors.New("mock error")
},
}

value, err := v.Get()
assert.NoError(t, err)
assert.NotNil(t, value)

time.Sleep(101 * time.Millisecond)

value, err = v.Get()
assert.Error(t, err)
assert.Nil(t, value)

value, err = v.Get(true)
assert.NoError(t, err)
assert.NotNil(t, value)

v.Reset()
}

0 comments on commit 6f60e2d

Please sign in to comment.