Initial commit

This commit is contained in:
Cruise Zhao
2020-04-06 19:57:19 +08:00
commit 2fc86fd0a1
42 changed files with 4056 additions and 0 deletions

122
cache/cache.go vendored Normal file
View File

@@ -0,0 +1,122 @@
package cache
import (
"errors"
"github.com/creachadair/cityhash"
"globalfintech/golib/tlog"
"sync"
"time"
)
//API
var Nil error = errors.New("cache: nil")
func Set(key string, value interface{}) error {
return SetEx(key, value, 86400)
}
func SetEx(key string, value interface{}, exp int) error {
return setEx(key, value, exp)
}
func Get(key string) (interface{}, error) {
return get(key)
}
func Del(key string) error {
return del(key)
}
//internal
var dbs map[byte]*db
type db struct {
m map[string]*item
t time.Duration
sync.RWMutex
}
type item struct {
t int
d interface{}
}
func init() {
if dbs == nil {
dbs = make(map[byte]*db, 256)
for i := 0; i <= 255; i++ {
dbs[byte(i)] = newdb(time.Duration(3600+i) * time.Second)
}
}
}
func newdb(t time.Duration) *db {
ret := &db{
t: t,
m: make(map[string]*item),
}
go ret.flush()
return ret
}
//定期扫描过期的key
func (this *db) flush() {
for range time.NewTicker(this.t).C {
this.doflush()
}
}
func (this *db) doflush() {
start := time.Now()
tt := int(start.Unix())
var i, j int
this.Lock()
for key, item := range this.m {
i++
if item.t != 0 && item.t < tt {
j++
delete(this.m, key)
}
}
this.Unlock()
tlog.Infof("FlushCacheKey||Totoal=%d||Expired=%d||t=%s", i, j, time.Since(start))
}
func setEx(key string, value interface{}, exp int) error {
if exp <= 0 {
return errors.New("args error, expTime must be > 0")
}
db, _ := dbs[hash(key)]
db.Lock()
db.m[key] = &item{
d: value,
t: int(time.Now().Unix()) + exp}
db.Unlock()
return nil
}
func get(key string) (interface{}, error) {
db, _ := dbs[hash(key)]
db.RLock()
item, ok := db.m[key]
db.RUnlock()
if ok {
if item.t >= int(time.Now().Unix()) {
return item.d, nil
}
del(key)
}
return nil, Nil
}
func del(key string) error {
db, _ := dbs[hash(key)]
db.Lock()
delete(db.m, key)
db.Unlock()
return nil
}
func hash(key string) byte {
return byte(cityhash.Hash32([]byte(key)))
}

88
cache/cache_test.go vendored Normal file
View File

@@ -0,0 +1,88 @@
package cache
import (
"fmt"
"testing"
"time"
)
type T struct {
A int
B string
}
func TestSet(t *testing.T) {
err := Set("test", "test")
if err != nil {
fmt.Println(err)
return
}
value, err := Get("test")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(value.(string))
}
func TestStruct(t *testing.T) {
err := Set("struct", T{A: 1, B: "testtest"})
if err != nil {
fmt.Println(err)
return
}
value1, err := Get("struct")
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v\n", value1.(T))
}
func TestStruct1(t *testing.T) {
err := Set("struct", &T{A: 1, B: "testtest"})
if err != nil {
fmt.Println(err)
return
}
value1, err := Get("struct")
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v\n", value1.(*T))
}
func TestDel(t *testing.T) {
err := Del("test")
if err != nil {
fmt.Println(err)
return
}
value, err := Get("test")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(value.(string))
}
func TestSetEx(t *testing.T) {
err := SetEx("testex", []byte("testex"), 2)
if err != nil {
fmt.Println(err)
}
valueEx, err := Get("testex")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(valueEx.([]byte))
time.Sleep(3 * time.Second)
valueEx, err = Get("testex")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(valueEx.([]byte))
}