1
0

Key-Value Storages (#674)

Fix lint

Add docs for keyvalue config options

Use keyvalue store to cache unsplash photo results

Cleanup

Use keyvalue store for upload avatar

Use keyvalue store for initials avatar

Fix initializing metrics

Use keyvalue for metrics

Add IncryBy and DecrBy methods to increase or decrease a value

Fix lint

Return custom error if a key does not exist

Init keyvalue storage

Follow the keyvalue storage setting for things like cache and other

Add docs

Add configuration of the storage backend

Add redis keyvalue storage implementation

Add doc comments

Add methods to use storage through the package itself

Add memory implementation for keyvalue store

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/674
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
This commit is contained in:
konrad
2020-10-10 16:53:59 +00:00
parent bf5d8af3f6
commit d56a611be7
16 changed files with 469 additions and 122 deletions

View File

@ -23,6 +23,8 @@ import (
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/models"
"code.vikunja.io/api/pkg/modules/background"
"code.vikunja.io/api/pkg/modules/keyvalue"
e "code.vikunja.io/api/pkg/modules/keyvalue/error"
"code.vikunja.io/web"
"encoding/json"
"net/http"
@ -32,7 +34,10 @@ import (
"time"
)
const unsplashAPIURL = `https://api.unsplash.com/`
const (
unsplashAPIURL = `https://api.unsplash.com/`
cachePrefix = `unsplash_photo_`
)
// Provider represents an unsplash image provider
type Provider struct {
@ -72,10 +77,6 @@ type Photo struct {
} `json:"links"`
}
// Very simple caching method - pretty much only used to retain information when saving an image
// FIXME: Should use a proper cache
var photos map[string]*Photo
// We're caching the initial collection to save a few api requests as this is retrieved every time a
// user opens the settings page.
type initialCollection struct {
@ -87,10 +88,6 @@ type initialCollection struct {
var emptySearchResult *initialCollection
func init() {
photos = make(map[string]*Photo)
}
func doGet(url string, result ...interface{}) (err error) {
req, err := http.NewRequest("GET", unsplashAPIURL+url, nil)
if err != nil {
@ -120,15 +117,21 @@ func getImageID(fullURL string) string {
// Gets an unsplash photo either from cache or directly from the unsplash api
func getUnsplashPhotoInfoByID(photoID string) (photo *Photo, err error) {
var exists bool
photo, exists = photos[photoID]
if !exists {
p, err := keyvalue.Get(cachePrefix + photoID)
if err != nil && !e.IsErrValueNotFoundForKey(err) {
return nil, err
}
if err != nil && e.IsErrValueNotFoundForKey(err) {
log.Debugf("Image information for unsplash photo %s not cached, requesting from unsplash...", photoID)
photo = &Photo{}
err = doGet("photos/"+photoID, photo)
if err != nil {
return
}
} else {
photo = p.(*Photo)
}
return
}
@ -180,7 +183,9 @@ func (p *Provider) Search(search string, page int64) (result []*background.Image
AuthorName: p.User.Name,
},
})
photos[p.ID] = p
if err := keyvalue.Put(cachePrefix+p.ID, p); err != nil {
return nil, err
}
}
// Put the collection in cache
@ -213,7 +218,9 @@ func (p *Provider) Search(search string, page int64) (result []*background.Image
AuthorName: p.User.Name,
},
})
photos[p.ID] = p
if err := keyvalue.Put(cachePrefix+p.ID, p); err != nil {
return nil, err
}
}
return