diff --git a/pkg/querier/queryrange/limits.go b/pkg/querier/queryrange/limits.go index 3ce777f10e11..1d697f9a5491 100644 --- a/pkg/querier/queryrange/limits.go +++ b/pkg/querier/queryrange/limits.go @@ -51,6 +51,9 @@ type cacheKeyLimits struct { // GenerateCacheKey will panic if it encounters a 0 split duration. We ensure against this by requiring // a nonzero split interval when caching is enabled func (l cacheKeyLimits) GenerateCacheKey(userID string, r queryrange.Request) string { - currentInterval := r.GetStart() / int64(l.QuerySplitDuration(userID)/time.Millisecond) - return fmt.Sprintf("%s:%s:%d:%d", userID, r.GetQuery(), r.GetStep(), currentInterval) + split := l.QuerySplitDuration(userID) + currentInterval := r.GetStart() / int64(split/time.Millisecond) + // include both the currentInterval and the split duration in key to ensure + // a cache key can't be reused when an interval changes + return fmt.Sprintf("%s:%s:%d:%d:%d", userID, r.GetQuery(), r.GetStep(), currentInterval, split) } diff --git a/pkg/querier/queryrange/limits_test.go b/pkg/querier/queryrange/limits_test.go index b58f8aaff85f..8e5fc0404339 100644 --- a/pkg/querier/queryrange/limits_test.go +++ b/pkg/querier/queryrange/limits_test.go @@ -1,6 +1,7 @@ package queryrange import ( + "fmt" "testing" "time" @@ -8,7 +9,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestWithDefaultLimits(t *testing.T) { +func TestLimits(t *testing.T) { l := fakeLimits{ splits: map[string]time.Duration{"a": time.Minute}, } @@ -31,4 +32,15 @@ func TestWithDefaultLimits(t *testing.T) { require.Equal(t, wrapped.QuerySplitDuration("a"), time.Minute) require.Equal(t, wrapped.QuerySplitDuration("b"), time.Hour) + r := &LokiRequest{ + Query: "qry", + StartTs: time.Now(), + Step: int64(time.Minute / time.Millisecond), + } + + require.Equal( + t, + fmt.Sprintf("%s:%s:%d:%d:%d", "a", r.GetQuery(), r.GetStep(), r.GetStart()/int64(time.Minute/time.Millisecond), int64(time.Minute)), + cacheKeyLimits{wrapped}.GenerateCacheKey("a", r), + ) }