From 222024dabbaf1aaa8c87f5ff4129fd5d0a972979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Thu, 17 Feb 2022 10:34:33 +0100 Subject: [PATCH] chore: cache avatars in memory --- go.mod | 1 + go.sum | 2 ++ routes/api/avatar.go | 24 +++++++++++++++++------- utils/fs/exists.go | 13 +++++++++---- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index f9c6624..ce255d7 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/gorilla/schema v1.2.0 github.com/gorilla/securecookie v1.1.1 + github.com/hashicorp/golang-lru v0.5.4 github.com/jackc/pgx/v4 v4.14.1 // indirect github.com/jinzhu/configor v1.2.1 github.com/jinzhu/now v1.1.4 // indirect diff --git a/go.sum b/go.sum index 5d316f7..862ccf0 100644 --- a/go.sum +++ b/go.sum @@ -109,6 +109,8 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= diff --git a/routes/api/avatar.go b/routes/api/avatar.go index f5e3818..5faf49b 100644 --- a/routes/api/avatar.go +++ b/routes/api/avatar.go @@ -3,16 +3,26 @@ package api import ( "codeberg.org/Codeberg/avatars" "github.com/gorilla/mux" + lru "github.com/hashicorp/golang-lru" conf "github.com/muety/wakapi/config" "net/http" ) type AvatarHandler struct { config *conf.Config + cache *lru.Cache } func NewAvatarHandler() *AvatarHandler { - return &AvatarHandler{config: conf.Get()} + cache, err := lru.New(1 * 1000 * 64) // assuming an avatar is 1 kb, allocate up to 64 mb of memory for avatars cache + if err != nil { + panic(err) + } + + return &AvatarHandler{ + config: conf.Get(), + cache: cache, + } } func (h *AvatarHandler) RegisterRoutes(router *mux.Router) { @@ -21,15 +31,15 @@ func (h *AvatarHandler) RegisterRoutes(router *mux.Router) { } func (h *AvatarHandler) Get(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) + hash := mux.Vars(r)["hash"] - if vars["hash"] == "" { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte{}) - return + if !h.cache.Contains(hash) { + h.cache.Add(hash, avatars.MakeMaleAvatar(hash)) } + data, _ := h.cache.Get(hash) w.Header().Set("Content-Type", "image/svg+xml") + w.Header().Set("Cache-Control", "max-age=2592000") w.WriteHeader(http.StatusOK) - w.Write([]byte(avatars.MakeMaleAvatar(vars["hash"]))) + w.Write([]byte(data.(string))) } diff --git a/utils/fs/exists.go b/utils/fs/exists.go index 08c256d..a0b0d6d 100644 --- a/utils/fs/exists.go +++ b/utils/fs/exists.go @@ -1,23 +1,28 @@ package fs import ( - "github.com/patrickmn/go-cache" + lru "github.com/hashicorp/golang-lru" "io/fs" "net/http" "strings" ) func NewExistsFS(fs fs.FS) ExistsFS { + cache, err := lru.New(1 << 24) + if err != nil { + panic(err) + } + return ExistsFS{ FS: fs, - cache: cache.New(cache.NoExpiration, cache.NoExpiration), + cache: cache, } } type ExistsFS struct { fs.FS UseCache bool - cache *cache.Cache + cache *lru.Cache } func (efs ExistsFS) WithCache(withCache bool) ExistsFS { @@ -34,7 +39,7 @@ func (efs ExistsFS) Exists(name string) bool { _, err := fs.Stat(efs.FS, name) result := err == nil if efs.UseCache { - efs.cache.SetDefault(name, result) + efs.cache.Add(name, result) } return result }