Update vendored dskit (#8155)

**What this PR does / why we need it**:

The Changelog diff between the two commits is
3e308a4944...7242706251

```
* [CHANGE] Cache: Switch Memcached backend to use `github.com/grafana/gomemcache` repository instead of `github.com/bradfitz/gomemcache`. #248
* [ENHANCEMENT] Add cache, gate and stringsutil packages. #239
* [ENHANCEMENT] Cache: add Redis support. #245
* [ENHANCEMENT] Cache: Add the ability to use a custom memory allocator for cache results. #249
* [BUGFIX] Memberlist: fix crash when methods from `memberlist.Delegate` interface are called on `*memberlist.KV` before the service is fully started. #244
```

**Checklist**
- [x] Reviewed the [`CONTRIBUTING.md`](../CONTRIBUTING.md) guide
(**required**)
- N/A Documentation added
- N/A Tests updated
- N/A `CHANGELOG.md` updated
- N/A Changes that require user attention or interaction to upgrade are
documented in `docs/sources/upgrading/_index.md`
pull/8159/head
Dimitar Dimitrov 2 years ago committed by GitHub
parent d317e659c7
commit 6ea5a8e497
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      go.mod
  2. 11
      go.sum
  3. 2
      pkg/storage/chunk/cache/memcached_client.go
  4. 2
      pkg/storage/chunk/cache/memcached_client_test.go
  5. 2
      pkg/storage/chunk/cache/memcached_test.go
  6. 4
      vendor/github.com/grafana/dskit/crypto/tls/tls.go
  7. 11
      vendor/github.com/grafana/dskit/internal/slices/slices.go
  8. 28
      vendor/github.com/grafana/dskit/kv/memberlist/memberlist_client.go
  9. 4
      vendor/github.com/grafana/dskit/ring/client/pool.go
  10. 14
      vendor/github.com/grafana/dskit/ring/ring.go
  11. 12
      vendor/github.com/grafana/dskit/ring/util/string_utils.go
  12. 57
      vendor/github.com/grafana/gomemcache/memcache/memcache.go
  13. 59
      vendor/github.com/grafana/gomemcache/memcache/options.go
  14. 10
      vendor/modules.txt

@ -48,9 +48,9 @@ require (
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
github.com/grafana/cloudflare-go v0.0.0-20230110200409-c627cf6792f2
github.com/grafana/dskit v0.0.0-20221212120341-3e308a49441b
github.com/grafana/dskit v0.0.0-20230109170026-7242706251b9
github.com/grafana/go-gelf/v2 v2.0.1
github.com/grafana/gomemcache v0.0.0-20221213170046-b5da8a745d41
github.com/grafana/gomemcache v0.0.0-20230105173749-11f792309e1f
github.com/grafana/regexp v0.0.0-20221005093135-b4c2bcb0a4b6
github.com/grafana/tail v0.0.0-20221214082743-3a1c242a4d7b
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
@ -253,7 +253,6 @@ require (
github.com/prometheus/exporter-toolkit v0.8.2 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/rs/xid v1.4.0 // indirect
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
github.com/sercand/kuberesolver v2.4.0+incompatible // indirect

@ -736,14 +736,14 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/grafana/cloudflare-go v0.0.0-20230110200409-c627cf6792f2 h1:qhugDMdQ4Vp68H0tp/0iN17DM2ehRo1rLEdOFe/gB8I=
github.com/grafana/cloudflare-go v0.0.0-20230110200409-c627cf6792f2/go.mod h1:w/aiO1POVIeXUQyl0VQSZjl5OAGDTL5aX+4v0RA1tcw=
github.com/grafana/dskit v0.0.0-20221212120341-3e308a49441b h1:3Di+jzpE0CHlzlYtjDq9xL5xinR4FUQ7GoQ44JkfQLc=
github.com/grafana/dskit v0.0.0-20221212120341-3e308a49441b/go.mod h1:rJRGBDtyQNA3OFh7WecUILvxkgGrdIuA4f9wgZOn3V0=
github.com/grafana/dskit v0.0.0-20230109170026-7242706251b9 h1:eAPMj0IgfkMn+jxBjIbNjnak7Fu/0HXWF+/DMWRS/Sk=
github.com/grafana/dskit v0.0.0-20230109170026-7242706251b9/go.mod h1:zj+5BNZAVmQafV583uLTAOzRr963KPdEm4d6NPmtbwg=
github.com/grafana/go-gelf/v2 v2.0.1 h1:BOChP0h/jLeD+7F9mL7tq10xVkDG15he3T1zHuQaWak=
github.com/grafana/go-gelf/v2 v2.0.1/go.mod h1:lexHie0xzYGwCgiRGcvZ723bSNyNI8ZRD4s0CLobh90=
github.com/grafana/gocql v0.0.0-20200605141915-ba5dc39ece85 h1:xLuzPoOzdfNb/RF/IENCw+oLVdZB4G21VPhkHBgwSHY=
github.com/grafana/gocql v0.0.0-20200605141915-ba5dc39ece85/go.mod h1:crI9WX6p0IhrqB+DqIUHulRW853PaNFf7o4UprV//3I=
github.com/grafana/gomemcache v0.0.0-20221213170046-b5da8a745d41 h1:YxVdHh0Erfya/wb4mzy/JkTxtmefBICE6gAwSkS+61I=
github.com/grafana/gomemcache v0.0.0-20221213170046-b5da8a745d41/go.mod h1:6fkC8bkriadatJOc7Pvjcvqr2xh9C79BYRRfE3WWoo0=
github.com/grafana/gomemcache v0.0.0-20230105173749-11f792309e1f h1:ANwIMe7kOiMNTK88tusoNDb840pWVskI4rCrdoMv5i0=
github.com/grafana/gomemcache v0.0.0-20230105173749-11f792309e1f/go.mod h1:PGk3RjYHpxMM8HFPhKKo+vve3DdlPUELZLSDEFehPuU=
github.com/grafana/memberlist v0.3.1-0.20220714140823-09ffed8adbbe h1:yIXAAbLswn7VNWBIvM71O2QsgfgW9fRXZNR0DXe6pDU=
github.com/grafana/memberlist v0.3.1-0.20220714140823-09ffed8adbbe/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/grafana/regexp v0.0.0-20221005093135-b4c2bcb0a4b6 h1:A3dhViTeFDSQcGOXuUi6ukCQSMyDtDISBp2z6OOo2YM=
@ -1108,7 +1108,7 @@ github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/openconfig/gnmi v0.0.0-20180912164834-33a1865c3029/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@ -1244,7 +1244,6 @@ github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rollbar/rollbar-go v1.0.2/go.mod h1:AcFs5f0I+c71bpHlXNNDbOWJiKwjFDtISeXco0L5PKQ=
github.com/rollbar/rollbar-go v1.2.0/go.mod h1:czC86b8U4xdUH7W2C6gomi2jutLm8qK0OtrF5WMvpcc=
github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=

@ -24,7 +24,7 @@ import (
// MemcachedClient interface exists for mocking memcacheClient.
type MemcachedClient interface {
GetMulti(keys []string) (map[string]*memcache.Item, error)
GetMulti(keys []string, opts ...memcache.Option) (map[string]*memcache.Item, error)
Set(item *memcache.Item) error
}

@ -17,7 +17,7 @@ func newMockMemcache() *mockMemcache {
}
}
func (m *mockMemcache) GetMulti(keys []string) (map[string]*memcache.Item, error) {
func (m *mockMemcache) GetMulti(keys []string, _ ...memcache.Option) (map[string]*memcache.Item, error) {
m.RLock()
defer m.RUnlock()
result := map[string]*memcache.Item{}

@ -125,7 +125,7 @@ func newMockMemcacheFailing() *mockMemcacheFailing {
}
}
func (c *mockMemcacheFailing) GetMulti(keys []string) (map[string]*memcache.Item, error) {
func (c *mockMemcacheFailing) GetMulti(keys []string, _ ...memcache.Option) (map[string]*memcache.Item, error) {
calls := c.calls.Inc()
if calls%3 == 0 {
return nil, errors.New("fail")

@ -8,6 +8,8 @@ import (
"os"
"strings"
"google.golang.org/grpc/credentials/insecure"
"github.com/pkg/errors"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
@ -126,7 +128,7 @@ func (cfg *ClientConfig) GetTLSConfig() (*tls.Config, error) {
// GetGRPCDialOptions creates GRPC DialOptions for TLS
func (cfg *ClientConfig) GetGRPCDialOptions(enabled bool) ([]grpc.DialOption, error) {
if !enabled {
return []grpc.DialOption{grpc.WithInsecure()}, nil
return []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}, nil
}
tlsConfig, err := cfg.GetTLSConfig()

@ -0,0 +1,11 @@
package slices
func Contains[T comparable](haystack []T, needle T) bool {
for _, e := range haystack {
if e == needle {
return true
}
}
return false
}

@ -18,6 +18,7 @@ import (
"github.com/go-kit/log/level"
"github.com/hashicorp/memberlist"
"github.com/prometheus/client_golang/prometheus"
"go.uber.org/atomic"
"github.com/grafana/dskit/backoff"
"github.com/grafana/dskit/flagext"
@ -233,9 +234,9 @@ type KV struct {
provider DNSProvider
// Protects access to memberlist and broadcasts fields.
initWG sync.WaitGroup
memberlist *memberlist.Memberlist
broadcasts *memberlist.TransmitLimitedQueue
delegateReady atomic.Bool
memberlist *memberlist.Memberlist
broadcasts *memberlist.TransmitLimitedQueue
// KV Store.
storeMu sync.Mutex
@ -451,7 +452,6 @@ func (m *KV) starting(ctx context.Context) error {
//
// Note: We cannot check for Starting state, as we want to use delegate during cluster joining process
// that happens in Starting state.
m.initWG.Add(1)
list, err := memberlist.Create(mlCfg)
if err != nil {
return fmt.Errorf("failed to create memberlist: %v", err)
@ -462,7 +462,7 @@ func (m *KV) starting(ctx context.Context) error {
NumNodes: list.NumMembers,
RetransmitMult: mlCfg.RetransmitMult,
}
m.initWG.Done()
m.delegateReady.Store(true)
// Try to fast-join memberlist cluster in Starting state, so that we don't start with empty KV store.
if len(m.cfg.JoinMembers) > 0 {
@ -992,6 +992,10 @@ func (m *KV) NodeMeta(limit int) []byte {
// NotifyMsg is method from Memberlist Delegate interface
// Called when single message is received, i.e. what our broadcastNewValue has sent.
func (m *KV) NotifyMsg(msg []byte) {
if !m.delegateReady.Load() {
return
}
m.numberOfReceivedMessages.Inc()
m.totalSizeOfReceivedMessages.Add(float64(len(msg)))
@ -1101,7 +1105,9 @@ func (m *KV) queueBroadcast(key string, content []string, version uint, message
// GetBroadcasts is method from Memberlist Delegate interface
// It returns all pending broadcasts (within the size limit)
func (m *KV) GetBroadcasts(overhead, limit int) [][]byte {
m.initWG.Wait()
if !m.delegateReady.Load() {
return nil
}
return m.broadcasts.GetBroadcasts(overhead, limit)
}
@ -1112,7 +1118,9 @@ func (m *KV) GetBroadcasts(overhead, limit int) [][]byte {
// Here we dump our entire state -- all keys and their values. There is no limit on message size here,
// as Memberlist uses 'stream' operations for transferring this state.
func (m *KV) LocalState(join bool) []byte {
m.initWG.Wait()
if !m.delegateReady.Load() {
return nil
}
m.numberOfPulls.Inc()
@ -1184,9 +1192,11 @@ func (m *KV) LocalState(join bool) []byte {
//
// Data is full state of remote KV store, as generated by LocalState method (run on another node).
func (m *KV) MergeRemoteState(data []byte, join bool) {
received := time.Now()
if !m.delegateReady.Load() {
return
}
m.initWG.Wait()
received := time.Now()
m.numberOfPushes.Inc()
m.totalSizeOfPushes.Add(float64(len(data)))

@ -14,7 +14,7 @@ import (
"google.golang.org/grpc/health/grpc_health_v1"
"github.com/grafana/dskit/concurrency"
"github.com/grafana/dskit/ring/util"
"github.com/grafana/dskit/internal/slices"
"github.com/grafana/dskit/services"
)
@ -171,7 +171,7 @@ func (p *Pool) removeStaleClients() {
}
for _, addr := range p.RegisteredAddresses() {
if util.StringsContain(serviceAddrs, addr) {
if slices.Contains(serviceAddrs, addr) {
continue
}
level.Info(p.logger).Log("msg", "removing stale client", "addr", addr)

@ -6,6 +6,7 @@ import (
"context"
"flag"
"fmt"
"math"
"math/rand"
"net/http"
@ -19,13 +20,12 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/grafana/dskit/flagext"
dsmath "github.com/grafana/dskit/internal/math"
"github.com/grafana/dskit/internal/slices"
"github.com/grafana/dskit/kv"
shardUtil "github.com/grafana/dskit/ring/shard"
"github.com/grafana/dskit/ring/util"
"github.com/grafana/dskit/services"
"github.com/grafana/dskit/flagext"
dsmath "github.com/grafana/dskit/internal/math"
)
const (
@ -291,7 +291,7 @@ func (r *Ring) updateRingState(ringDesc *Desc) {
// Filter out all instances belonging to excluded zones.
if len(r.cfg.ExcludedZones) > 0 {
for instanceID, instance := range ringDesc.Ingesters {
if util.StringsContain(r.cfg.ExcludedZones, instance.Zone) {
if slices.Contains(r.cfg.ExcludedZones, instance.Zone) {
delete(ringDesc.Ingesters, instanceID)
}
}
@ -364,13 +364,13 @@ func (r *Ring) Get(key uint32, op Operation, bufDescs []InstanceDesc, bufHosts,
}
// We want n *distinct* instances && distinct zones.
if util.StringsContain(distinctHosts, info.InstanceID) {
if slices.Contains(distinctHosts, info.InstanceID) {
continue
}
// Ignore if the instances don't have a zone set.
if r.cfg.ZoneAwarenessEnabled && info.Zone != "" {
if util.StringsContain(distinctZones, info.Zone) {
if slices.Contains(distinctZones, info.Zone) {
continue
}
}

@ -1,12 +0,0 @@
package util
// StringsContain returns true if the search value is within the list of input values.
func StringsContain(values []string, search string) bool {
for _, v := range values {
if search == v {
return true
}
}
return false
}

@ -100,7 +100,6 @@ func legalKey(key string) bool {
var (
crlf = []byte("\r\n")
space = []byte(" ")
resultOK = []byte("OK\r\n")
resultStored = []byte("STORED\r\n")
resultNotStored = []byte("NOT_STORED\r\n")
@ -113,6 +112,7 @@ var (
resultClientErrorPrefix = []byte("CLIENT_ERROR ")
versionPrefix = []byte("VERSION")
valuePrefix = []byte("VALUE ")
)
// New returns a memcache client using the provided server(s)
@ -120,7 +120,7 @@ var (
// it gets a proportional amount of weight.
func New(server ...string) *Client {
ss := new(ServerList)
ss.SetServers(server...)
_ = ss.SetServers(server...)
return NewFromSelector(ss)
}
@ -146,8 +146,6 @@ type Client struct {
// be set to a number higher than your peak parallel requests.
MaxIdleConns int
Pool BytesPool
selector ServerSelector
lk sync.Mutex
@ -183,22 +181,13 @@ type conn struct {
c *Client
}
// BytesPool is a pool of bytes that can be reused.
type BytesPool interface {
// Get returns a new byte slice that has a capacity at least the same as the
// requested size.
Get(sz int) (*[]byte, error)
// Put returns a byte slice to the pool.
Put(b *[]byte)
}
// release returns this connection back to the client's free pool
func (cn *conn) release() {
cn.c.putFreeConn(cn.addr, cn)
}
func (cn *conn) extendDeadline() {
cn.nc.SetDeadline(time.Now().Add(cn.c.netTimeout()))
_ = cn.nc.SetDeadline(time.Now().Add(cn.c.netTimeout()))
}
// condRelease releases this connection if the error pointed to by err
@ -326,9 +315,10 @@ func (c *Client) FlushAll() error {
// Get gets the item for the given key. ErrCacheMiss is returned for a
// memcache cache miss. The key must be at most 250 bytes in length.
func (c *Client) Get(key string) (item *Item, err error) {
func (c *Client) Get(key string, opts ...Option) (item *Item, err error) {
options := newOptions(opts...)
err = c.withKeyAddr(key, func(addr net.Addr) error {
return c.getFromAddr(addr, []string{key}, func(it *Item) { item = it })
return c.getFromAddr(addr, []string{key}, options, func(it *Item) { item = it })
})
if err == nil && item == nil {
err = ErrCacheMiss
@ -373,7 +363,7 @@ func (c *Client) withKeyRw(key string, fn func(*bufio.ReadWriter) error) error {
})
}
func (c *Client) getFromAddr(addr net.Addr, keys []string, cb func(*Item)) error {
func (c *Client) getFromAddr(addr net.Addr, keys []string, opts *Options, cb func(*Item)) error {
return c.withAddrRw(addr, func(rw *bufio.ReadWriter) error {
if _, err := fmt.Fprintf(rw, "gets %s\r\n", strings.Join(keys, " ")); err != nil {
return err
@ -381,7 +371,7 @@ func (c *Client) getFromAddr(addr net.Addr, keys []string, cb func(*Item)) error
if err := rw.Flush(); err != nil {
return err
}
if err := c.parseGetResponse(rw.Reader, cb); err != nil {
if err := c.parseGetResponse(rw.Reader, opts, cb); err != nil {
return err
}
return nil
@ -465,7 +455,9 @@ func (c *Client) touchFromAddr(addr net.Addr, keys []string, expiration int32) e
// items may have fewer elements than the input slice, due to memcache
// cache misses. Each key must be at most 250 bytes in length.
// If no error is returned, the returned map will also be non-nil.
func (c *Client) GetMulti(keys []string) (map[string]*Item, error) {
func (c *Client) GetMulti(keys []string, opts ...Option) (map[string]*Item, error) {
options := newOptions(opts...)
var lk sync.Mutex
m := make(map[string]*Item)
addItemToMap := func(it *Item) {
@ -489,12 +481,12 @@ func (c *Client) GetMulti(keys []string) (map[string]*Item, error) {
ch := make(chan error, buffered)
for addr, keys := range keyMap {
go func(addr net.Addr, keys []string) {
ch <- c.getFromAddr(addr, keys, addItemToMap)
ch <- c.getFromAddr(addr, keys, options, addItemToMap)
}(addr, keys)
}
var err error
for _ = range keyMap {
for range keyMap {
if ge := <-ch; ge != nil {
err = ge
}
@ -504,7 +496,7 @@ func (c *Client) GetMulti(keys []string) (map[string]*Item, error) {
// parseGetResponse reads a GET response from r and calls cb for each
// read and allocated Item
func (c *Client) parseGetResponse(r *bufio.Reader, cb func(*Item)) error {
func (c *Client) parseGetResponse(r *bufio.Reader, opts *Options, cb func(*Item)) error {
for {
line, err := r.ReadSlice('\n')
if err != nil {
@ -519,26 +511,15 @@ func (c *Client) parseGetResponse(r *bufio.Reader, cb func(*Item)) error {
return err
}
buffSize := size + 2
if c.Pool != nil {
v, err := c.Pool.Get(buffSize)
if err != nil {
return err
}
it.Value = (*v)[:buffSize]
} else {
it.Value = make([]byte, buffSize)
}
buff := opts.Alloc.Get(buffSize)
it.Value = (*buff)[:buffSize]
_, err = io.ReadFull(r, it.Value)
if err != nil {
if c.Pool != nil {
c.Pool.Put(&it.Value)
}
opts.Alloc.Put(buff)
return err
}
if !bytes.HasSuffix(it.Value, crlf) {
if c.Pool != nil {
c.Pool.Put(&it.Value)
}
opts.Alloc.Put(buff)
return fmt.Errorf("memcache: corrupt get result read")
}
it.Value = it.Value[:size]
@ -552,7 +533,7 @@ func scanGetResponseLine(line []byte, it *Item) (size int, err error) {
errf := func(line []byte) (int, error) {
return -1, fmt.Errorf("memcache: unexpected line in get response: %q", line)
}
if !bytes.HasPrefix(line, []byte("VALUE ")) || !bytes.HasSuffix(line, []byte("\r\n")) {
if !bytes.HasPrefix(line, valuePrefix) || !bytes.HasSuffix(line, []byte("\r\n")) {
return errf(line)
}
s := string(line[6 : len(line)-2])

@ -0,0 +1,59 @@
package memcache
var nopAllocator = &defaultAllocator{}
func newOptions(opts ...Option) *Options {
o := &Options{
Alloc: nopAllocator,
}
for _, opt := range opts {
opt(o)
}
return o
}
// Options are used to modify the behavior of an individual Get or GetMulti
// call made by the Client. They are constructed by applying Option callbacks
// passed to a Client method to a default Options instance.
type Options struct {
Alloc Allocator
}
// Option is a callback used to modify the Options that a particular Client
// method uses.
type Option func(opts *Options)
// WithAllocator creates a new Option that makes use of a specific memory Allocator
// for result values (Item.Value) loaded from memcached.
func WithAllocator(alloc Allocator) Option {
return func(opts *Options) {
opts.Alloc = alloc
}
}
// Allocator allows memory for memcached result values (Item.Value) to be managed by
// callers of the Client instead of by the Client itself. For example, this can be
// used by callers to implement arena-style memory management. The default implementation
// used, when not otherwise overridden, uses `make` and relies on GC for cleanup.
type Allocator interface {
// Get returns a byte slice with at least sz capacity. Length of the slice is
// not guaranteed and so must be asserted by callers (the Client).
Get(sz int) *[]byte
// Put returns the byte slice to the underlying allocator. The Client will
// only call this method during error handling when allocated values are not
// returned to the caller as cache results.
Put(b *[]byte)
}
type defaultAllocator struct{}
func (d defaultAllocator) Get(sz int) *[]byte {
b := make([]byte, sz)
return &b
}
func (d defaultAllocator) Put(_ *[]byte) {
// no-op
}

10
vendor/modules.txt vendored

@ -678,7 +678,7 @@ github.com/gorilla/websocket
# github.com/grafana/cloudflare-go v0.0.0-20230110200409-c627cf6792f2
## explicit; go 1.17
github.com/grafana/cloudflare-go
# github.com/grafana/dskit v0.0.0-20221212120341-3e308a49441b
# github.com/grafana/dskit v0.0.0-20230109170026-7242706251b9
## explicit; go 1.18
github.com/grafana/dskit/backoff
github.com/grafana/dskit/concurrency
@ -688,6 +688,7 @@ github.com/grafana/dskit/grpcclient
github.com/grafana/dskit/grpcencoding/snappy
github.com/grafana/dskit/grpcutil
github.com/grafana/dskit/internal/math
github.com/grafana/dskit/internal/slices
github.com/grafana/dskit/kv
github.com/grafana/dskit/kv/codec
github.com/grafana/dskit/kv/consul
@ -700,7 +701,6 @@ github.com/grafana/dskit/netutil
github.com/grafana/dskit/ring
github.com/grafana/dskit/ring/client
github.com/grafana/dskit/ring/shard
github.com/grafana/dskit/ring/util
github.com/grafana/dskit/runtimeconfig
github.com/grafana/dskit/services
github.com/grafana/dskit/spanlogger
@ -708,8 +708,8 @@ github.com/grafana/dskit/tenant
# github.com/grafana/go-gelf/v2 v2.0.1
## explicit; go 1.17
github.com/grafana/go-gelf/v2/gelf
# github.com/grafana/gomemcache v0.0.0-20221213170046-b5da8a745d41
## explicit; go 1.12
# github.com/grafana/gomemcache v0.0.0-20230105173749-11f792309e1f
## explicit; go 1.18
github.com/grafana/gomemcache/memcache
# github.com/grafana/regexp v0.0.0-20221005093135-b4c2bcb0a4b6
## explicit; go 1.17
@ -1100,8 +1100,6 @@ github.com/prometheus/prometheus/web/api/v1
# github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
## explicit
github.com/rcrowley/go-metrics
# github.com/rogpeppe/go-internal v1.9.0
## explicit; go 1.17
# github.com/rs/xid v1.4.0
## explicit; go 1.12
github.com/rs/xid

Loading…
Cancel
Save