From bf46501a1049667338295ff74df82b6d32bbffab Mon Sep 17 00:00:00 2001 From: dragon Date: Fri, 27 Dec 2024 17:32:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20cache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 + pkg/server.go | 8 ++++ pkg/services/cache.go | 96 ++++++++++++++++++++++++++++++++++++++++-- pkg/services/config.go | 58 +++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 pkg/services/config.go diff --git a/README.md b/README.md index 134c8ac..642049a 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ > 新一代 Gitea Pages,替换之前的 caddy-gitea-proxy +注意,默认实现未考虑高并发高负载环境, + ## TODO - [ ] CNAME 自定义域名 diff --git a/pkg/server.go b/pkg/server.go index d092a8d..992391e 100644 --- a/pkg/server.go +++ b/pkg/server.go @@ -6,6 +6,14 @@ import ( type ServerOptions struct { Domain string + Cache services.Config +} + +func DefaultOptions(domain string) *ServerOptions { + return &ServerOptions{ + Domain: domain, + Cache: services.NewConfigMemory(), + } } type Server struct { diff --git a/pkg/services/cache.go b/pkg/services/cache.go index 6525513..cb82be4 100644 --- a/pkg/services/cache.go +++ b/pkg/services/cache.go @@ -1,7 +1,97 @@ package services +import ( + "errors" + "io" + "sync" + "time" +) + type Cache interface { - Put(key string, value []byte) error - Get(key string) ([]byte, error) - Delete(key string) error + Put(key string, reader io.Reader) error + Get(key string) (io.ReadSeekCloser, error) + Delete(pattern string) error + io.Closer +} + +var ErrCacheOutOfMemory = errors.New("内容无法被缓存,超过最大限定值") + +type CacheMemory struct { + l sync.RWMutex + data map[string][]byte + maxAge time.Duration + sizeGl int + sizeOne int + + current int + cache []byte + ordered []string +} + +func NewCacheMemory(maxUsage, maxGlobalUsage int) *CacheMemory { + return &CacheMemory{ + data: make(map[string][]byte), + l: sync.RWMutex{}, + sizeGl: maxGlobalUsage, + sizeOne: maxUsage, + + cache: make([]byte, maxUsage+1), + ordered: make([]string, 0), + } +} + +func (c *CacheMemory) Put(key string, reader io.Reader) error { + c.l.Lock() + defer c.l.Unlock() + size, err := io.ReadAtLeast(reader, c.cache, 0) + if err != nil { + return err + } + if size == len(c.cache) { + return ErrCacheOutOfMemory + } + needed := c.sizeGl - c.current + size + if needed < 0 { + // 清理旧的内容 + count := 0 + for i, k := range c.ordered { + needed += len(c.data[k]) + if needed > 0 { + break + } + count = i + 1 + } + + if needed < 0 { + // 清理全部内容也无法留出空间 + return ErrCacheOutOfMemory + } + for _, s := range c.ordered[:count] { + delete(c.data, s) + c.current -= len(c.data) + } + c.ordered = c.ordered[count:] + } + + dest := make([]byte, size) + copy(dest, c.cache[:size]) + c.data[key] = dest + c.ordered = append(c.ordered, key) + c.current += len(dest) + return nil +} + +func (c *CacheMemory) Get(key string) (io.ReadSeekCloser, error) { + //TODO implement me + panic("implement me") +} + +func (c *CacheMemory) Delete(key string) error { + //TODO implement me + panic("implement me") +} + +func (c *CacheMemory) Close() error { + //TODO implement me + panic("implement me") } diff --git a/pkg/services/config.go b/pkg/services/config.go new file mode 100644 index 0000000..c96db81 --- /dev/null +++ b/pkg/services/config.go @@ -0,0 +1,58 @@ +package services + +import ( + "io" + "os" + "sync" +) + +type Config interface { + Put(key string, value string) error + Get(key string) (string, error) + Delete(key string) error + io.Closer +} + +func NewConfigMemory() Config { + return &ConfigMemory{ + data: make(map[string]string), + lock: sync.RWMutex{}, + } +} + +// ConfigMemory 一个简单的内存配置归档,仅用于测试 +type ConfigMemory struct { + data map[string]string + lock sync.RWMutex +} + +func (m *ConfigMemory) Put(key string, value string) error { + m.lock.Lock() + defer m.lock.Unlock() + m.data[key] = value + return nil +} + +func (m *ConfigMemory) Get(key string) (string, error) { + m.lock.RLock() + defer m.lock.RUnlock() + v, ok := m.data[key] + if !ok { + return "", os.ErrNotExist + } + return v, nil +} + +func (m *ConfigMemory) Delete(key string) error { + m.lock.Lock() + defer m.lock.Unlock() + delete(m.data, key) + return nil +} + +func (m *ConfigMemory) Close() error { + m.lock.Lock() + defer m.lock.Unlock() + clear(m.data) + return nil +}