github.com/thanos-io/thanos@v0.32.5/internal/cortex/chunk/cache/cache_gen.go (about)

     1  // Copyright (c) The Cortex Authors.
     2  // Licensed under the Apache License 2.0.
     3  
     4  package cache
     5  
     6  import (
     7  	"context"
     8  )
     9  
    10  type contextKey int
    11  
    12  // cacheGenContextKey is used for setting a Cache Generation number in context.
    13  const cacheGenContextKey contextKey = 0
    14  
    15  // GenNumMiddleware adds gen number to keys from context. Expected size of gen numbers is upto 2 digits.
    16  // If we start seeing problems with keys exceeding length limit, we need to look into resetting gen numbers.
    17  type GenNumMiddleware struct {
    18  	downstreamCache Cache
    19  }
    20  
    21  // NewCacheGenNumMiddleware creates a new GenNumMiddleware.
    22  func NewCacheGenNumMiddleware(downstreamCache Cache) Cache {
    23  	return &GenNumMiddleware{downstreamCache}
    24  }
    25  
    26  // Store adds cache gen number to keys before calling Store method of downstream cache.
    27  func (c GenNumMiddleware) Store(ctx context.Context, keys []string, buf [][]byte) {
    28  	keys = addCacheGenNumToCacheKeys(ctx, keys)
    29  	c.downstreamCache.Store(ctx, keys, buf)
    30  }
    31  
    32  // Fetch adds cache gen number to keys before calling Fetch method of downstream cache.
    33  // It also removes gen number before responding back with found and missing keys to make sure consumer of response gets to see same keys.
    34  func (c GenNumMiddleware) Fetch(ctx context.Context, keys []string) (found []string, bufs [][]byte, missing []string) {
    35  	keys = addCacheGenNumToCacheKeys(ctx, keys)
    36  
    37  	found, bufs, missing = c.downstreamCache.Fetch(ctx, keys)
    38  
    39  	found = removeCacheGenNumFromKeys(ctx, found)
    40  	missing = removeCacheGenNumFromKeys(ctx, missing)
    41  
    42  	return
    43  }
    44  
    45  // Stop calls Stop method of downstream cache.
    46  func (c GenNumMiddleware) Stop() {
    47  	c.downstreamCache.Stop()
    48  }
    49  
    50  // InjectCacheGenNumber returns a derived context containing the cache gen.
    51  func InjectCacheGenNumber(ctx context.Context, cacheGen string) context.Context {
    52  	return context.WithValue(ctx, interface{}(cacheGenContextKey), cacheGen)
    53  }
    54  
    55  // ExtractCacheGenNumbersFromHeaders gets the cache gen from the context.
    56  func ExtractCacheGenNumber(ctx context.Context) string {
    57  	cacheGenNumber, ok := ctx.Value(cacheGenContextKey).(string)
    58  	if !ok {
    59  		return ""
    60  	}
    61  	return cacheGenNumber
    62  }
    63  
    64  // addCacheGenNumToCacheKeys adds gen number to keys as prefix.
    65  func addCacheGenNumToCacheKeys(ctx context.Context, keys []string) []string {
    66  	cacheGen := ExtractCacheGenNumber(ctx)
    67  	if cacheGen == "" {
    68  		return keys
    69  	}
    70  
    71  	prefixedKeys := make([]string, len(keys))
    72  
    73  	for i := range keys {
    74  		prefixedKeys[i] = cacheGen + keys[i]
    75  	}
    76  
    77  	return prefixedKeys
    78  }
    79  
    80  // removeCacheGenNumFromKeys removes prefixed gen number from keys.
    81  func removeCacheGenNumFromKeys(ctx context.Context, keys []string) []string {
    82  	cacheGen := ExtractCacheGenNumber(ctx)
    83  	if cacheGen == "" {
    84  		return keys
    85  	}
    86  
    87  	unprefixedKeys := make([]string, len(keys))
    88  	cacheGenPrefixLen := len(cacheGen)
    89  
    90  	for i := range keys {
    91  		unprefixedKeys[i] = keys[i][cacheGenPrefixLen:]
    92  	}
    93  
    94  	return unprefixedKeys
    95  }