mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-31 01:10:20 -06:00
build(deps): bump github.com/jellydator/ttlcache/v3 from 3.3.0 to 3.4.0
Bumps [github.com/jellydator/ttlcache/v3](https://github.com/jellydator/ttlcache) from 3.3.0 to 3.4.0. - [Release notes](https://github.com/jellydator/ttlcache/releases) - [Commits](https://github.com/jellydator/ttlcache/compare/v3.3.0...v3.4.0) --- updated-dependencies: - dependency-name: github.com/jellydator/ttlcache/v3 dependency-version: 3.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
2
go.mod
2
go.mod
@@ -45,7 +45,7 @@ require (
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3
|
||||
github.com/invopop/validation v0.8.0
|
||||
github.com/jellydator/ttlcache/v2 v2.11.1
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0
|
||||
github.com/jellydator/ttlcache/v3 v3.4.0
|
||||
github.com/jinzhu/now v1.1.5
|
||||
github.com/justinas/alice v1.2.0
|
||||
github.com/kovidgoyal/imaging v1.6.4
|
||||
|
||||
4
go.sum
4
go.sum
@@ -647,8 +647,8 @@ github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZ
|
||||
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||
github.com/jellydator/ttlcache/v2 v2.11.1 h1:AZGME43Eh2Vv3giG6GeqeLeFXxwxn1/qHItqWZl6U64=
|
||||
github.com/jellydator/ttlcache/v2 v2.11.1/go.mod h1:RtE5Snf0/57e+2cLWFYWCCsLas2Hy3c5Z4n14XmSvTI=
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc=
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw=
|
||||
github.com/jellydator/ttlcache/v3 v3.4.0 h1:YS4P125qQS0tNhtL6aeYkheEaB/m8HCqdMMP4mnWdTY=
|
||||
github.com/jellydator/ttlcache/v3 v3.4.0/go.mod h1:Hw9EgjymziQD3yGsQdf1FqFdpp7YjFMd4Srg5EJlgD4=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
|
||||
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
|
||||
|
||||
47
vendor/github.com/jellydator/ttlcache/v3/README.md
generated
vendored
47
vendor/github.com/jellydator/ttlcache/v3/README.md
generated
vendored
@@ -10,10 +10,9 @@
|
||||
- Type parameters
|
||||
- Item expiration and automatic deletion
|
||||
- Automatic expiration time extension on each `Get` call
|
||||
- `Loader` interface that may be used to load/lazily initialize missing cache
|
||||
- Thread Safe
|
||||
items
|
||||
- Event handlers (insertion and eviction)
|
||||
- `Loader` interface that may be used to load/lazily initialize missing cache items
|
||||
- Thread safety
|
||||
- Event handlers (insertion, update, and eviction)
|
||||
- Metrics
|
||||
|
||||
## Installation
|
||||
@@ -21,6 +20,10 @@ items
|
||||
go get github.com/jellydator/ttlcache/v3
|
||||
```
|
||||
|
||||
## Status
|
||||
The `ttlcache` package is stable and used by [Jellydator](https://jellydator.com/),
|
||||
as well as thousands of other projects and organizations in production.
|
||||
|
||||
## Usage
|
||||
The main type of `ttlcache` is `Cache`. It represents a single
|
||||
in-memory data store.
|
||||
@@ -100,7 +103,7 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
To subscribe to insertion and eviction events, `cache.OnInsertion()` and
|
||||
To subscribe to insertion, update and eviction events, `cache.OnInsertion()`, `cache.OnUpdate()` and
|
||||
`cache.OnEviction()` methods should be used:
|
||||
```go
|
||||
func main() {
|
||||
@@ -112,6 +115,9 @@ func main() {
|
||||
cache.OnInsertion(func(ctx context.Context, item *ttlcache.Item[string, string]) {
|
||||
fmt.Println(item.Value(), item.ExpiresAt())
|
||||
})
|
||||
cache.OnUpdate(func(ctx context.Context, item *ttlcache.Item[string, string]) {
|
||||
fmt.Println(item.Value(), item.ExpiresAt())
|
||||
})
|
||||
cache.OnEviction(func(ctx context.Context, reason ttlcache.EvictionReason, item *ttlcache.Item[string, string]) {
|
||||
if reason == ttlcache.EvictionReasonCapacityReached {
|
||||
fmt.Println(item.Key(), item.Value())
|
||||
@@ -141,3 +147,34 @@ func main() {
|
||||
item := cache.Get("key from file")
|
||||
}
|
||||
```
|
||||
|
||||
To restrict the cache's capacity based on criteria beyond the number
|
||||
of items it can hold, the `ttlcache.WithMaxCost` option allows for
|
||||
implementing custom strategies. The following example shows how to limit
|
||||
memory usage for cached entries to ~5KiB.
|
||||
```go
|
||||
import (
|
||||
"github.com/jellydator/ttlcache"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cache := ttlcache.New[string, string](
|
||||
ttlcache.WithMaxCost[string, string](5120, func(item ttlcache.CostItem[string, string]) uint64 {
|
||||
// Note: The below line doesn't include memory used by internal
|
||||
// structures or string metadata for the key and the value.
|
||||
return len(item.Key) + len(item.Value)
|
||||
}),
|
||||
)
|
||||
|
||||
cache.Set("first", "value1", ttlcache.DefaultTTL)
|
||||
}
|
||||
```
|
||||
|
||||
## Examples & Tutorials
|
||||
|
||||
See the [example](https://github.com/jellydator/ttlcache/tree/v3/examples)
|
||||
directory for applications demonstrating how to use `ttlcache`.
|
||||
|
||||
If you want to learn and follow along as these example applications are
|
||||
built, check out the tutorials below:
|
||||
- [Speeding Up HTTP Endpoints with Response Caching in Go](https://jellydator.com/blog/speeding-up-http-endpoints-with-response-caching-in-go/)
|
||||
|
||||
157
vendor/github.com/jellydator/ttlcache/v3/cache.go
generated
vendored
157
vendor/github.com/jellydator/ttlcache/v3/cache.go
generated
vendored
@@ -15,6 +15,7 @@ const (
|
||||
EvictionReasonDeleted EvictionReason = iota + 1
|
||||
EvictionReasonCapacityReached
|
||||
EvictionReasonExpired
|
||||
EvictionReasonMaxCostExceeded
|
||||
)
|
||||
|
||||
// EvictionReason is used to specify why a certain item was
|
||||
@@ -36,6 +37,7 @@ type Cache[K comparable, V any] struct {
|
||||
|
||||
timerCh chan time.Duration
|
||||
}
|
||||
cost uint64
|
||||
|
||||
metricsMu sync.RWMutex
|
||||
metrics Metrics
|
||||
@@ -46,6 +48,11 @@ type Cache[K comparable, V any] struct {
|
||||
nextID uint64
|
||||
fns map[uint64]func(*Item[K, V])
|
||||
}
|
||||
update struct {
|
||||
mu sync.RWMutex
|
||||
nextID uint64
|
||||
fns map[uint64]func(*Item[K, V])
|
||||
}
|
||||
eviction struct {
|
||||
mu sync.RWMutex
|
||||
nextID uint64
|
||||
@@ -53,23 +60,28 @@ type Cache[K comparable, V any] struct {
|
||||
}
|
||||
}
|
||||
|
||||
stopMu sync.Mutex
|
||||
stopCh chan struct{}
|
||||
stopped bool
|
||||
|
||||
options options[K, V]
|
||||
}
|
||||
|
||||
// New creates a new instance of cache.
|
||||
func New[K comparable, V any](opts ...Option[K, V]) *Cache[K, V] {
|
||||
c := &Cache[K, V]{
|
||||
stopCh: make(chan struct{}),
|
||||
stopCh: make(chan struct{}),
|
||||
stopped: true, // cache cleanup process is stopped by default
|
||||
}
|
||||
c.items.values = make(map[K]*list.Element)
|
||||
c.items.lru = list.New()
|
||||
c.items.expQueue = newExpirationQueue[K, V]()
|
||||
c.items.timerCh = make(chan time.Duration, 1) // buffer is important
|
||||
c.events.insertion.fns = make(map[uint64]func(*Item[K, V]))
|
||||
c.events.update.fns = make(map[uint64]func(*Item[K, V]))
|
||||
c.events.eviction.fns = make(map[uint64]func(EvictionReason, *Item[K, V]))
|
||||
|
||||
applyOptions(&c.options, opts...)
|
||||
c.options = applyOptions(c.options, opts...)
|
||||
|
||||
return c
|
||||
}
|
||||
@@ -137,9 +149,30 @@ func (c *Cache[K, V]) set(key K, value V, ttl time.Duration) *Item[K, V] {
|
||||
if elem != nil {
|
||||
// update/overwrite an existing item
|
||||
item := elem.Value.(*Item[K, V])
|
||||
oldItemCost := item.cost
|
||||
|
||||
item.update(value, ttl)
|
||||
|
||||
c.updateExpirations(false, elem)
|
||||
|
||||
if c.options.maxCost != 0 {
|
||||
c.cost = c.cost - oldItemCost + item.cost
|
||||
|
||||
for c.cost > c.options.maxCost {
|
||||
c.evict(EvictionReasonMaxCostExceeded, c.items.lru.Back())
|
||||
}
|
||||
}
|
||||
|
||||
c.metricsMu.Lock()
|
||||
c.metrics.Updates++
|
||||
c.metricsMu.Unlock()
|
||||
|
||||
c.events.update.mu.RLock()
|
||||
for _, fn := range c.events.update.fns {
|
||||
fn(item)
|
||||
}
|
||||
c.events.update.mu.RUnlock()
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
@@ -153,11 +186,19 @@ func (c *Cache[K, V]) set(key K, value V, ttl time.Duration) *Item[K, V] {
|
||||
}
|
||||
|
||||
// create a new item
|
||||
item := newItem(key, value, ttl, c.options.enableVersionTracking)
|
||||
item := NewItemWithOpts(key, value, ttl, c.options.itemOpts...)
|
||||
elem = c.items.lru.PushFront(item)
|
||||
c.items.values[key] = elem
|
||||
c.updateExpirations(true, elem)
|
||||
|
||||
if c.options.maxCost != 0 {
|
||||
c.cost += item.cost
|
||||
|
||||
for c.cost > c.options.maxCost {
|
||||
c.evict(EvictionReasonMaxCostExceeded, c.items.lru.Back())
|
||||
}
|
||||
}
|
||||
|
||||
c.metricsMu.Lock()
|
||||
c.metrics.Insertions++
|
||||
c.metricsMu.Unlock()
|
||||
@@ -212,7 +253,7 @@ func (c *Cache[K, V]) getWithOpts(key K, lockAndLoad bool, opts ...Option[K, V])
|
||||
disableTouchOnHit: c.options.disableTouchOnHit,
|
||||
}
|
||||
|
||||
applyOptions(&getOpts, opts...)
|
||||
getOpts = applyOptions(getOpts, opts...)
|
||||
|
||||
if lockAndLoad {
|
||||
c.items.mu.Lock()
|
||||
@@ -258,6 +299,11 @@ func (c *Cache[K, V]) evict(reason EvictionReason, elems ...*list.Element) {
|
||||
for i := range elems {
|
||||
item := elems[i].Value.(*Item[K, V])
|
||||
delete(c.items.values, item.key)
|
||||
|
||||
if c.options.maxCost != 0 {
|
||||
c.cost -= item.cost
|
||||
}
|
||||
|
||||
c.items.lru.Remove(elems[i])
|
||||
c.items.expQueue.remove(elems[i])
|
||||
|
||||
@@ -351,6 +397,23 @@ func (c *Cache[K, V]) Has(key K) bool {
|
||||
// If the loader is non-nil (i.e., used as an option or specified when
|
||||
// creating the cache instance), its execution is skipped.
|
||||
func (c *Cache[K, V]) GetOrSet(key K, value V, opts ...Option[K, V]) (*Item[K, V], bool) {
|
||||
return c.GetOrSetFunc(
|
||||
key,
|
||||
func() V {
|
||||
return value
|
||||
},
|
||||
opts...,
|
||||
)
|
||||
}
|
||||
|
||||
// GetOrSetFunc retrieves an item from the cache by the provided key.
|
||||
// If the element is not found, it is created by executing the fn function
|
||||
// with the provided options and then returned.
|
||||
// The bool return value is true if the item was found, false if created
|
||||
// during the execution of the method.
|
||||
// If the loader is non-nil (i.e., used as an option or specified when
|
||||
// creating the cache instance), its execution is skipped.
|
||||
func (c *Cache[K, V]) GetOrSetFunc(key K, fn func() V, opts ...Option[K, V]) (*Item[K, V], bool) {
|
||||
c.items.mu.Lock()
|
||||
defer c.items.mu.Unlock()
|
||||
|
||||
@@ -362,9 +425,9 @@ func (c *Cache[K, V]) GetOrSet(key K, value V, opts ...Option[K, V]) (*Item[K, V
|
||||
setOpts := options[K, V]{
|
||||
ttl: c.options.ttl,
|
||||
}
|
||||
applyOptions(&setOpts, opts...) // used only to update the TTL
|
||||
setOpts = applyOptions(setOpts, opts...) // used only to update the TTL
|
||||
|
||||
item := c.set(key, value, setOpts.ttl)
|
||||
item := c.set(key, fn(), setOpts.ttl)
|
||||
|
||||
return item, false
|
||||
}
|
||||
@@ -386,7 +449,7 @@ func (c *Cache[K, V]) GetAndDelete(key K, opts ...Option[K, V]) (*Item[K, V], bo
|
||||
getOpts := options[K, V]{
|
||||
loader: c.options.loader,
|
||||
}
|
||||
applyOptions(&getOpts, opts...) // used only to update the loader
|
||||
getOpts = applyOptions(getOpts, opts...) // used only to update the loader
|
||||
|
||||
if getOpts.loader != nil {
|
||||
item := getOpts.loader.Load(c, key)
|
||||
@@ -529,19 +592,17 @@ func (c *Cache[K, V]) Range(fn func(item *Item[K, V]) bool) {
|
||||
return
|
||||
}
|
||||
|
||||
for item := c.items.lru.Front(); item != c.items.lru.Back().Next(); item = item.Next() {
|
||||
for item := c.items.lru.Front(); c.items.lru.Len() != 0 && item != c.items.lru.Back().Next(); item = item.Next() {
|
||||
i := item.Value.(*Item[K, V])
|
||||
expired := i.isExpiredUnsafe()
|
||||
c.items.mu.RUnlock()
|
||||
|
||||
c.items.mu.RUnlock() // unlock mutex so fn func can access it (if it needs to)
|
||||
if !expired && !fn(i) {
|
||||
return
|
||||
}
|
||||
|
||||
if item.Next() != nil {
|
||||
c.items.mu.RLock()
|
||||
}
|
||||
c.items.mu.RLock()
|
||||
}
|
||||
|
||||
c.items.mu.RUnlock()
|
||||
}
|
||||
|
||||
// RangeBackwards calls fn for each unexpired item in the cache in reverse order.
|
||||
@@ -555,19 +616,17 @@ func (c *Cache[K, V]) RangeBackwards(fn func(item *Item[K, V]) bool) {
|
||||
return
|
||||
}
|
||||
|
||||
for item := c.items.lru.Back(); item != c.items.lru.Front().Prev(); item = item.Prev() {
|
||||
for item := c.items.lru.Back(); c.items.lru.Len() != 0 && item != c.items.lru.Front().Prev(); item = item.Prev() {
|
||||
i := item.Value.(*Item[K, V])
|
||||
expired := i.isExpiredUnsafe()
|
||||
c.items.mu.RUnlock()
|
||||
|
||||
c.items.mu.RUnlock() // unlock mutex so fn func can access it (if it needs to)
|
||||
if !expired && !fn(i) {
|
||||
return
|
||||
}
|
||||
|
||||
if item.Prev() != nil {
|
||||
c.items.mu.RLock()
|
||||
}
|
||||
c.items.mu.RLock()
|
||||
}
|
||||
|
||||
c.items.mu.RUnlock()
|
||||
}
|
||||
|
||||
// Metrics returns the metrics of the cache.
|
||||
@@ -582,6 +641,15 @@ func (c *Cache[K, V]) Metrics() Metrics {
|
||||
// expired items.
|
||||
// It blocks until Stop is called.
|
||||
func (c *Cache[K, V]) Start() {
|
||||
c.stopMu.Lock()
|
||||
if !c.stopped {
|
||||
c.stopMu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
c.stopped = false
|
||||
c.stopMu.Unlock()
|
||||
|
||||
waitDur := func() time.Duration {
|
||||
c.items.mu.RLock()
|
||||
defer c.items.mu.RUnlock()
|
||||
@@ -635,7 +703,16 @@ func (c *Cache[K, V]) Start() {
|
||||
// Stop stops the automatic cleanup process.
|
||||
// It blocks until the cleanup process exits.
|
||||
func (c *Cache[K, V]) Stop() {
|
||||
c.stopMu.Lock()
|
||||
defer c.stopMu.Unlock()
|
||||
|
||||
if c.stopped {
|
||||
return
|
||||
}
|
||||
|
||||
c.stopCh <- struct{}{}
|
||||
c.stopped = true
|
||||
|
||||
}
|
||||
|
||||
// OnInsertion adds the provided function to be executed when
|
||||
@@ -676,6 +753,44 @@ func (c *Cache[K, V]) OnInsertion(fn func(context.Context, *Item[K, V])) func()
|
||||
}
|
||||
}
|
||||
|
||||
// OnUpdate adds the provided function to be executed when
|
||||
// an item is updated in the cache. The function is executed
|
||||
// on a separate goroutine and does not block the flow of the cache
|
||||
// manager.
|
||||
// The returned function may be called to delete the subscription function
|
||||
// from the list of update subscribers.
|
||||
// When the returned function is called, it blocks until all instances of
|
||||
// the same subscription function return. A context is used to notify the
|
||||
// subscription function when the returned/deletion function is called.
|
||||
func (c *Cache[K, V]) OnUpdate(fn func(context.Context, *Item[K, V])) func() {
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
ctx, cancel = context.WithCancel(context.Background())
|
||||
)
|
||||
|
||||
c.events.update.mu.Lock()
|
||||
id := c.events.update.nextID
|
||||
c.events.update.fns[id] = func(item *Item[K, V]) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
fn(ctx, item)
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
c.events.update.nextID++
|
||||
c.events.update.mu.Unlock()
|
||||
|
||||
return func() {
|
||||
cancel()
|
||||
|
||||
c.events.update.mu.Lock()
|
||||
delete(c.events.update.fns, id)
|
||||
c.events.update.mu.Unlock()
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
}
|
||||
|
||||
// OnEviction adds the provided function to be executed when
|
||||
// an item is evicted/deleted from the cache. The function is executed
|
||||
// on a separate goroutine and does not block the flow of the cache
|
||||
|
||||
80
vendor/github.com/jellydator/ttlcache/v3/item.go
generated
vendored
80
vendor/github.com/jellydator/ttlcache/v3/item.go
generated
vendored
@@ -18,6 +18,13 @@ const (
|
||||
DefaultTTL time.Duration = 0
|
||||
)
|
||||
|
||||
// CostItem holds the key and the value of the Item object for
|
||||
// Item cost calculation purposes.
|
||||
type CostItem[K comparable, V any] struct {
|
||||
Key K
|
||||
Value V
|
||||
}
|
||||
|
||||
// Item holds all the information that is associated with a single
|
||||
// cache value.
|
||||
type Item[K comparable, V any] struct {
|
||||
@@ -30,28 +37,42 @@ type Item[K comparable, V any] struct {
|
||||
// well, so locking this mutex would be redundant.
|
||||
// In other words, this mutex is only useful when these fields
|
||||
// are being read from the outside (e.g. in event functions).
|
||||
mu sync.RWMutex
|
||||
key K
|
||||
value V
|
||||
ttl time.Duration
|
||||
expiresAt time.Time
|
||||
queueIndex int
|
||||
version int64
|
||||
mu sync.RWMutex
|
||||
key K
|
||||
value V
|
||||
ttl time.Duration
|
||||
expiresAt time.Time
|
||||
queueIndex int
|
||||
version int64
|
||||
calculateCost CostFunc[K, V]
|
||||
cost uint64
|
||||
}
|
||||
|
||||
// newItem creates a new cache item.
|
||||
func newItem[K comparable, V any](key K, value V, ttl time.Duration, enableVersionTracking bool) *Item[K, V] {
|
||||
// NewItem creates a new cache item.
|
||||
//
|
||||
// Deprecated: Use NewItemWithOpts instead. This function will be removed
|
||||
// in a future release.
|
||||
func NewItem[K comparable, V any](key K, value V, ttl time.Duration, enableVersionTracking bool) *Item[K, V] {
|
||||
return NewItemWithOpts(key, value, ttl, WithItemVersion[K, V](enableVersionTracking))
|
||||
}
|
||||
|
||||
// NewItemWithOpts creates a new cache item and applies the provided item
|
||||
// options.
|
||||
func NewItemWithOpts[K comparable, V any](key K, value V, ttl time.Duration, opts ...ItemOption[K, V]) *Item[K, V] {
|
||||
item := &Item[K, V]{
|
||||
key: key,
|
||||
value: value,
|
||||
ttl: ttl,
|
||||
}
|
||||
|
||||
if !enableVersionTracking {
|
||||
item.version = -1
|
||||
key: key,
|
||||
value: value,
|
||||
ttl: ttl,
|
||||
version: -1,
|
||||
calculateCost: func(item CostItem[K, V]) uint64 { return 0 },
|
||||
}
|
||||
|
||||
applyItemOptions(item, opts...)
|
||||
item.touch()
|
||||
item.cost = item.calculateCost(CostItem[K, V]{
|
||||
Key: key,
|
||||
Value: value,
|
||||
})
|
||||
|
||||
return item
|
||||
}
|
||||
@@ -69,16 +90,19 @@ func (item *Item[K, V]) update(value V, ttl time.Duration) {
|
||||
}
|
||||
|
||||
// no need to update ttl or expiry in this case
|
||||
if ttl == PreviousOrDefaultTTL {
|
||||
return
|
||||
if ttl != PreviousOrDefaultTTL {
|
||||
item.ttl = ttl
|
||||
// reset expiration timestamp because the new TTL may be
|
||||
// 0 or below
|
||||
item.expiresAt = time.Time{}
|
||||
item.touchUnsafe()
|
||||
}
|
||||
|
||||
item.ttl = ttl
|
||||
|
||||
// reset expiration timestamp because the new TTL may be
|
||||
// 0 or below
|
||||
item.expiresAt = time.Time{}
|
||||
item.touchUnsafe()
|
||||
// calculating the costs
|
||||
item.cost = item.calculateCost(CostItem[K, V]{
|
||||
Key: item.key,
|
||||
Value: item.value,
|
||||
})
|
||||
}
|
||||
|
||||
// touch updates the item's expiration timestamp.
|
||||
@@ -142,6 +166,14 @@ func (item *Item[K, V]) TTL() time.Duration {
|
||||
return item.ttl
|
||||
}
|
||||
|
||||
// Cost returns the cost of the item.
|
||||
func (item *Item[K, V]) Cost() uint64 {
|
||||
item.mu.RLock()
|
||||
defer item.mu.RUnlock()
|
||||
|
||||
return item.cost
|
||||
}
|
||||
|
||||
// ExpiresAt returns the expiration timestamp of the item.
|
||||
func (item *Item[K, V]) ExpiresAt() time.Time {
|
||||
item.mu.RLock()
|
||||
|
||||
3
vendor/github.com/jellydator/ttlcache/v3/metrics.go
generated
vendored
3
vendor/github.com/jellydator/ttlcache/v3/metrics.go
generated
vendored
@@ -6,6 +6,9 @@ type Metrics struct {
|
||||
// Insertions specifies how many items were inserted.
|
||||
Insertions uint64
|
||||
|
||||
// Updates specifies how many items were updated.
|
||||
Updates uint64
|
||||
|
||||
// Hits specifies how many items were successfully retrieved
|
||||
// from the cache.
|
||||
// Retrievals made with a loader function are not tracked.
|
||||
|
||||
105
vendor/github.com/jellydator/ttlcache/v3/options.go
generated
vendored
105
vendor/github.com/jellydator/ttlcache/v3/options.go
generated
vendored
@@ -4,46 +4,56 @@ import "time"
|
||||
|
||||
// Option sets a specific cache option.
|
||||
type Option[K comparable, V any] interface {
|
||||
apply(opts *options[K, V])
|
||||
apply(opts options[K, V]) options[K, V]
|
||||
}
|
||||
|
||||
// optionFunc wraps a function and implements the Option interface.
|
||||
type optionFunc[K comparable, V any] func(*options[K, V])
|
||||
type optionFunc[K comparable, V any] func(options[K, V]) options[K, V]
|
||||
|
||||
// apply calls the wrapped function.
|
||||
func (fn optionFunc[K, V]) apply(opts *options[K, V]) {
|
||||
fn(opts)
|
||||
func (fn optionFunc[K, V]) apply(opts options[K, V]) options[K, V] {
|
||||
return fn(opts)
|
||||
}
|
||||
|
||||
// CostFunc is used to calculate the cost of the key and the item to be
|
||||
// inserted into the cache.
|
||||
type CostFunc[K comparable, V any] func(item CostItem[K, V]) uint64
|
||||
|
||||
// options holds all available cache configuration options.
|
||||
type options[K comparable, V any] struct {
|
||||
capacity uint64
|
||||
ttl time.Duration
|
||||
loader Loader[K, V]
|
||||
disableTouchOnHit bool
|
||||
enableVersionTracking bool
|
||||
capacity uint64
|
||||
maxCost uint64
|
||||
ttl time.Duration
|
||||
loader Loader[K, V]
|
||||
disableTouchOnHit bool
|
||||
itemOpts []ItemOption[K, V]
|
||||
}
|
||||
|
||||
// applyOptions applies the provided option values to the option struct.
|
||||
func applyOptions[K comparable, V any](v *options[K, V], opts ...Option[K, V]) {
|
||||
// applyOptions applies the provided option values to the option struct
|
||||
// and returns the modified option struct.
|
||||
func applyOptions[K comparable, V any](v options[K, V], opts ...Option[K, V]) options[K, V] {
|
||||
for i := range opts {
|
||||
opts[i].apply(v)
|
||||
v = opts[i].apply(v)
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// WithCapacity sets the maximum capacity of the cache.
|
||||
// It has no effect when used with Get().
|
||||
func WithCapacity[K comparable, V any](c uint64) Option[K, V] {
|
||||
return optionFunc[K, V](func(opts *options[K, V]) {
|
||||
return optionFunc[K, V](func(opts options[K, V]) options[K, V] {
|
||||
opts.capacity = c
|
||||
return opts
|
||||
})
|
||||
}
|
||||
|
||||
// WithTTL sets the TTL of the cache.
|
||||
// It has no effect when used with Get().
|
||||
func WithTTL[K comparable, V any](ttl time.Duration) Option[K, V] {
|
||||
return optionFunc[K, V](func(opts *options[K, V]) {
|
||||
return optionFunc[K, V](func(opts options[K, V]) options[K, V] {
|
||||
opts.ttl = ttl
|
||||
return opts
|
||||
})
|
||||
}
|
||||
|
||||
@@ -51,8 +61,9 @@ func WithTTL[K comparable, V any](ttl time.Duration) Option[K, V] {
|
||||
// If version tracking is disabled, the version is always -1.
|
||||
// It has no effect when used with Get().
|
||||
func WithVersion[K comparable, V any](enable bool) Option[K, V] {
|
||||
return optionFunc[K, V](func(opts *options[K, V]) {
|
||||
opts.enableVersionTracking = enable
|
||||
return optionFunc[K, V](func(opts options[K, V]) options[K, V] {
|
||||
opts.itemOpts = append(opts.itemOpts, WithItemVersion[K, V](enable))
|
||||
return opts
|
||||
})
|
||||
}
|
||||
|
||||
@@ -60,8 +71,9 @@ func WithVersion[K comparable, V any](enable bool) Option[K, V] {
|
||||
// When passing into Get(), it sets an ephemeral loader that
|
||||
// is used instead of the cache's default one.
|
||||
func WithLoader[K comparable, V any](l Loader[K, V]) Option[K, V] {
|
||||
return optionFunc[K, V](func(opts *options[K, V]) {
|
||||
return optionFunc[K, V](func(opts options[K, V]) options[K, V] {
|
||||
opts.loader = l
|
||||
return opts
|
||||
})
|
||||
}
|
||||
|
||||
@@ -71,7 +83,64 @@ func WithLoader[K comparable, V any](l Loader[K, V]) Option[K, V] {
|
||||
// When used with Get(), it overrides the default value of the
|
||||
// cache.
|
||||
func WithDisableTouchOnHit[K comparable, V any]() Option[K, V] {
|
||||
return optionFunc[K, V](func(opts *options[K, V]) {
|
||||
return optionFunc[K, V](func(opts options[K, V]) options[K, V] {
|
||||
opts.disableTouchOnHit = true
|
||||
return opts
|
||||
})
|
||||
}
|
||||
|
||||
// WithMaxCost sets the maximum cost the cache is allowed to use (e.g. the used memory).
|
||||
// The actual cost calculation for each inserted item happens by making use of the
|
||||
// callback CostFunc.
|
||||
// It has no effect when used with Get().
|
||||
func WithMaxCost[K comparable, V any](s uint64, callback CostFunc[K, V]) Option[K, V] {
|
||||
return optionFunc[K, V](func(opts options[K, V]) options[K, V] {
|
||||
opts.maxCost = s
|
||||
opts.itemOpts = append(opts.itemOpts, WithItemCostFunc(callback))
|
||||
return opts
|
||||
})
|
||||
}
|
||||
|
||||
// ItemOption sets a specific item option on item creation.
|
||||
type ItemOption[K comparable, V any] interface {
|
||||
apply(item *Item[K, V])
|
||||
}
|
||||
|
||||
// itemOptionFunc wraps a function and implements the itemOption interface.
|
||||
type itemOptionFunc[K comparable, V any] func(*Item[K, V])
|
||||
|
||||
// apply calls the wrapped function.
|
||||
func (fn itemOptionFunc[K, V]) apply(item *Item[K, V]) {
|
||||
fn(item)
|
||||
}
|
||||
|
||||
// applyItemOptions applies the provided option values to the Item.
|
||||
// Note that this function needs to be called only when creating a new item,
|
||||
// because we don't use the Item's mutex here.
|
||||
func applyItemOptions[K comparable, V any](item *Item[K, V], opts ...ItemOption[K, V]) {
|
||||
for i := range opts {
|
||||
opts[i].apply(item)
|
||||
}
|
||||
}
|
||||
|
||||
// WithItemVersion activates item version tracking.
|
||||
// If version tracking is disabled, the version is always -1.
|
||||
func WithItemVersion[K comparable, V any](enable bool) ItemOption[K, V] {
|
||||
return itemOptionFunc[K, V](func(item *Item[K, V]) {
|
||||
if enable {
|
||||
item.version = 0
|
||||
} else {
|
||||
item.version = -1
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// WithItemCostFunc configures an item's cost calculation function.
|
||||
// A nil value disables an item's cost calculation.
|
||||
func WithItemCostFunc[K comparable, V any](costFunc CostFunc[K, V]) ItemOption[K, V] {
|
||||
return itemOptionFunc[K, V](func(item *Item[K, V]) {
|
||||
if costFunc != nil {
|
||||
item.calculateCost = costFunc
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@@ -805,8 +805,8 @@ github.com/jbenet/go-context/io
|
||||
# github.com/jellydator/ttlcache/v2 v2.11.1
|
||||
## explicit; go 1.15
|
||||
github.com/jellydator/ttlcache/v2
|
||||
# github.com/jellydator/ttlcache/v3 v3.3.0
|
||||
## explicit; go 1.18
|
||||
# github.com/jellydator/ttlcache/v3 v3.4.0
|
||||
## explicit; go 1.23.0
|
||||
github.com/jellydator/ttlcache/v3
|
||||
# github.com/jinzhu/now v1.1.5
|
||||
## explicit; go 1.12
|
||||
|
||||
Reference in New Issue
Block a user