Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion galaxycache.go
Original file line number Diff line number Diff line change
Expand Up @@ -1104,10 +1104,10 @@ func (g *Galaxy) getFromPeer(ctx context.Context, peer RemoteFetcherWithInfo, ke
HCStats: g.hcStatsWithTime.hcs,
}
value := g.newValWithStat(data, kStats)
g.opts.getTTL.capExpiry(g.clock, &bgInfo)
if g.opts.promoter.ShouldPromote(key, value.data, stats) {
g.populateCache(ctx, key, value, &g.hotCache, bgInfo)
}
g.opts.getTTL.capExpiry(g.clock, &bgInfo)
return value, bgInfo, nil
}

Expand Down
44 changes: 31 additions & 13 deletions galaxycache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -732,18 +732,20 @@ func (t *trackingNeverPromoter) ShouldPromote(key string, data []byte, stats pro
func TestPromotion(t *testing.T) {
outerCtx := context.Background()
const testKey = "to-get"
fc := fake.NewClock(time.Now())
testCases := []struct {
testName string
promoter promoter.Interface
cacheSize int64
firstCheck func(ctx context.Context, t testing.TB, key string, val valWithStat, okCand bool, okHot bool, tf *TestFetcher, g *Galaxy)
secondCheck func(ctx context.Context, t testing.TB, key string, val valWithStat, okCand bool, okHot bool, tf *TestFetcher, g *Galaxy)
expiryCap time.Duration
firstCheck func(ctx context.Context, t testing.TB, key string, val valWithStat, okCand bool, okHot bool, exp time.Time, tf *TestFetcher, g *Galaxy)
secondCheck func(ctx context.Context, t testing.TB, key string, val valWithStat, okCand bool, okHot bool, exp time.Time, tf *TestFetcher, g *Galaxy)
}{
{
testName: "never_promote",
promoter: promoter.Func(func(key string, data []byte, stats promoter.Stats) bool { return false }),
cacheSize: 1 << 20,
firstCheck: func(_ context.Context, t testing.TB, _ string, _ valWithStat, okCand bool, okHot bool, _ *TestFetcher, _ *Galaxy) {
firstCheck: func(_ context.Context, t testing.TB, _ string, _ valWithStat, okCand bool, okHot bool, _ time.Time, _ *TestFetcher, _ *Galaxy) {
if !okCand {
t.Error("Candidate not found in candidate cache")
}
Expand All @@ -756,19 +758,35 @@ func TestPromotion(t *testing.T) {
testName: "always_promote",
promoter: promoter.Func(func(key string, data []byte, stats promoter.Stats) bool { return true }),
cacheSize: 1 << 20,
firstCheck: func(_ context.Context, t testing.TB, _ string, val valWithStat, _ bool, okHot bool, _ *TestFetcher, _ *Galaxy) {
firstCheck: func(_ context.Context, t testing.TB, _ string, val valWithStat, _ bool, okHot bool, _ time.Time, _ *TestFetcher, _ *Galaxy) {
if !okHot {
t.Error("Key not found in hotcache")
} else if val.data == nil {
t.Error("Found element in hotcache, but no associated data")
}
},
},
{
testName: "always_promote_with_capped_expiry",
promoter: promoter.Func(func(key string, data []byte, stats promoter.Stats) bool { return true }),
cacheSize: 1 << 20,
expiryCap: time.Hour,
firstCheck: func(_ context.Context, t testing.TB, _ string, val valWithStat, _ bool, okHot bool, exp time.Time, _ *TestFetcher, _ *Galaxy) {
if !okHot {
t.Error("Key not found in hotcache")
} else if val.data == nil {
t.Error("Found element in hotcache, but no associated data")
} else if !exp.Equal(fc.Now().Add(time.Hour)) {
t.Errorf("hotcache entry was added with an unexpected expiration timestamp: %s; expected %s",
exp, fc.Now().Add(time.Hour))
}
},
},
{
testName: "candidate_promotion",
promoter: &promoteFromCandidate{},
cacheSize: 1 << 20,
firstCheck: func(ctx context.Context, t testing.TB, key string, _ valWithStat, okCand bool, okHot bool, tf *TestFetcher, g *Galaxy) {
firstCheck: func(ctx context.Context, t testing.TB, key string, _ valWithStat, okCand bool, okHot bool, _ time.Time, tf *TestFetcher, g *Galaxy) {
if !okCand {
t.Error("Candidate not found in candidate cache")
}
Expand All @@ -789,7 +807,7 @@ func TestPromotion(t *testing.T) {
testName: "never_promote_but_track",
promoter: &trackingNeverPromoter{},
cacheSize: 1 << 20,
firstCheck: func(_ context.Context, t testing.TB, _ string, _ valWithStat, okCand bool, okHot bool, _ *TestFetcher, g *Galaxy) {
firstCheck: func(_ context.Context, t testing.TB, _ string, _ valWithStat, okCand bool, okHot bool, _ time.Time, _ *TestFetcher, g *Galaxy) {
if okHot {
t.Errorf("value unexpectedly in hot-cache")
}
Expand All @@ -811,7 +829,7 @@ func TestPromotion(t *testing.T) {
t.Errorf("first hit had non-zero QPS: %f", pro.stats[0].KeyQPS)
}
},
secondCheck: func(_ context.Context, t testing.TB, _ string, _ valWithStat, okCand bool, okHot bool, _ *TestFetcher, g *Galaxy) {
secondCheck: func(_ context.Context, t testing.TB, _ string, _ valWithStat, okCand bool, okHot bool, _ time.Time, _ *TestFetcher, g *Galaxy) {
if okHot {
t.Errorf("value unexpectedly in hot-cache")
}
Expand Down Expand Up @@ -848,24 +866,24 @@ func TestPromotion(t *testing.T) {
getter := func(_ context.Context, key string, dest Codec) error {
return dest.UnmarshalBinary([]byte("got:" + key))
}
universe := NewUniverse(testProto, "promotion-test")
universe := NewUniverse(testProto, "promotion-test", WithUniversalClock(fc))
universe.Set("foobar")
galaxy := universe.NewGalaxy("test-galaxy", tc.cacheSize, GetterFunc(getter), WithPromoter(tc.promoter))
galaxy := universe.NewGalaxy("test-galaxy", tc.cacheSize, GetterFunc(getter), WithPromoter(tc.promoter), WithGetTTL(tc.expiryCap, 0))
sc := StringCodec("")
{
galaxy.Get(ctx, testKey, &sc)
_, okCandidate := galaxy.candidateCache.get(testKey)
value, _, okHot := galaxy.hotCache.get(testKey)
tc.firstCheck(ctx, t, testKey, value, okCandidate, okHot, fetcher, galaxy)
value, exp, okHot := galaxy.hotCache.get(testKey)
tc.firstCheck(ctx, t, testKey, value, okCandidate, okHot, exp, fetcher, galaxy)
}
if tc.secondCheck == nil {
return
}
{
galaxy.Get(ctx, testKey, &sc)
_, okCandidate := galaxy.candidateCache.get(testKey)
value, _, okHot := galaxy.hotCache.get(testKey)
tc.secondCheck(ctx, t, testKey, value, okCandidate, okHot, fetcher, galaxy)
value, exp, okHot := galaxy.hotCache.get(testKey)
tc.secondCheck(ctx, t, testKey, value, okCandidate, okHot, exp, fetcher, galaxy)
}

})
Expand Down