Skip to content

Commit

Permalink
Merge pull request #11 from FishGoddess/develop
Browse files Browse the repository at this point in the history
v0.6.0-alpha
  • Loading branch information
FishGoddess authored Jan 13, 2024
2 parents a2285c6 + 0426d61 commit b57d3a2
Show file tree
Hide file tree
Showing 34 changed files with 322 additions and 252 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- name: Setup
uses: actions/setup-go@v4
with:
go-version: "1.17"
go-version: "1.20"
- run: go version

- name: Checkout
Expand Down
6 changes: 5 additions & 1 deletion FUTURE.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
## ✒ 未来版本的新特性 (Features in future versions)

### v0.6.x

* [ ] 梳理代码,优化代码风格,精简部分代码和注释
* [ ] 完善监控上报器,提供更多缓存信息查询的方法

### v0.5.x

* [ ] ~~提供一个清空并设置全量值的方法,方便定时数据的全量替换~~
目前还找不到一个合适的设计去加入这个功能,并且也不是非常刚需,通过业务手段可以处理,所以先不加
* [ ] 完善监控上报器,提供更多缓存信息查询的方法

### v0.4.x

Expand Down
7 changes: 7 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
## ✒ 历史版本的特性介绍 (Features in old versions)

### v0.6.0-alpha

> 此版本发布于 2024-01-13
* 受小徒弟的灵感激发,进行 loader 代码的调整
* 把 cache 结构去掉,精简这部分设计

### v0.5.0

> 此版本发布于 2023-11-30
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
all: test bench

test:
go test -cover ./...
go test -cover -count=1 -test.cpu=1 ./...

bench:
go test -v -bench=. -benchtime=1s ./_examples/performance_test.go
go test -v ./_examples/performance_test.go -bench=. -benchtime=1s

fmt:
go fmt ./...
2 changes: 1 addition & 1 deletion README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Go Doc](_icons/godoc.svg)](https://pkg.go.dev/github.com/FishGoddess/cachego)
[![License](_icons/license.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
[![License](_icons/coverage.svg)](_icons/coverage.svg)
[![Coverage](_icons/coverage.svg)](_icons/coverage.svg)
![Test](https://github.com/FishGoddess/cachego/actions/workflows/test.yml/badge.svg)

**cachego** is an api friendly memory-based cache for [GoLang](https://golang.org) applications.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Go Doc](_icons/godoc.svg)](https://pkg.go.dev/github.com/FishGoddess/cachego)
[![License](_icons/license.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
[![License](_icons/coverage.svg)](_icons/coverage.svg)
[![Coverage](_icons/coverage.svg)](_icons/coverage.svg)
![Test](https://github.com/FishGoddess/cachego/actions/workflows/test.yml/badge.svg)

**cachego** 是一个拥有分片机制的轻量级内存缓存库,API 友好,支持多种数据淘汰机制,可以应用于所有的 [GoLang](https://golang.org) 应用程序中。
Expand Down
7 changes: 1 addition & 6 deletions _examples/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,5 @@ func main() {
// Duration is the duration between two loop of fn, optional.
// Run will start a new goroutine and run the task loop.
// The task will stop if context is done.
task.New(printContextValue).
Before(beforePrint).
After(afterPrint).
Context(ctx).
Duration(time.Second).
Run()
task.New(printContextValue).Before(beforePrint).After(afterPrint).Context(ctx).Duration(time.Second).Run()
}
4 changes: 2 additions & 2 deletions _icons/coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed _icons/jetbrains.png
Binary file not shown.
91 changes: 21 additions & 70 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package cachego

import (
"context"
"sync"
"time"

"github.com/FishGoddess/cachego/pkg/task"
Expand All @@ -27,20 +26,6 @@ const (
NoTTL = 0
)

const (
// standard cache is a simple cache with locked map.
// It evicts entries randomly if cache size reaches to max entries.
standard CacheType = "standard"

// lru cache is a cache using lru to evict entries.
// More details see https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU).
lru CacheType = "lru"

// lfu cache is a cache using lfu to evict entries.
// More details see https://en.wikipedia.org/wiki/Cache_replacement_policies#Least-frequently_used_(LFU).
lfu CacheType = "lfu"
)

var (
newCaches = map[CacheType]func(conf *config) Cache{
standard: newStandardCache,
Expand All @@ -49,29 +34,6 @@ var (
}
)

// CacheType is the type of cache.
type CacheType string

// String returns the cache type in string form.
func (ct CacheType) String() string {
return string(ct)
}

// IsStandard returns if cache type is standard.
func (ct CacheType) IsStandard() bool {
return ct == standard
}

// IsLRU returns if cache type is lru.
func (ct CacheType) IsLRU() bool {
return ct == lru
}

// IsLFU returns if cache type is lfu.
func (ct CacheType) IsLFU() bool {
return ct == lfu
}

// Cache is the core interface of cachego.
// We provide some implements including standard cache and sharding cache.
type Cache interface {
Expand Down Expand Up @@ -101,38 +63,10 @@ type Cache interface {
// Reset resets cache to initial status which is like a new cache.
Reset()

// Loader loads a value to cache.
// See Loader interface.
Loader
}

type cache struct {
*config
Loader

lock sync.RWMutex
}

func (c *cache) setup(conf *config, cache Cache) {
c.config = conf
c.Loader = NewLoader(cache, conf.singleflight)
}

// RunGCTask runs a gc task in a new goroutine and returns a cancel function to cancel the task.
// However, you don't need to call it manually for most time, instead, use options is a better choice.
// Making it a public function is for more customizations in some situations.
// For example, using options to run gc task is un-cancelable, so you can use it to run gc task by your own
// and get a cancel function to cancel the gc task.
func RunGCTask(cache Cache, duration time.Duration) (cancel func()) {
fn := func(ctx context.Context) {
cache.GC()
}

ctx := context.Background()
ctx, cancel = context.WithCancel(ctx)

go task.New(fn).Context(ctx).Duration(duration).Run()
return cancel
// Load loads a key with ttl to cache and returns an error if failed.
// We recommend you use this method to load missed keys to cache,
// because it may use singleflight to reduce the times calling load function.
Load(key string, ttl time.Duration, load func() (value interface{}, err error)) (value interface{}, err error)
}

func newCache(withReport bool, opts ...Option) (cache Cache, reporter *Reporter) {
Expand Down Expand Up @@ -180,3 +114,20 @@ func NewCache(opts ...Option) (cache Cache) {
func NewCacheWithReport(opts ...Option) (cache Cache, reporter *Reporter) {
return newCache(true, opts...)
}

// RunGCTask runs a gc task in a new goroutine and returns a cancel function to cancel the task.
// However, you don't need to call it manually for most time, instead, use options is a better choice.
// Making it a public function is for more customizations in some situations.
// For example, using options to run gc task is un-cancelable, so you can use it to run gc task by your own
// and get a cancel function to cancel the gc task.
func RunGCTask(cache Cache, duration time.Duration) (cancel func()) {
fn := func(ctx context.Context) {
cache.GC()
}

ctx := context.Background()
ctx, cancel = context.WithCancel(ctx)

go task.New(fn).Context(ctx).Duration(duration).Run()
return cancel
}
41 changes: 10 additions & 31 deletions cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,10 @@ const (
maxTestEntries = 10
)

// go test -v -cover -run=^TestCacheType$
func TestCacheType(t *testing.T) {
if standard.String() != string(standard) {
t.Fatalf("standard.String() %s is wrong", standard.String())
}

if lru.String() != string(lru) {
t.Fatalf("lru.String() %s is wrong", lru.String())
}

if lfu.String() != string(lfu) {
t.Fatalf("lfu.String() %s is wrong", lfu.String())
}

if !standard.IsStandard() {
t.Fatal("!standard.IsStandard()")
}

if !lru.IsLRU() {
t.Fatal("!standard.IsLRU()")
}

if !lfu.IsLFU() {
t.Fatal("!standard.IsLFU()")
}
}

type testCache struct {
cache
*config
loader *loader

count int32
}

Expand Down Expand Up @@ -84,6 +59,10 @@ func (tc *testCache) GC() (cleans int) {

func (tc *testCache) Reset() {}

func (tc *testCache) Load(key string, ttl time.Duration, load func() (value interface{}, err error)) (value interface{}, err error) {
return nil, nil
}

func testCacheGet(t *testing.T, cache Cache) {
value, found := cache.Get("key")
if found {
Expand Down Expand Up @@ -273,7 +252,7 @@ func testCacheImplement(t *testing.T, cache Cache) {
}
}

// go test -v -cover=^TestNewCache$
// go test -v -cover -count=1 -test.cpu=1=^TestNewCache$
func TestNewCache(t *testing.T) {
cache := NewCache()

Expand Down Expand Up @@ -317,7 +296,7 @@ func TestNewCache(t *testing.T) {
cache = NewCache(WithLRU(0))
}

// go test -v -cover=^TestNewCacheWithReport$
// go test -v -cover -count=1 -test.cpu=1=^TestNewCacheWithReport$
func TestNewCacheWithReport(t *testing.T) {
cache, reporter := NewCacheWithReport()

Expand All @@ -335,7 +314,7 @@ func TestNewCacheWithReport(t *testing.T) {
}
}

// go test -v -cover=^TestRunGCTask$
// go test -v -cover -count=1 -test.cpu=1=^TestRunGCTask$
func TestRunGCTask(t *testing.T) {
cache := new(testCache)

Expand Down
52 changes: 52 additions & 0 deletions cache_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2024 FishGoddess. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cachego

const (
// standard cache is a simple cache with locked map.
// It evicts entries randomly if cache size reaches to max entries.
standard CacheType = "standard"

// lru cache is a cache using lru to evict entries.
// More details see https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU).
lru CacheType = "lru"

// lfu cache is a cache using lfu to evict entries.
// More details see https://en.wikipedia.org/wiki/Cache_replacement_policies#Least-frequently_used_(LFU).
lfu CacheType = "lfu"
)

// CacheType is the type of cache.
type CacheType string

// String returns the cache type in string form.
func (ct CacheType) String() string {
return string(ct)
}

// IsStandard returns if cache type is standard.
func (ct CacheType) IsStandard() bool {
return ct == standard
}

// IsLRU returns if cache type is lru.
func (ct CacheType) IsLRU() bool {
return ct == lru
}

// IsLFU returns if cache type is lfu.
func (ct CacheType) IsLFU() bool {
return ct == lfu
}
44 changes: 44 additions & 0 deletions cache_type_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2024 FishGoddess. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cachego

import "testing"

// go test -v -cover -count=1 -test.cpu=1 -run=^TestCacheType$
func TestCacheType(t *testing.T) {
if standard.String() != string(standard) {
t.Fatalf("standard.String() %s is wrong", standard.String())
}

if lru.String() != string(lru) {
t.Fatalf("lru.String() %s is wrong", lru.String())
}

if lfu.String() != string(lfu) {
t.Fatalf("lfu.String() %s is wrong", lfu.String())
}

if !standard.IsStandard() {
t.Fatal("!standard.IsStandard()")
}

if !lru.IsLRU() {
t.Fatal("!standard.IsLRU()")
}

if !lfu.IsLFU() {
t.Fatal("!standard.IsLFU()")
}
}
2 changes: 1 addition & 1 deletion config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func isConfigEquals(conf1 *config, conf2 *config) bool {
return true
}

// go test -v -cover -run=^TestApplyOptions$
// go test -v -cover -count=1 -test.cpu=1 -run=^TestApplyOptions$
func TestApplyOptions(t *testing.T) {
got := &config{
shardings: 0,
Expand Down
Loading

0 comments on commit b57d3a2

Please sign in to comment.