diff --git a/CHANGELOG.md b/CHANGELOG.md index bdf8ca7..11ff8c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Unnecessarily encoded characters in URLs will be decoded (#138) - URLs are NFC-normalized before any processing (#138) - Links to the wiki in the new tab +- Cache times out after 30 minutes by default (#110) ### Changed - Updated [go-gemini](https://github.com/makeworld-the-better-one/go-gemini) to v0.11.0 diff --git a/cache/page.go b/cache/page.go index 0175e2f..4e80b89 100644 --- a/cache/page.go +++ b/cache/page.go @@ -4,6 +4,7 @@ package cache import ( "sync" + "time" "github.com/makeworld-the-better-one/amfora/structs" ) @@ -13,6 +14,7 @@ var urls = make([]string, 0) // Duplicate of the keys in the `page var maxPages = 0 // Max allowed number of pages in cache var maxSize = 0 // Max allowed cache size in bytes var lock = sync.RWMutex{} +var timeout = time.Duration(0) // SetMaxPages sets the max number of pages the cache can hold. // A value <= 0 means infinite pages. @@ -26,6 +28,16 @@ func SetMaxSize(max int) { maxSize = max } +// SetTimeout sets the max number of a seconds a page can still +// be valid for. A value <= 0 means forever. +func SetTimeout(t int) { + if t <= 0 { + timeout = time.Duration(0) + return + } + timeout = time.Duration(t) * time.Second +} + func removeIndex(s []string, i int) []string { s[len(s)-1], s[i] = s[i], s[len(s)-1] return s[:len(s)-1] @@ -110,10 +122,14 @@ func NumPages() int { } // GetPage returns the page struct, and a bool indicating if the page was in the cache or not. -// An empty page struct is returned if the page isn't in the cache. +// (nil, false) is returned if the page isn't in the cache. func GetPage(url string) (*structs.Page, bool) { lock.RLock() defer lock.RUnlock() + p, ok := pages[url] - return p, ok + if ok && (timeout == 0 || time.Since(p.MadeAt) < timeout) { + return p, ok + } + return nil, false } diff --git a/config/config.go b/config/config.go index 7935799..9184648 100644 --- a/config/config.go +++ b/config/config.go @@ -180,10 +180,10 @@ func Init() error { // Setup main config - viper.SetDefault("a-general.home", "gemini.circumlunar.space") + viper.SetDefault("a-general.home", "gemini://gemini.circumlunar.space") viper.SetDefault("a-general.auto_redirect", false) viper.SetDefault("a-general.http", "default") - viper.SetDefault("a-general.search", "gus.guru/search") + viper.SetDefault("a-general.search", "gemini://gus.guru/search") viper.SetDefault("a-general.color", true) viper.SetDefault("a-general.ansi", true) viper.SetDefault("a-general.bullets", true) @@ -198,6 +198,7 @@ func Init() error { viper.SetDefault("url-handlers.other", "off") viper.SetDefault("cache.max_size", 0) viper.SetDefault("cache.max_pages", 20) + viper.SetDefault("cache.timeout", 1800) viper.SetDefault("subscriptions.popup", true) viper.SetDefault("subscriptions.update_interval", 1800) viper.SetDefault("subscriptions.workers", 3) @@ -249,6 +250,7 @@ func Init() error { // Setup cache from config cache.SetMaxSize(viper.GetInt("cache.max_size")) cache.SetMaxPages(viper.GetInt("cache.max_pages")) + cache.SetTimeout(viper.GetInt("cache.timeout")) // Setup theme configTheme := viper.Sub("theme") diff --git a/config/default.go b/config/default.go index b217428..162565d 100644 --- a/config/default.go +++ b/config/default.go @@ -116,13 +116,15 @@ other = 'off' [cache] -# Options for page cache - which is only for text/gemini pages +# Options for page cache - which is only for text pages # Increase the cache size to speed up browsing at the expense of memory - # Zero values mean there is no limit + max_size = 0 # Size in bytes max_pages = 30 # The maximum number of pages the cache will store +# How long a page will stay in cache, in seconds. +timeout = 1800 # 30 mins [proxies] # Allows setting a Gemini proxy for different schemes. diff --git a/default-config.toml b/default-config.toml index 5dca13a..c815c37 100644 --- a/default-config.toml +++ b/default-config.toml @@ -113,13 +113,15 @@ other = 'off' [cache] -# Options for page cache - which is only for text/gemini pages +# Options for page cache - which is only for text pages # Increase the cache size to speed up browsing at the expense of memory - # Zero values mean there is no limit + max_size = 0 # Size in bytes max_pages = 30 # The maximum number of pages the cache will store +# How long a page will stay in cache, in seconds. +timeout = 1800 # 30 mins [proxies] # Allows setting a Gemini proxy for different schemes. diff --git a/renderer/page.go b/renderer/page.go index ad42d17..b5a81ce 100644 --- a/renderer/page.go +++ b/renderer/page.go @@ -7,6 +7,7 @@ import ( "mime" "os" "strings" + "time" "github.com/makeworld-the-better-one/amfora/structs" "github.com/makeworld-the-better-one/go-gemini" @@ -108,6 +109,7 @@ func MakePage(url string, res *gemini.Response, width, leftMargin int, proxied b Raw: utfText, Content: rendered, Links: links, + MadeAt: time.Now(), }, nil } else if strings.HasPrefix(mediatype, "text/") { if mediatype == "text/x-ansi" || strings.HasSuffix(url, ".ans") || strings.HasSuffix(url, ".ansi") { @@ -119,6 +121,7 @@ func MakePage(url string, res *gemini.Response, width, leftMargin int, proxied b Raw: utfText, Content: RenderANSI(utfText, leftMargin), Links: []string{}, + MadeAt: time.Now(), }, nil } @@ -130,6 +133,7 @@ func MakePage(url string, res *gemini.Response, width, leftMargin int, proxied b Raw: utfText, Content: RenderPlainText(utfText, leftMargin), Links: []string{}, + MadeAt: time.Now(), }, nil } diff --git a/structs/structs.go b/structs/structs.go index ce78fe0..8770cc0 100644 --- a/structs/structs.go +++ b/structs/structs.go @@ -1,5 +1,7 @@ package structs +import "time" + type Mediatype string const ( @@ -31,6 +33,7 @@ type Page struct { SelectedID string // The cview region ID for the selected text/link Mode PageMode Favicon string + MadeAt time.Time // When the page was made. Zero value indicates it should stay in cache forever. } // Size returns an approx. size of a Page in bytes.