新增 cache
This commit is contained in:
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
> 新一代 Gitea Pages,替换之前的 caddy-gitea-proxy
|
> 新一代 Gitea Pages,替换之前的 caddy-gitea-proxy
|
||||||
|
|
||||||
|
注意,默认实现未考虑高并发高负载环境,
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- [ ] CNAME 自定义域名
|
- [ ] CNAME 自定义域名
|
||||||
|
|||||||
@@ -6,6 +6,14 @@ import (
|
|||||||
|
|
||||||
type ServerOptions struct {
|
type ServerOptions struct {
|
||||||
Domain string
|
Domain string
|
||||||
|
Cache services.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultOptions(domain string) *ServerOptions {
|
||||||
|
return &ServerOptions{
|
||||||
|
Domain: domain,
|
||||||
|
Cache: services.NewConfigMemory(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
|
|||||||
@@ -1,7 +1,97 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
type Cache interface {
|
type Cache interface {
|
||||||
Put(key string, value []byte) error
|
Put(key string, reader io.Reader) error
|
||||||
Get(key string) ([]byte, error)
|
Get(key string) (io.ReadSeekCloser, error)
|
||||||
Delete(key string) 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")
|
||||||
}
|
}
|
||||||
|
|||||||
58
pkg/services/config.go
Normal file
58
pkg/services/config.go
Normal file
@@ -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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user