Chore: remove old cache implementation
This commit is contained in:
parent
730f5b2d5f
commit
08f414e9c7
10 changed files with 26 additions and 205 deletions
106
common/cache/cache.go
vendored
106
common/cache/cache.go
vendored
|
@ -1,106 +0,0 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Cache store element with a expired time
|
||||
type Cache struct {
|
||||
*cache
|
||||
}
|
||||
|
||||
type cache struct {
|
||||
mapping sync.Map
|
||||
janitor *janitor
|
||||
}
|
||||
|
||||
type element struct {
|
||||
Expired time.Time
|
||||
Payload any
|
||||
}
|
||||
|
||||
// Put element in Cache with its ttl
|
||||
func (c *cache) Put(key any, payload any, ttl time.Duration) {
|
||||
c.mapping.Store(key, &element{
|
||||
Payload: payload,
|
||||
Expired: time.Now().Add(ttl),
|
||||
})
|
||||
}
|
||||
|
||||
// Get element in Cache, and drop when it expired
|
||||
func (c *cache) Get(key any) any {
|
||||
item, exist := c.mapping.Load(key)
|
||||
if !exist {
|
||||
return nil
|
||||
}
|
||||
elm := item.(*element)
|
||||
// expired
|
||||
if time.Since(elm.Expired) > 0 {
|
||||
c.mapping.Delete(key)
|
||||
return nil
|
||||
}
|
||||
return elm.Payload
|
||||
}
|
||||
|
||||
// GetWithExpire element in Cache with Expire Time
|
||||
func (c *cache) GetWithExpire(key any) (payload any, expired time.Time) {
|
||||
item, exist := c.mapping.Load(key)
|
||||
if !exist {
|
||||
return
|
||||
}
|
||||
elm := item.(*element)
|
||||
// expired
|
||||
if time.Since(elm.Expired) > 0 {
|
||||
c.mapping.Delete(key)
|
||||
return
|
||||
}
|
||||
return elm.Payload, elm.Expired
|
||||
}
|
||||
|
||||
func (c *cache) cleanup() {
|
||||
c.mapping.Range(func(k, v any) bool {
|
||||
key := k.(string)
|
||||
elm := v.(*element)
|
||||
if time.Since(elm.Expired) > 0 {
|
||||
c.mapping.Delete(key)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
type janitor struct {
|
||||
interval time.Duration
|
||||
stop chan struct{}
|
||||
}
|
||||
|
||||
func (j *janitor) process(c *cache) {
|
||||
ticker := time.NewTicker(j.interval)
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
c.cleanup()
|
||||
case <-j.stop:
|
||||
ticker.Stop()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func stopJanitor(c *Cache) {
|
||||
c.janitor.stop <- struct{}{}
|
||||
}
|
||||
|
||||
// New return *Cache
|
||||
func New(interval time.Duration) *Cache {
|
||||
j := &janitor{
|
||||
interval: interval,
|
||||
stop: make(chan struct{}),
|
||||
}
|
||||
c := &cache{janitor: j}
|
||||
go j.process(c)
|
||||
C := &Cache{c}
|
||||
runtime.SetFinalizer(C, stopJanitor)
|
||||
return C
|
||||
}
|
70
common/cache/cache_test.go
vendored
70
common/cache/cache_test.go
vendored
|
@ -1,70 +0,0 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCache_Basic(t *testing.T) {
|
||||
interval := 200 * time.Millisecond
|
||||
ttl := 20 * time.Millisecond
|
||||
c := New(interval)
|
||||
c.Put("int", 1, ttl)
|
||||
c.Put("string", "a", ttl)
|
||||
|
||||
i := c.Get("int")
|
||||
assert.Equal(t, i.(int), 1, "should recv 1")
|
||||
|
||||
s := c.Get("string")
|
||||
assert.Equal(t, s.(string), "a", "should recv 'a'")
|
||||
}
|
||||
|
||||
func TestCache_TTL(t *testing.T) {
|
||||
interval := 200 * time.Millisecond
|
||||
ttl := 20 * time.Millisecond
|
||||
now := time.Now()
|
||||
c := New(interval)
|
||||
c.Put("int", 1, ttl)
|
||||
c.Put("int2", 2, ttl)
|
||||
|
||||
i := c.Get("int")
|
||||
_, expired := c.GetWithExpire("int2")
|
||||
assert.Equal(t, i.(int), 1, "should recv 1")
|
||||
assert.True(t, now.Before(expired))
|
||||
|
||||
time.Sleep(ttl * 2)
|
||||
i = c.Get("int")
|
||||
j, _ := c.GetWithExpire("int2")
|
||||
assert.Nil(t, i, "should recv nil")
|
||||
assert.Nil(t, j, "should recv nil")
|
||||
}
|
||||
|
||||
func TestCache_AutoCleanup(t *testing.T) {
|
||||
interval := 10 * time.Millisecond
|
||||
ttl := 15 * time.Millisecond
|
||||
c := New(interval)
|
||||
c.Put("int", 1, ttl)
|
||||
|
||||
time.Sleep(ttl * 2)
|
||||
i := c.Get("int")
|
||||
j, _ := c.GetWithExpire("int")
|
||||
assert.Nil(t, i, "should recv nil")
|
||||
assert.Nil(t, j, "should recv nil")
|
||||
}
|
||||
|
||||
func TestCache_AutoGC(t *testing.T) {
|
||||
sign := make(chan struct{})
|
||||
go func() {
|
||||
interval := 10 * time.Millisecond
|
||||
ttl := 15 * time.Millisecond
|
||||
c := New(interval)
|
||||
c.Put("int", 1, ttl)
|
||||
sign <- struct{}{}
|
||||
}()
|
||||
|
||||
<-sign
|
||||
runtime.GC()
|
||||
}
|
4
common/cache/lrucache.go
vendored
4
common/cache/lrucache.go
vendored
|
@ -64,8 +64,8 @@ type LruCache struct {
|
|||
onEvict EvictCallback
|
||||
}
|
||||
|
||||
// NewLRUCache creates an LruCache
|
||||
func NewLRUCache(options ...Option) *LruCache {
|
||||
// New creates an LruCache
|
||||
func New(options ...Option) *LruCache {
|
||||
lc := &LruCache{
|
||||
lru: list.New(),
|
||||
cache: make(map[any]*list.Element),
|
||||
|
|
20
common/cache/lrucache_test.go
vendored
20
common/cache/lrucache_test.go
vendored
|
@ -19,7 +19,7 @@ var entries = []struct {
|
|||
}
|
||||
|
||||
func TestLRUCache(t *testing.T) {
|
||||
c := NewLRUCache()
|
||||
c := New()
|
||||
|
||||
for _, e := range entries {
|
||||
c.Set(e.key, e.value)
|
||||
|
@ -45,7 +45,7 @@ func TestLRUCache(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestLRUMaxAge(t *testing.T) {
|
||||
c := NewLRUCache(WithAge(86400))
|
||||
c := New(WithAge(86400))
|
||||
|
||||
now := time.Now().Unix()
|
||||
expected := now + 86400
|
||||
|
@ -88,7 +88,7 @@ func TestLRUMaxAge(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestLRUpdateOnGet(t *testing.T) {
|
||||
c := NewLRUCache(WithAge(86400), WithUpdateAgeOnGet())
|
||||
c := New(WithAge(86400), WithUpdateAgeOnGet())
|
||||
|
||||
now := time.Now().Unix()
|
||||
expires := now + 86400/2
|
||||
|
@ -103,7 +103,7 @@ func TestLRUpdateOnGet(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMaxSize(t *testing.T) {
|
||||
c := NewLRUCache(WithSize(2))
|
||||
c := New(WithSize(2))
|
||||
// Add one expired entry
|
||||
c.Set("foo", "bar")
|
||||
_, ok := c.Get("foo")
|
||||
|
@ -117,7 +117,7 @@ func TestMaxSize(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestExist(t *testing.T) {
|
||||
c := NewLRUCache(WithSize(1))
|
||||
c := New(WithSize(1))
|
||||
c.Set(1, 2)
|
||||
assert.True(t, c.Exist(1))
|
||||
c.Set(2, 3)
|
||||
|
@ -130,7 +130,7 @@ func TestEvict(t *testing.T) {
|
|||
temp = key.(int) + value.(int)
|
||||
}
|
||||
|
||||
c := NewLRUCache(WithEvict(evict), WithSize(1))
|
||||
c := New(WithEvict(evict), WithSize(1))
|
||||
c.Set(1, 2)
|
||||
c.Set(2, 3)
|
||||
|
||||
|
@ -138,7 +138,7 @@ func TestEvict(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSetWithExpire(t *testing.T) {
|
||||
c := NewLRUCache(WithAge(1))
|
||||
c := New(WithAge(1))
|
||||
now := time.Now().Unix()
|
||||
|
||||
tenSecBefore := time.Unix(now-10, 0)
|
||||
|
@ -152,7 +152,7 @@ func TestSetWithExpire(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestStale(t *testing.T) {
|
||||
c := NewLRUCache(WithAge(1), WithStale(true))
|
||||
c := New(WithAge(1), WithStale(true))
|
||||
now := time.Now().Unix()
|
||||
|
||||
tenSecBefore := time.Unix(now-10, 0)
|
||||
|
@ -165,11 +165,11 @@ func TestStale(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCloneTo(t *testing.T) {
|
||||
o := NewLRUCache(WithSize(10))
|
||||
o := New(WithSize(10))
|
||||
o.Set("1", 1)
|
||||
o.Set("2", 2)
|
||||
|
||||
n := NewLRUCache(WithSize(2))
|
||||
n := New(WithSize(2))
|
||||
n.Set("3", 3)
|
||||
n.Set("4", 4)
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ func New(options Options) (*Pool, error) {
|
|||
}
|
||||
} else {
|
||||
pool.store = &memoryStore{
|
||||
cache: cache.NewLRUCache(cache.WithSize(options.Size * 2)),
|
||||
cache: cache.New(cache.WithSize(options.Size * 2)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ func NewEnhancer(cfg Config) *ResolverEnhancer {
|
|||
|
||||
if cfg.EnhancedMode != C.DNSNormal {
|
||||
fakePool = cfg.Pool
|
||||
mapping = cache.NewLRUCache(cache.WithSize(4096), cache.WithStale(true))
|
||||
mapping = cache.New(cache.WithSize(4096), cache.WithStale(true))
|
||||
}
|
||||
|
||||
return &ResolverEnhancer{
|
||||
|
|
|
@ -363,13 +363,13 @@ type Config struct {
|
|||
func NewResolver(config Config) *Resolver {
|
||||
defaultResolver := &Resolver{
|
||||
main: transform(config.Default, nil),
|
||||
lruCache: cache.NewLRUCache(cache.WithSize(4096), cache.WithStale(true)),
|
||||
lruCache: cache.New(cache.WithSize(4096), cache.WithStale(true)),
|
||||
}
|
||||
|
||||
r := &Resolver{
|
||||
ipv6: config.IPv6,
|
||||
main: transform(config.Main, defaultResolver),
|
||||
lruCache: cache.NewLRUCache(cache.WithSize(4096), cache.WithStale(true)),
|
||||
lruCache: cache.New(cache.WithSize(4096), cache.WithStale(true)),
|
||||
hosts: config.Hosts,
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Dreamacro/clash/adapter/inbound"
|
||||
"github.com/Dreamacro/clash/common/cache"
|
||||
|
@ -15,7 +14,7 @@ import (
|
|||
"github.com/Dreamacro/clash/log"
|
||||
)
|
||||
|
||||
func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) {
|
||||
func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.LruCache) {
|
||||
client := newClient(c.RemoteAddr(), in)
|
||||
defer client.CloseIdleConnections()
|
||||
|
||||
|
@ -99,7 +98,7 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) {
|
|||
conn.Close()
|
||||
}
|
||||
|
||||
func authenticate(request *http.Request, cache *cache.Cache) *http.Response {
|
||||
func authenticate(request *http.Request, cache *cache.LruCache) *http.Response {
|
||||
authenticator := authStore.Authenticator()
|
||||
if authenticator != nil {
|
||||
credential := parseBasicProxyAuthorization(request)
|
||||
|
@ -109,11 +108,11 @@ func authenticate(request *http.Request, cache *cache.Cache) *http.Response {
|
|||
return resp
|
||||
}
|
||||
|
||||
var authed any
|
||||
if authed = cache.Get(credential); authed == nil {
|
||||
authed, exist := cache.Get(credential)
|
||||
if !exist {
|
||||
user, pass, err := decodeBasicProxyAuthorization(credential)
|
||||
authed = err == nil && authenticator.Verify(user, pass)
|
||||
cache.Put(credential, authed, time.Minute)
|
||||
cache.Set(credential, authed)
|
||||
}
|
||||
if !authed.(bool) {
|
||||
log.Infoln("Auth failed from %s", request.RemoteAddr)
|
||||
|
|
|
@ -2,7 +2,6 @@ package http
|
|||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/Dreamacro/clash/common/cache"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
@ -40,9 +39,9 @@ func NewWithAuthenticate(addr string, in chan<- C.ConnContext, authenticate bool
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var c *cache.Cache
|
||||
var c *cache.LruCache
|
||||
if authenticate {
|
||||
c = cache.New(time.Second * 30)
|
||||
c = cache.New(cache.WithAge(30))
|
||||
}
|
||||
|
||||
hl := &Listener{
|
||||
|
|
|
@ -2,7 +2,6 @@ package mixed
|
|||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/Dreamacro/clash/common/cache"
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
|
@ -16,7 +15,7 @@ import (
|
|||
type Listener struct {
|
||||
listener net.Listener
|
||||
addr string
|
||||
cache *cache.Cache
|
||||
cache *cache.LruCache
|
||||
closed bool
|
||||
}
|
||||
|
||||
|
@ -45,7 +44,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) {
|
|||
ml := &Listener{
|
||||
listener: l,
|
||||
addr: addr,
|
||||
cache: cache.New(30 * time.Second),
|
||||
cache: cache.New(cache.WithAge(30)),
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
|
@ -63,7 +62,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) {
|
|||
return ml, nil
|
||||
}
|
||||
|
||||
func handleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.Cache) {
|
||||
func handleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.LruCache) {
|
||||
conn.(*net.TCPConn).SetKeepAlive(true)
|
||||
|
||||
bufConn := N.NewBufferedConn(conn)
|
||||
|
|
Loading…
Reference in a new issue