From 1d49801a27392b518f04b2da05c88696a7920a06 Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Wed, 1 May 2024 18:55:59 -0700 Subject: [PATCH] feat(api): cache thumb and preview in memory for fast retrieval. Help address #3462 --- controllers/images.go | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/controllers/images.go b/controllers/images.go index 6ea3eadf3..86d37d5be 100644 --- a/controllers/images.go +++ b/controllers/images.go @@ -3,7 +3,9 @@ package controllers import ( "net/http" "path/filepath" + "time" + "github.com/jellydator/ttlcache/v3" "github.com/owncast/owncast/config" "github.com/owncast/owncast/utils" ) @@ -13,16 +15,28 @@ const ( contentTypeGIF = "image/gif" ) +var previewThumbCache = ttlcache.New( + ttlcache.WithTTL[string, []byte](15), + ttlcache.WithCapacity[string, []byte](1), + ttlcache.WithDisableTouchOnHit[string, []byte](), +) + // GetThumbnail will return the thumbnail image as a response. func GetThumbnail(w http.ResponseWriter, r *http.Request) { imageFilename := "thumbnail.jpg" imagePath := filepath.Join(config.TempDir, imageFilename) + httpCacheTime := utils.GetCacheDurationSecondsForPath(imagePath) + inMemoryCacheTime := time.Duration(15) * time.Second var imageBytes []byte var err error - if utils.DoesFileExists(imagePath) { + if previewThumbCache.Get(imagePath) != nil { + ci := previewThumbCache.Get(imagePath) + imageBytes = ci.Value() + } else if utils.DoesFileExists(imagePath) { imageBytes, err = getImage(imagePath) + previewThumbCache.Set(imagePath, imageBytes, inMemoryCacheTime) } else { GetLogo(w, r) return @@ -33,20 +47,25 @@ func GetThumbnail(w http.ResponseWriter, r *http.Request) { return } - cacheTime := utils.GetCacheDurationSecondsForPath(imagePath) - writeBytesAsImage(imageBytes, contentTypeJPEG, w, cacheTime) + writeBytesAsImage(imageBytes, contentTypeJPEG, w, httpCacheTime) } // GetPreview will return the preview gif as a response. func GetPreview(w http.ResponseWriter, r *http.Request) { imageFilename := "preview.gif" imagePath := filepath.Join(config.TempDir, imageFilename) + httpCacheTime := utils.GetCacheDurationSecondsForPath(imagePath) + inMemoryCacheTime := time.Duration(15) * time.Second var imageBytes []byte var err error - if utils.DoesFileExists(imagePath) { + if previewThumbCache.Get(imagePath) != nil { + ci := previewThumbCache.Get(imagePath) + imageBytes = ci.Value() + } else if utils.DoesFileExists(imagePath) { imageBytes, err = getImage(imagePath) + previewThumbCache.Set(imagePath, imageBytes, inMemoryCacheTime) } else { GetLogo(w, r) return @@ -57,6 +76,5 @@ func GetPreview(w http.ResponseWriter, r *http.Request) { return } - cacheTime := utils.GetCacheDurationSecondsForPath(imagePath) - writeBytesAsImage(imageBytes, contentTypeGIF, w, cacheTime) + writeBytesAsImage(imageBytes, contentTypeGIF, w, httpCacheTime) }