dnfjson: Add a cache of dnf-json results
This adds a cache structure with timeout handling and cache cleanup. Also adds some testing of the new functions.
This commit is contained in:
parent
f4aed3e6e2
commit
35059ca60e
2 changed files with 109 additions and 0 deletions
|
|
@ -9,6 +9,8 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
)
|
||||
|
||||
|
|
@ -207,3 +209,60 @@ func dirSize(path string) (uint64, error) {
|
|||
err := filepath.Walk(path, sizer)
|
||||
return size, err
|
||||
}
|
||||
|
||||
// dnfResults holds the results of a dnfjson request
|
||||
// expire is the time the request was made, used to expire the entry
|
||||
type dnfResults struct {
|
||||
expire time.Time
|
||||
pkgs rpmmd.PackageList
|
||||
}
|
||||
|
||||
// dnfCache is a cache of results from dnf-json requests
|
||||
type dnfCache struct {
|
||||
results map[string]dnfResults
|
||||
timeout time.Duration
|
||||
*sync.RWMutex
|
||||
}
|
||||
|
||||
// NewDNFCache returns a pointer to an initialized dnfCache struct
|
||||
func NewDNFCache(timeout time.Duration) *dnfCache {
|
||||
return &dnfCache{
|
||||
results: make(map[string]dnfResults),
|
||||
timeout: timeout,
|
||||
RWMutex: new(sync.RWMutex),
|
||||
}
|
||||
}
|
||||
|
||||
// CleanCache deletes unused cache entries
|
||||
// This prevents the cache from growing for longer than the timeout interval
|
||||
func (d *dnfCache) CleanCache() {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
// Delete expired resultCache entries
|
||||
for k := range d.results {
|
||||
if time.Since(d.results[k].expire) > d.timeout {
|
||||
delete(d.results, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the package list and true if cached
|
||||
// or an empty list and false if not cached or if cache is timed out
|
||||
func (d *dnfCache) Get(hash string) (rpmmd.PackageList, bool) {
|
||||
d.RLock()
|
||||
defer d.RUnlock()
|
||||
|
||||
result, ok := d.results[hash]
|
||||
if !ok || time.Since(result.expire) >= d.timeout {
|
||||
return rpmmd.PackageList{}, false
|
||||
}
|
||||
return result.pkgs, true
|
||||
}
|
||||
|
||||
// Store saves the package list in the cache
|
||||
func (d *dnfCache) Store(hash string, pkgs rpmmd.PackageList) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
d.results[hash] = dnfResults{expire: time.Now(), pkgs: pkgs}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -273,3 +275,51 @@ func TestCacheCleanup(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Mock package list to use in testing
|
||||
var PackageList = rpmmd.PackageList{
|
||||
rpmmd.Package{
|
||||
Name: "package0",
|
||||
Summary: "package summary",
|
||||
Description: "package description",
|
||||
URL: "https://package-url/",
|
||||
Epoch: 0,
|
||||
Version: "1.0.0",
|
||||
Release: "3",
|
||||
Arch: "x86_64",
|
||||
License: "MIT",
|
||||
},
|
||||
}
|
||||
|
||||
func TestDNFCacheStoreGet(t *testing.T) {
|
||||
cache := NewDNFCache(1 * time.Second)
|
||||
assert.Equal(t, cache.timeout, 1*time.Second)
|
||||
assert.NotNil(t, cache.RWMutex)
|
||||
|
||||
cache.Store("notreallyahash", PackageList)
|
||||
assert.Equal(t, 1, len(cache.results))
|
||||
pkgs, ok := cache.Get("notreallyahash")
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "package0", pkgs[0].Name)
|
||||
}
|
||||
|
||||
func TestDNFCacheTimeout(t *testing.T) {
|
||||
cache := NewDNFCache(1 * time.Second)
|
||||
cache.Store("notreallyahash", PackageList)
|
||||
_, ok := cache.Get("notreallyahash")
|
||||
assert.True(t, ok)
|
||||
time.Sleep(2 * time.Second)
|
||||
_, ok = cache.Get("notreallyahash")
|
||||
assert.False(t, ok)
|
||||
}
|
||||
|
||||
func TestDNFCacheCleanup(t *testing.T) {
|
||||
cache := NewDNFCache(1 * time.Second)
|
||||
cache.Store("notreallyahash", PackageList)
|
||||
time.Sleep(2 * time.Second)
|
||||
assert.Equal(t, 1, len(cache.results))
|
||||
cache.CleanCache()
|
||||
assert.Equal(t, 0, len(cache.results))
|
||||
_, ok := cache.Get("notreallyahash")
|
||||
assert.False(t, ok)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue