Welcome to mirror list, hosted at ThFree Co, Russian Federation.

lru_cache.go « zip « vfs « internal - gitlab.com/gitlab-org/gitlab-pages.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9810e2453c6f7c1061f6154b11f714fc9b145f10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package zip

import (
	"time"

	"github.com/karlseguin/ccache/v2"

	"gitlab.com/gitlab-org/gitlab-pages/metrics"
)

// lruCacheGetPerPromote is a value that makes the item to be promoted
// it is taken arbitrally as a sane value indicating that the item
// was frequently picked
// promotion moves the item to the front of the LRU list
const lruCacheGetsPerPromote = 64

// lruCacheItemsToPruneDiv is a value that indicates how much items
// needs to be pruned on OOM, this prunes 1/16 of items
const lruCacheItemsToPruneDiv = 16

type lruCache struct {
	op       string
	duration time.Duration
	cache    *ccache.Cache
}

func newLruCache(op string, maxEntries int64, duration time.Duration) *lruCache {
	configuration := ccache.Configure()
	configuration.MaxSize(maxEntries)
	configuration.ItemsToPrune(uint32(maxEntries) / lruCacheItemsToPruneDiv)
	configuration.GetsPerPromote(lruCacheGetsPerPromote) // if item gets requested frequently promote it
	configuration.OnDelete(func(*ccache.Item) {
		metrics.ZipCachedEntries.WithLabelValues(op).Dec()
	})

	return &lruCache{
		op:       op,
		cache:    ccache.New(configuration),
		duration: duration,
	}
}

func (c *lruCache) findOrFetch(cacheNamespace, key string, fetchFn func() (interface{}, error)) (interface{}, error) {
	item := c.cache.Get(cacheNamespace + key)

	if item != nil && !item.Expired() {
		metrics.ZipCacheRequests.WithLabelValues(c.op, "hit").Inc()
		return item.Value(), nil
	}

	value, err := fetchFn()
	if err != nil {
		metrics.ZipCacheRequests.WithLabelValues(c.op, "error").Inc()
		return nil, err
	}

	metrics.ZipCacheRequests.WithLabelValues(c.op, "miss").Inc()
	metrics.ZipCachedEntries.WithLabelValues(c.op).Inc()

	c.cache.Set(cacheNamespace+key, value, c.duration)
	return value, nil
}