github.com/sequix/cortex@v1.1.6/pkg/chunk/storage/caching_index_client_test.go (about) 1 package storage 2 3 import ( 4 "context" 5 "testing" 6 "time" 7 8 "github.com/sequix/cortex/pkg/chunk" 9 "github.com/sequix/cortex/pkg/chunk/cache" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 "github.com/weaveworks/common/user" 13 ) 14 15 var ctx = user.InjectOrgID(context.Background(), "1") 16 17 type mockStore struct { 18 chunk.IndexClient 19 queries int 20 results ReadBatch 21 } 22 23 func (m *mockStore) QueryPages(ctx context.Context, queries []chunk.IndexQuery, callback func(chunk.IndexQuery, chunk.ReadBatch) (shouldContinue bool)) error { 24 for _, query := range queries { 25 m.queries++ 26 callback(query, m.results) 27 } 28 return nil 29 } 30 31 func TestCachingStorageClientBasic(t *testing.T) { 32 store := &mockStore{ 33 results: ReadBatch{ 34 Entries: []Entry{{ 35 Column: []byte("foo"), 36 Value: []byte("bar"), 37 }}, 38 }, 39 } 40 limits, err := defaultLimits() 41 require.NoError(t, err) 42 cache := cache.NewFifoCache("test", cache.FifoCacheConfig{Size: 10, Validity: 10 * time.Second}) 43 client := newCachingIndexClient(store, cache, 1*time.Second, limits) 44 queries := []chunk.IndexQuery{{ 45 TableName: "table", 46 HashValue: "baz", 47 }} 48 err = client.QueryPages(ctx, queries, func(_ chunk.IndexQuery, _ chunk.ReadBatch) bool { 49 return true 50 }) 51 require.NoError(t, err) 52 assert.EqualValues(t, 1, store.queries) 53 54 // If we do the query to the cache again, the underlying store shouldn't see it. 55 err = client.QueryPages(ctx, queries, func(_ chunk.IndexQuery, _ chunk.ReadBatch) bool { 56 return true 57 }) 58 require.NoError(t, err) 59 assert.EqualValues(t, 1, store.queries) 60 } 61 62 func TestTempCachingStorageClient(t *testing.T) { 63 store := &mockStore{ 64 results: ReadBatch{ 65 Entries: []Entry{{ 66 Column: []byte("foo"), 67 Value: []byte("bar"), 68 }}, 69 }, 70 } 71 limits, err := defaultLimits() 72 require.NoError(t, err) 73 cache := cache.NewFifoCache("test", cache.FifoCacheConfig{Size: 10, Validity: 10 * time.Second}) 74 client := newCachingIndexClient(store, cache, 100*time.Millisecond, limits) 75 queries := []chunk.IndexQuery{ 76 {TableName: "table", HashValue: "foo"}, 77 {TableName: "table", HashValue: "bar"}, 78 {TableName: "table", HashValue: "baz"}, 79 } 80 results := 0 81 err = client.QueryPages(ctx, queries, func(query chunk.IndexQuery, batch chunk.ReadBatch) bool { 82 iter := batch.Iterator() 83 for iter.Next() { 84 results++ 85 } 86 return true 87 }) 88 require.NoError(t, err) 89 assert.EqualValues(t, len(queries), store.queries) 90 assert.EqualValues(t, len(queries), results) 91 92 // If we do the query to the cache again, the underlying store shouldn't see it. 93 results = 0 94 err = client.QueryPages(ctx, queries, func(query chunk.IndexQuery, batch chunk.ReadBatch) bool { 95 iter := batch.Iterator() 96 for iter.Next() { 97 results++ 98 } 99 return true 100 }) 101 require.NoError(t, err) 102 assert.EqualValues(t, len(queries), store.queries) 103 assert.EqualValues(t, len(queries), results) 104 105 // If we do the query after validity, it should see the queries. 106 time.Sleep(100 * time.Millisecond) 107 results = 0 108 err = client.QueryPages(ctx, queries, func(query chunk.IndexQuery, batch chunk.ReadBatch) bool { 109 iter := batch.Iterator() 110 for iter.Next() { 111 results++ 112 } 113 return true 114 }) 115 require.NoError(t, err) 116 assert.EqualValues(t, 2*len(queries), store.queries) 117 assert.EqualValues(t, len(queries), results) 118 } 119 120 func TestPermCachingStorageClient(t *testing.T) { 121 store := &mockStore{ 122 results: ReadBatch{ 123 Entries: []Entry{{ 124 Column: []byte("foo"), 125 Value: []byte("bar"), 126 }}, 127 }, 128 } 129 limits, err := defaultLimits() 130 require.NoError(t, err) 131 cache := cache.NewFifoCache("test", cache.FifoCacheConfig{Size: 10, Validity: 10 * time.Second}) 132 client := newCachingIndexClient(store, cache, 100*time.Millisecond, limits) 133 queries := []chunk.IndexQuery{ 134 {TableName: "table", HashValue: "foo", Immutable: true}, 135 {TableName: "table", HashValue: "bar", Immutable: true}, 136 {TableName: "table", HashValue: "baz", Immutable: true}, 137 } 138 results := 0 139 err = client.QueryPages(ctx, queries, func(query chunk.IndexQuery, batch chunk.ReadBatch) bool { 140 iter := batch.Iterator() 141 for iter.Next() { 142 results++ 143 } 144 return true 145 }) 146 require.NoError(t, err) 147 assert.EqualValues(t, len(queries), store.queries) 148 assert.EqualValues(t, len(queries), results) 149 150 // If we do the query to the cache again, the underlying store shouldn't see it. 151 results = 0 152 err = client.QueryPages(ctx, queries, func(query chunk.IndexQuery, batch chunk.ReadBatch) bool { 153 iter := batch.Iterator() 154 for iter.Next() { 155 results++ 156 } 157 return true 158 }) 159 require.NoError(t, err) 160 assert.EqualValues(t, len(queries), store.queries) 161 assert.EqualValues(t, len(queries), results) 162 163 // If we do the query after validity, it still shouldn't see the queries. 164 time.Sleep(200 * time.Millisecond) 165 results = 0 166 err = client.QueryPages(ctx, queries, func(query chunk.IndexQuery, batch chunk.ReadBatch) bool { 167 iter := batch.Iterator() 168 for iter.Next() { 169 results++ 170 } 171 return true 172 }) 173 require.NoError(t, err) 174 assert.EqualValues(t, len(queries), store.queries) 175 assert.EqualValues(t, len(queries), results) 176 } 177 178 func TestCachingStorageClientEmptyResponse(t *testing.T) { 179 store := &mockStore{} 180 limits, err := defaultLimits() 181 require.NoError(t, err) 182 cache := cache.NewFifoCache("test", cache.FifoCacheConfig{Size: 10, Validity: 10 * time.Second}) 183 client := newCachingIndexClient(store, cache, 1*time.Second, limits) 184 queries := []chunk.IndexQuery{{TableName: "table", HashValue: "foo"}} 185 err = client.QueryPages(ctx, queries, func(query chunk.IndexQuery, batch chunk.ReadBatch) bool { 186 assert.False(t, batch.Iterator().Next()) 187 return true 188 }) 189 require.NoError(t, err) 190 assert.EqualValues(t, 1, store.queries) 191 192 // If we do the query to the cache again, the underlying store shouldn't see it. 193 err = client.QueryPages(ctx, queries, func(query chunk.IndexQuery, batch chunk.ReadBatch) bool { 194 assert.False(t, batch.Iterator().Next()) 195 return true 196 }) 197 require.NoError(t, err) 198 assert.EqualValues(t, 1, store.queries) 199 } 200 201 func TestCachingStorageClientCollision(t *testing.T) { 202 // These two queries should result in one query to the cache & index, but 203 // two results, as we cache entire rows. 204 store := &mockStore{ 205 results: ReadBatch{ 206 Entries: []Entry{ 207 { 208 Column: []byte("bar"), 209 Value: []byte("bar"), 210 }, 211 { 212 Column: []byte("baz"), 213 Value: []byte("baz"), 214 }, 215 }, 216 }, 217 } 218 limits, err := defaultLimits() 219 require.NoError(t, err) 220 cache := cache.NewFifoCache("test", cache.FifoCacheConfig{Size: 10, Validity: 10 * time.Second}) 221 client := newCachingIndexClient(store, cache, 1*time.Second, limits) 222 queries := []chunk.IndexQuery{ 223 {TableName: "table", HashValue: "foo", RangeValuePrefix: []byte("bar")}, 224 {TableName: "table", HashValue: "foo", RangeValuePrefix: []byte("baz")}, 225 } 226 227 var results ReadBatch 228 err = client.QueryPages(ctx, queries, func(query chunk.IndexQuery, batch chunk.ReadBatch) bool { 229 iter := batch.Iterator() 230 for iter.Next() { 231 results.Entries = append(results.Entries, Entry{ 232 Column: iter.RangeValue(), 233 Value: iter.Value(), 234 }) 235 } 236 return true 237 }) 238 require.NoError(t, err) 239 assert.EqualValues(t, 1, store.queries) 240 assert.EqualValues(t, store.results, results) 241 242 // If we do the query to the cache again, the underlying store shouldn't see it. 243 results = ReadBatch{} 244 err = client.QueryPages(ctx, queries, func(query chunk.IndexQuery, batch chunk.ReadBatch) bool { 245 iter := batch.Iterator() 246 for iter.Next() { 247 results.Entries = append(results.Entries, Entry{ 248 Column: iter.RangeValue(), 249 Value: iter.Value(), 250 }) 251 } 252 return true 253 }) 254 require.NoError(t, err) 255 assert.EqualValues(t, 1, store.queries) 256 assert.EqualValues(t, store.results, results) 257 }