add: cache for remote images (#310)

* add: cache for remote image requests

* update: use default expiration for NoExpiration setting

* update: clean code

* fix: do not save empty etag

* fix: panic during type assertion
This commit is contained in:
HolgerHuo 2024-02-10 18:55:23 -08:00 committed by GitHub
parent 12d4cc1a0b
commit 123c96dde7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 44 additions and 4 deletions

View File

@ -10,5 +10,6 @@
"ENABLE_EXTRA_PARAMS": false, "ENABLE_EXTRA_PARAMS": false,
"READ_BUFFER_SIZE": 4096, "READ_BUFFER_SIZE": 4096,
"CONCURRENCY": 262144, "CONCURRENCY": 262144,
"DISABLE_KEEPALIVE": false "DISABLE_KEEPALIVE": false,
"CACHE_TTL": 259200
} }

View File

@ -33,7 +33,8 @@ const (
"ENABLE_EXTRA_PARAMS": false "ENABLE_EXTRA_PARAMS": false
"READ_BUFFER_SIZE": 4096, "READ_BUFFER_SIZE": 4096,
"CONCURRENCY": 262144, "CONCURRENCY": 262144,
"DISABLE_KEEPALIVE": false "DISABLE_KEEPALIVE": false,
"CACHE_TTL": 259200,
}` }`
) )
@ -52,6 +53,7 @@ var (
RemoteRaw = "./remote-raw" RemoteRaw = "./remote-raw"
Metadata = "./metadata" Metadata = "./metadata"
LocalHostAlias = "local" LocalHostAlias = "local"
RemoteCache *cache.Cache
) )
type MetaFile struct { type MetaFile struct {
@ -73,6 +75,7 @@ type WebpConfig struct {
ReadBufferSize int `json:"READ_BUFFER_SIZE"` ReadBufferSize int `json:"READ_BUFFER_SIZE"`
Concurrency int `json:"CONCURRENCY"` Concurrency int `json:"CONCURRENCY"`
DisableKeepalive bool `json:"DISABLE_KEEPALIVE"` DisableKeepalive bool `json:"DISABLE_KEEPALIVE"`
CacheTTL int `json:"CACHE_TTL"`
} }
func NewWebPConfig() *WebpConfig { func NewWebPConfig() *WebpConfig {
@ -89,6 +92,7 @@ func NewWebPConfig() *WebpConfig {
ReadBufferSize: 4096, ReadBufferSize: 4096,
Concurrency: 262144, Concurrency: 262144,
DisableKeepalive: false, DisableKeepalive: false,
CacheTTL: 259200,
} }
} }
@ -184,6 +188,20 @@ func LoadConfig() {
log.Warnf("WEBP_DISABLE_KEEPALIVE is not a valid boolean, using value in config.json %t", Config.DisableKeepalive) log.Warnf("WEBP_DISABLE_KEEPALIVE is not a valid boolean, using value in config.json %t", Config.DisableKeepalive)
} }
} }
if os.Getenv("CACHE_TTL") != "" {
cacheTTL, err := strconv.Atoi(os.Getenv("CACHE_TTL"))
if err != nil {
log.Warnf("CACHE_TTL is not a valid integer, using value in config.json %d", Config.CacheTTL)
} else {
Config.CacheTTL = cacheTTL
}
}
if Config.CacheTTL == 0 {
RemoteCache = cache.New(cache.NoExpiration, 10*time.Minute)
} else {
RemoteCache = cache.New(time.Duration(Config.CacheTTL)*time.Minute, 10*time.Minute)
}
log.Debugln("Config init complete") log.Debugln("Config init complete")
log.Debugln("Config", Config) log.Debugln("Config", Config)

View File

@ -21,6 +21,7 @@ func TestLoadConfig(t *testing.T) {
assert.Equal(t, Config.ImgPath, "./pics") assert.Equal(t, Config.ImgPath, "./pics")
assert.Equal(t, Config.ImageMap, map[string]string{}) assert.Equal(t, Config.ImageMap, map[string]string{})
assert.Equal(t, Config.ExhaustPath, "./exhaust") assert.Equal(t, Config.ExhaustPath, "./exhaust")
assert.Equal(t, Config.CacheTTL, 259200)
} }
func TestSwitchProxyMode(t *testing.T) { func TestSwitchProxyMode(t *testing.T) {

View File

@ -12,6 +12,7 @@ import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/h2non/filetype" "github.com/h2non/filetype"
"github.com/patrickmn/go-cache"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -78,8 +79,27 @@ func downloadFile(filepath string, url string) {
func fetchRemoteImg(url string, subdir string) config.MetaFile { func fetchRemoteImg(url string, subdir string) config.MetaFile {
// url is https://test.webp.sh/mypic/123.jpg?someother=200&somebugs=200 // url is https://test.webp.sh/mypic/123.jpg?someother=200&somebugs=200
// How do we know if the remote img is changed? we're using hash(etag+length) // How do we know if the remote img is changed? we're using hash(etag+length)
log.Infof("Remote Addr is %s, pinging for info...", url) var etag string
etag := pingURL(url)
cacheKey := subdir+":"+helper.HashString(url)
if val, found := config.RemoteCache.Get(cacheKey); found {
if etagVal, ok := val.(string); ok {
log.Infof("Using cache for remote addr: %s", url)
etag = etagVal
} else {
config.RemoteCache.Delete(cacheKey)
}
}
if etag == "" {
log.Infof("Remote Addr is %s, pinging for info...", url)
etag = pingURL(url)
if etag != "" {
config.RemoteCache.Set(cacheKey, etag, cache.DefaultExpiration)
}
}
metadata := helper.ReadMetadata(url, etag, subdir) metadata := helper.ReadMetadata(url, etag, subdir)
localRawImagePath := path.Join(config.RemoteRaw, subdir, metadata.Id) localRawImagePath := path.Join(config.RemoteRaw, subdir, metadata.Id)