Skip to content

Commit 61dc9b3

Browse files
committed
init commit
1 parent ccb041c commit 61dc9b3

361 files changed

Lines changed: 250018 additions & 1 deletion

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.idea/.gitignore

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/go-cache.iml

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,75 @@
1-
# go-cache
1+
# Usage
2+
3+
## What
4+
5+
This repo is a wrapper with [go-cache](https://github.com/patrickmn/go-cache). We use `gocache.GetOrSet` to set or get
6+
cache safely. It means that when multiple threads/go-routing call `gocache.GetOrSet`, the cache will be set only once.
7+
Usually it means we just call database to retrieve data ONLY one time.
8+
9+
#### Install
10+
11+
```
12+
go get -u
13+
```
14+
15+
#### STEP 1: Register all your cache keys
16+
17+
```go
18+
package example
19+
20+
import gocache "go-cache/core"
21+
22+
const (
23+
KeyOrders = "KEY_ORDERS"
24+
KeyUsers = "KEY_USERS"
25+
KeyBooks = "KEY_BOOKS"
26+
KeyModules = "KEY_MODULES"
27+
KeyConfig = "KEY_CONFIG"
28+
)
29+
30+
func RegisterAllCacheKeys() {
31+
registry := gocache.GetRegistryInstance()
32+
registry.Register(&gocache.CacheKey{Key: KeyOrders, Expire: gocache.OneDay})
33+
registry.Register(&gocache.CacheKey{Key: KeyUsers, Expire: gocache.OneMinute})
34+
registry.Register(&gocache.CacheKey{Key: KeyBooks, Expire: gocache.OneHour})
35+
registry.Register(&gocache.CacheKey{Key: KeyModules, Expire: gocache.FiveMinutes})
36+
registry.Register(&gocache.CacheKey{Key: KeyConfig, Expire: gocache.OneMinute})
37+
}
38+
39+
```
40+
41+
#### STEP 2: Use `gocache.GetOrSet` to get or set cache thread safely.
42+
43+
```go
44+
package example
45+
46+
import (
47+
gocache "go-cache/core"
48+
49+
log "github.com/sirupsen/logrus"
50+
)
51+
52+
type Book struct {
53+
name string
54+
}
55+
56+
func StartApp() {
57+
RegisterAllCacheKeys()
58+
books, ok := gocache.GetOrSet(KeyBooks, func(cache *gocache.CacheKey) (interface{}, error) {
59+
// you also can call database to retrieve cache here.
60+
return []Book{
61+
{name: "i love coding"},
62+
{name: "coding is great"},
63+
}, nil
64+
})
65+
66+
if ok {
67+
log.Info("Got books and also set cache.")
68+
log.Info(books)
69+
} else {
70+
log.Info("No books found in cache also in database maybe")
71+
}
72+
}
73+
```
74+
75+
example refer to `./example`

core/consts.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package gocache
2+
3+
import "time"
4+
5+
const (
6+
OneDay = 24 * time.Hour
7+
OneHour = 1 * time.Hour
8+
OneMinute = 1 * time.Minute
9+
FiveMinutes = 5 * time.Minute
10+
defaultCacheExpiration = OneDay
11+
defaultCacheCleanupInterval = OneHour
12+
)

core/instance.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package gocache
2+
3+
import (
4+
"sync"
5+
6+
"github.com/patrickmn/go-cache"
7+
log "github.com/sirupsen/logrus"
8+
)
9+
10+
var cacheInstance *cache.Cache
11+
var onceCreateCacheInstance sync.Once
12+
13+
func GetInstance() *cache.Cache {
14+
onceCreateCacheInstance.Do(func() {
15+
cacheInstance = cache.New(defaultCacheExpiration, defaultCacheCleanupInterval)
16+
})
17+
18+
return cacheInstance
19+
}
20+
21+
type CallbackIfCacheMissing func(cache *CacheKey) (interface{}, error)
22+
23+
func GetOrSet(key string, callback CallbackIfCacheMissing) (interface{}, bool) {
24+
keyRegistry := GetRegistryInstance()
25+
cacheInstance := GetInstance()
26+
cache := keyRegistry.Get(key)
27+
if cache == nil {
28+
log.Panicf("Cache key %v not found in registry, you need to Register it first", key)
29+
return nil, false
30+
}
31+
32+
_, ok := cacheInstance.Get(cache.Key)
33+
if !ok { // if cache missing, set cache thread safely
34+
cache.Sync.Lock()
35+
defer cache.Sync.Unlock()
36+
_, okAgain := cacheInstance.Get(cache.Key)
37+
if !okAgain {
38+
log.Infof("Cache missing for %s, setting cache with callback ...", cache.Key)
39+
value, err := callback(cache)
40+
if err == nil {
41+
log.Infof("Set cache for %s successfully", cache.Key)
42+
cacheInstance.Set(cache.Key, value, cache.Expire)
43+
} else {
44+
log.Errorf("Set cache for %s failed: %v", cache.Key, err)
45+
}
46+
}
47+
}
48+
49+
return cacheInstance.Get(cache.Key)
50+
}

core/instance_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package gocache_test
2+
3+
import "testing"
4+
5+
func TestInstance_UsageExample(t *testing.T) {
6+
t.Parallel()
7+
8+
}

core/key.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package gocache
2+
3+
import (
4+
"sync"
5+
"time"
6+
7+
"github.com/patrickmn/go-cache"
8+
)
9+
10+
type CacheKey struct {
11+
Key string
12+
Sync sync.Mutex
13+
Expire time.Duration
14+
}
15+
16+
var (
17+
Default = &CacheKey{Key: "__DEFAULT_KEY__", Expire: cache.DefaultExpiration}
18+
)

core/registry.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package gocache
2+
3+
import (
4+
"sync"
5+
)
6+
7+
type Registry interface {
8+
Register(key *CacheKey)
9+
Get(key string) *CacheKey
10+
}
11+
12+
type RegistryImpl struct {
13+
keymap sync.Map
14+
}
15+
16+
func (r *RegistryImpl) Get(key string) *CacheKey {
17+
value, ok := r.keymap.Load(key)
18+
if ok {
19+
return value.(*CacheKey)
20+
} else {
21+
return nil
22+
}
23+
}
24+
25+
func (r *RegistryImpl) Register(cacheKey *CacheKey) {
26+
r.keymap.Store(cacheKey.Key, cacheKey)
27+
}
28+
29+
var onceCreateRegistry sync.Once
30+
var registryInstance Registry
31+
32+
func GetRegistryInstance() Registry {
33+
onceCreateRegistry.Do(func() {
34+
registryInstance = &RegistryImpl{}
35+
})
36+
37+
return registryInstance
38+
}

0 commit comments

Comments
 (0)