[BUG] Store JSON in contributors commit cache

- The code that gets contributor stats tried to store an
`map[string]*ContributorData` type in the cache, this works for the
memory cache but not for other caches such as Redis.
- The cache implementation for Redis would convert this map via
`fmt.Sprintf` to an string, which would simply print the pointer and not
the value of the pointer. Storing pointers is a no-go as this will get
GC-ed eventually within a few minutes. Therefore store everything with
json, that does properly store the value of the pointers.
- Adds unit test that verifies JSON is being used.
- Resolves https://codeberg.org/forgejo/forgejo/issues/3158
This commit is contained in:
Gusted 2024-04-11 12:50:04 +02:00
parent 656554e247
commit 4c8b67c4b2
No known key found for this signature in database
GPG key ID: FD821B732837125F
2 changed files with 22 additions and 4 deletions

View file

@ -20,6 +20,7 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
@ -108,8 +109,9 @@ func GetContributorStats(ctx context.Context, cache cache.Cache, repo *repo_mode
switch v := cache.Get(cacheKey).(type) {
case error:
return nil, v
case map[string]*ContributorData:
return v, nil
case string:
var cachedStats map[string]*ContributorData
return cachedStats, json.Unmarshal([]byte(v), &cachedStats)
default:
return nil, fmt.Errorf("unexpected type in cache detected")
}
@ -309,7 +311,16 @@ func generateContributorStats(genDone chan struct{}, cache cache.Cache, cacheKey
total.TotalCommits++
}
_ = cache.Put(cacheKey, contributorsCommitStats, contributorStatsCacheTimeout)
data, err := json.Marshal(contributorsCommitStats)
if err != nil {
err := fmt.Errorf("couldn't marshal the data: %w", err)
_ = cache.Put(cacheKey, err, contributorStatsCacheTimeout)
return
}
// Store the data as an string, to make it uniform what data type is returned
// from caches.
_ = cache.Put(cacheKey, string(data), contributorStatsCacheTimeout)
generateLock.Delete(cacheKey)
if genDone != nil {
genDone <- struct{}{}