From 913f72d4623d4db8902e0f6ec1a527be8dff2668 Mon Sep 17 00:00:00 2001 From: perennial Date: Wed, 16 Oct 2024 01:31:16 +1100 Subject: [PATCH] implement caching configuration --- .env.example | 4 ++++ config/config.go | 11 +++++++++++ core/requests.go | 20 ++++++++++---------- doc/hosting/environment-variables.md | 27 +++++++++++++++++++++++++++ i18n/locale/en/code.json | 1 + main.go | 5 +++++ 6 files changed, 58 insertions(+), 10 deletions(-) diff --git a/.env.example b/.env.example index 9a2cd89..8f15510 100644 --- a/.env.example +++ b/.env.example @@ -31,6 +31,10 @@ PIXIVFE_HOST='127.0.0.1' # PIXIVFE_TOKEN_BASE_TIMEOUT= # PIXIVFE_TOKEN_MAX_BACKOFF_TIME= +### Caching configuration +# PIXIVFE_CACHE_SIZE= +# PIXIVFE_CACHE_TTL= + ### Development options # PIXIVFE_DEV= # PIXIVFE_RESPONSE_SAVE_LOCATION diff --git a/config/config.go b/config/config.go index e13518b..3f491b8 100644 --- a/config/config.go +++ b/config/config.go @@ -67,6 +67,10 @@ type ServerConfig struct { ProxyCheckInterval time.Duration `env:"PIXIVFE_PROXY_CHECK_INTERVAL,overwrite"` ProxyCheckTimeout time.Duration `env:"PIXIVFE_PROXY_CHECK_TIMEOUT,overwrite"` + // Caching configuration + CacheSize int `env:"PIXIVFE_CACHE_SIZE,overwrite"` + CacheTTL time.Duration `env:"PIXIVFE_CACHE_TTL,overwrite"` + // Development options InDevelopment bool `env:"PIXIVFE_DEV"` ResponseSaveLocation string `env:"PIXIVFE_RESPONSE_SAVE_LOCATION,overwrite"` @@ -133,6 +137,9 @@ func (s *ServerConfig) LoadConfig() error { s.APIBaseTimeout = 500 * time.Millisecond s.APIMaxBackoffTime = 8000 * time.Millisecond + s.CacheSize = 1000 + s.CacheTTL = 5 * time.Minute + s.ResponseSaveLocation = "/tmp/pixivfe/responses" s.LogLevel = "info" @@ -207,6 +214,10 @@ func (s *ServerConfig) LoadConfig() error { log.Printf("API request backoff settings: Max retries: %d, Base timeout: %v, Max backoff time: %v\n", s.APIMaxRetries, s.APIBaseTimeout, s.APIMaxBackoffTime) + // Print cache configuration + log.Printf("API response cache size set to: %d items\n", s.CacheSize) + log.Printf("API response cache TTL set to: %v\n", s.CacheTTL) + // Only print ResponseSaveLocation if InDevelopment is set if s.InDevelopment { log.Printf("Response save location: %s\n", s.ResponseSaveLocation) diff --git a/core/requests.go b/core/requests.go index e72c48b..6822c8b 100644 --- a/core/requests.go +++ b/core/requests.go @@ -39,9 +39,17 @@ type CachedItem struct { var ( cache *lru.Cache cacheLock sync.RWMutex - cacheTTL time.Duration ) +// initCache initializes the API response cache with the configured size +func InitCache() { + var err error + cache, err = lru.New(config.GlobalConfig.CacheSize) + if err != nil { + panic(i18n.Sprintf("Failed to create cache: %v", err)) + } +} + func init() { retryClient = retryablehttp.NewClient() retryClient.RetryMax = config.GlobalConfig.APIMaxRetries @@ -49,14 +57,6 @@ func init() { retryClient.RetryWaitMax = config.GlobalConfig.APIMaxBackoffTime retryClient.HTTPClient = utils.HttpClient retryClient.Logger = nil // Disables the default logger in go-retryablehttp - - // Initialize cache - var err error - cache, err = lru.New(1000) // Cache size of 1000 items - if err != nil { - panic(fmt.Sprintf("Failed to create cache: %v", err)) - } - cacheTTL = 5 * time.Minute // Default TTL of 5 minutes } // Helper function to handle common request logic @@ -165,7 +165,7 @@ Please refer the following documentation for additional information: cacheLock.Lock() cache.Add(cacheKey, CachedItem{ Response: resp, - ExpiresAt: time.Now().Add(cacheTTL), + ExpiresAt: time.Now().Add(config.GlobalConfig.CacheTTL), }) cacheLock.Unlock() return resp, nil diff --git a/doc/hosting/environment-variables.md b/doc/hosting/environment-variables.md index 8a472a2..9e50da7 100644 --- a/doc/hosting/environment-variables.md +++ b/doc/hosting/environment-variables.md @@ -197,6 +197,33 @@ Base timeout duration for token management. Maximum backoff time for token management. +## Caching configuration + +PixivFE caches responses from the Pixiv API to improve performance. The following environment variables can be used to configure the caching behavior. + +### `PIXIVFE_CACHE_SIZE` + +**Required**: No + +**Default:** `1000` + +Specifies the maximum number of items that can be stored in the cache. This limits the memory usage of the cache. + +### `PIXIVFE_CACHE_TTL` + +**Required**: No + +**Default:** `5m` + +Specifies the Time To Live (TTL) for cached items. This is the duration for which an item remains valid in the cache before it's considered stale and needs to be fetched again. + +The value should be specified in Go's [`time.Duration`](https://pkg.go.dev/time#ParseDuration) notation. + +!!! note + While caching improves performance, it also means that changes on Pixiv might not be immediately reflected in PixivFE. + + If you want content updates that are closer to real-time, consider reducing the cache TTL. + ## Network proxy configuration Used to set the [proxy server](https://en.wikipedia.org/wiki/Proxy_server) that PixivFE will use for all requests. Not to be confused with the image proxy, which is used to comply with the `Referer` check required by `i.pximg.net`. diff --git a/i18n/locale/en/code.json b/i18n/locale/en/code.json index 37a05a3..981a910 100644 --- a/i18n/locale/en/code.json +++ b/i18n/locale/en/code.json @@ -19,6 +19,7 @@ "core/requests.go:0hOvqlK-HwY": "HTTP status code: %d", "core/requests.go:7heLIvyBB2M": "Invalid JSON: %v", "core/requests.go:7pvvVOIzWew": "Max retries reached for GET request. Last error: %v", + "core/requests.go:Kt44RnMSg6M": "Failed to create cache: %v", "core/requests.go:Odhyy2SoIGU": "failed to make request: %w", "core/requests.go:XGjPq4l3s2o": "userToken is required for POST requests", "core/requests.go:XdMN7Q7DY3k": "failed to proxy request: %w", diff --git a/main.go b/main.go index 8ce5824..1420a3c 100644 --- a/main.go +++ b/main.go @@ -15,6 +15,7 @@ import ( "time" "codeberg.org/vnpower/pixivfe/v2/config" + "codeberg.org/vnpower/pixivfe/v2/core" "codeberg.org/vnpower/pixivfe/v2/i18n" "codeberg.org/vnpower/pixivfe/v2/server/audit" "codeberg.org/vnpower/pixivfe/v2/server/middleware" @@ -64,6 +65,10 @@ func main() { log.Println("Skipping proxy checker initialization.") } + // Initialize cache + core.InitCache() + log.Println("API response cache initialized.") + log.Println("Starting server...") router := middleware.DefineRoutes()