mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 18:51:59 +00:00
Merge 431199f6f2 into cff1669bc1
This commit is contained in:
commit
2f96496c8b
@ -110,5 +110,5 @@ func NewDiagnosticsHandler(baseLogger log.Logger, next http.Handler, redisCache
|
||||
}
|
||||
|
||||
func healthz(ctx context.Context, cache redispool.KeyValue) error {
|
||||
return cache.WithContext(ctx).Ping()
|
||||
return cache.Ping(ctx)
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ func (r *RepositoryResolver) RecordedCommands(ctx context.Context, args *Recorde
|
||||
return gqlutil.NewSliceConnectionResolver([]RecordedCommandResolver{}, 0, currentEnd), nil
|
||||
}
|
||||
store := rcache.NewFIFOList(redispool.Cache, wrexec.GetFIFOListKey(r.Name()), recordingConf.Size)
|
||||
empty, err := store.IsEmpty()
|
||||
empty, err := store.IsEmpty(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -67,7 +67,7 @@ func (r *RepositoryResolver) RecordedCommands(ctx context.Context, args *Recorde
|
||||
return nil, err
|
||||
}
|
||||
|
||||
size, err := store.Size()
|
||||
size, err := store.Size(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ func (r *slowRequestConnectionResolver) fetch(ctx context.Context) ([]*types.Slo
|
||||
r.err = err
|
||||
}
|
||||
r.reqs, r.err = getSlowRequestsAfter(ctx, slowRequestRedisFIFOList, n, r.perPage)
|
||||
size, err := slowRequestRedisFIFOList.Size()
|
||||
size, err := slowRequestRedisFIFOList.Size(ctx)
|
||||
if err != nil {
|
||||
r.err = errors.Append(r.err, err)
|
||||
} else {
|
||||
|
||||
@ -460,7 +460,7 @@ func waitForRedis(logger sglog.Logger, kv redispool.KeyValue) {
|
||||
var err error
|
||||
for {
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
err = kv.Ping()
|
||||
err = kv.Ping(context.Background())
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -173,7 +173,8 @@ func (m *Recorder) saveRun(jobName string, routineName string, hostName string,
|
||||
}
|
||||
|
||||
// Save run
|
||||
err = getRecentRuns(m.rcache, jobName, routineName, hostName).Insert(runJson)
|
||||
// TODO(multi-tenant): Remove context.Background()
|
||||
err = getRecentRuns(m.rcache, jobName, routineName, hostName).Insert(context.Background(), runJson)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "save run")
|
||||
}
|
||||
|
||||
@ -118,7 +118,7 @@ func redisLoggerMiddleware() Middleware {
|
||||
|
||||
go func() {
|
||||
// Save new item
|
||||
if err := outboundRequestsRedisFIFOList.Insert(logItemJson); err != nil {
|
||||
if err := outboundRequestsRedisFIFOList.Insert(req.Context(), logItemJson); err != nil {
|
||||
// Log would get upset if we created a logger at init time → create logger on the fly
|
||||
log.Scoped("redisLoggerMiddleware").Error("insert log item", log.Error(err))
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ go_library(
|
||||
deps = [
|
||||
"//internal/conf",
|
||||
"//internal/redispool",
|
||||
"//internal/tenant",
|
||||
"//internal/timeutil",
|
||||
"//lib/errors",
|
||||
"@com_github_gomodule_redigo//redis",
|
||||
|
||||
@ -18,6 +18,7 @@ import (
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/conf"
|
||||
"github.com/sourcegraph/sourcegraph/internal/redispool"
|
||||
"github.com/sourcegraph/sourcegraph/internal/tenant"
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
)
|
||||
|
||||
@ -498,11 +499,12 @@ type TB interface {
|
||||
func SetupForTest(t TB) {
|
||||
t.Helper()
|
||||
|
||||
ctx := tenant.TestContext()
|
||||
testStore = redispool.NewTestKeyValue()
|
||||
|
||||
// If we are not on CI, skip the test if our redis connection fails.
|
||||
if os.Getenv("CI") == "" {
|
||||
if err := testStore.Ping(); err != nil {
|
||||
if err := testStore.Ping(ctx); err != nil {
|
||||
t.Skip("could not connect to redis", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ go_library(
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
"//internal/redispool",
|
||||
"//internal/tenant",
|
||||
"//lib/errors",
|
||||
"@com_github_gomodule_redigo//redis",
|
||||
"@com_github_inconshreveable_log15//:log15",
|
||||
@ -30,6 +31,7 @@ go_test(
|
||||
"requires-network",
|
||||
],
|
||||
deps = [
|
||||
"//internal/tenant",
|
||||
"@com_github_stretchr_testify//assert",
|
||||
"@com_github_stretchr_testify//require",
|
||||
],
|
||||
|
||||
@ -37,7 +37,7 @@ func NewFIFOListDynamic(kv redispool.KeyValue, key string, size func() int) *FIF
|
||||
}
|
||||
|
||||
// Insert b in the cache and drops the oldest inserted item if the size exceeds the configured limit.
|
||||
func (l *FIFOList) Insert(b []byte) error {
|
||||
func (l *FIFOList) Insert(ctx context.Context, b []byte) error {
|
||||
if !utf8.Valid(b) {
|
||||
return errors.Newf("rcache: keys must be valid utf8", "key", b)
|
||||
}
|
||||
@ -47,28 +47,28 @@ func (l *FIFOList) Insert(b []byte) error {
|
||||
// disabling.
|
||||
maxSize := l.MaxSize()
|
||||
if maxSize == 0 {
|
||||
if err := l.kv().LTrim(key, 0, 0); err != nil {
|
||||
if err := l.kv().LTrim(ctx, key, 0, 0); err != nil {
|
||||
return errors.Wrap(err, "failed to execute redis command LTRIM")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// O(1) because we're just adding a single element.
|
||||
if err := l.kv().LPush(key, b); err != nil {
|
||||
if err := l.kv().LPush(ctx, key, b); err != nil {
|
||||
return errors.Wrap(err, "failed to execute redis command LPUSH")
|
||||
}
|
||||
|
||||
// O(1) because the average case if just about dropping the last element.
|
||||
if err := l.kv().LTrim(key, 0, maxSize-1); err != nil {
|
||||
if err := l.kv().LTrim(ctx, key, 0, maxSize-1); err != nil {
|
||||
return errors.Wrap(err, "failed to execute redis command LTRIM")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Size returns the number of elements in the list.
|
||||
func (l *FIFOList) Size() (int, error) {
|
||||
func (l *FIFOList) Size(ctx context.Context) (int, error) {
|
||||
key := l.globalPrefixKey()
|
||||
n, err := l.kv().LLen(key)
|
||||
n, err := l.kv().LLen(ctx, key)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "failed to execute redis command LLEN")
|
||||
}
|
||||
@ -76,8 +76,8 @@ func (l *FIFOList) Size() (int, error) {
|
||||
}
|
||||
|
||||
// IsEmpty returns true if the number of elements in the list is 0.
|
||||
func (l *FIFOList) IsEmpty() (bool, error) {
|
||||
size, err := l.Size()
|
||||
func (l *FIFOList) IsEmpty(ctx context.Context) (bool, error) {
|
||||
size, err := l.Size(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -110,7 +110,7 @@ func (l *FIFOList) Slice(ctx context.Context, from, to int) ([][]byte, error) {
|
||||
}
|
||||
|
||||
key := l.globalPrefixKey()
|
||||
bs, err := l.kv().WithContext(ctx).LRange(key, from, to).ByteSlices()
|
||||
bs, err := l.kv().LRange(ctx, key, from, to).ByteSlices()
|
||||
if err != nil {
|
||||
// Return ctx error if it expired
|
||||
if ctx.Err() != nil {
|
||||
|
||||
@ -8,9 +8,12 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/tenant"
|
||||
)
|
||||
|
||||
func Test_FIFOList_All_OK(t *testing.T) {
|
||||
ctx := tenant.TestContext()
|
||||
kv := SetupForTest(t)
|
||||
|
||||
type testcase struct {
|
||||
@ -57,7 +60,7 @@ func Test_FIFOList_All_OK(t *testing.T) {
|
||||
r := NewFIFOList(kv, c.key, c.size)
|
||||
t.Run(fmt.Sprintf("size %d with %d entries", c.size, len(c.inserts)), func(t *testing.T) {
|
||||
for _, b := range c.inserts {
|
||||
if err := r.Insert(b); err != nil {
|
||||
if err := r.Insert(ctx, b); err != nil {
|
||||
t.Errorf("expected no error, got %q", err)
|
||||
}
|
||||
}
|
||||
@ -65,7 +68,7 @@ func Test_FIFOList_All_OK(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %q", err)
|
||||
}
|
||||
s, err := r.Size()
|
||||
s, err := r.Size(ctx)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %q", err)
|
||||
}
|
||||
@ -80,6 +83,7 @@ func Test_FIFOList_All_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_FIFOList_Slice_OK(t *testing.T) {
|
||||
ctx := tenant.TestContext()
|
||||
kv := SetupForTest(t)
|
||||
|
||||
type testcase struct {
|
||||
@ -146,7 +150,7 @@ func Test_FIFOList_Slice_OK(t *testing.T) {
|
||||
r := NewFIFOList(kv, c.key, c.size)
|
||||
t.Run(fmt.Sprintf("size %d with %d entries, [%d,%d]", c.size, len(c.inserts), c.from, c.to), func(t *testing.T) {
|
||||
for _, b := range c.inserts {
|
||||
if err := r.Insert(b); err != nil {
|
||||
if err := r.Insert(ctx, b); err != nil {
|
||||
t.Errorf("expected no error, got %q", err)
|
||||
}
|
||||
}
|
||||
@ -162,11 +166,12 @@ func Test_FIFOList_Slice_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_NewFIFOListDynamic(t *testing.T) {
|
||||
ctx := tenant.TestContext()
|
||||
kv := SetupForTest(t)
|
||||
maxSize := 3
|
||||
r := NewFIFOListDynamic(kv, "a", func() int { return maxSize })
|
||||
for range 10 {
|
||||
err := r.Insert([]byte("a"))
|
||||
err := r.Insert(ctx, []byte("a"))
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %q", err)
|
||||
}
|
||||
@ -182,7 +187,7 @@ func Test_NewFIFOListDynamic(t *testing.T) {
|
||||
|
||||
maxSize = 2
|
||||
for range 10 {
|
||||
err := r.Insert([]byte("b"))
|
||||
err := r.Insert(ctx, []byte("b"))
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %q", err)
|
||||
}
|
||||
@ -198,9 +203,10 @@ func Test_NewFIFOListDynamic(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_FIFOListContextCancellation(t *testing.T) {
|
||||
ctx := tenant.TestContext()
|
||||
kv := SetupForTest(t)
|
||||
r := NewFIFOList(kv, "a", 3)
|
||||
err := r.Insert([]byte("a"))
|
||||
err := r.Insert(ctx, []byte("a"))
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got %q", err)
|
||||
}
|
||||
@ -213,14 +219,15 @@ func Test_FIFOListContextCancellation(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_FIFOListIsEmpty(t *testing.T) {
|
||||
ctx := tenant.TestContext()
|
||||
kv := SetupForTest(t)
|
||||
r := NewFIFOList(kv, "a", 3)
|
||||
empty, err := r.IsEmpty()
|
||||
empty, err := r.IsEmpty(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, empty)
|
||||
err = r.Insert([]byte("a"))
|
||||
err = r.Insert(ctx, []byte("a"))
|
||||
require.NoError(t, err)
|
||||
empty, err = r.IsEmpty()
|
||||
empty, err = r.IsEmpty(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, empty)
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"github.com/inconshreveable/log15" //nolint:logging // TODO move all logging to sourcegraph/log
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/redispool"
|
||||
"github.com/sourcegraph/sourcegraph/internal/tenant"
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
)
|
||||
|
||||
@ -243,6 +244,7 @@ const testAddr = "127.0.0.1:6379"
|
||||
func SetupForTest(t testing.TB) redispool.KeyValue {
|
||||
t.Helper()
|
||||
|
||||
ctx := tenant.TestContext()
|
||||
testStore = redispool.NewTestKeyValue()
|
||||
t.Cleanup(func() {
|
||||
testStore.Pool().Close()
|
||||
@ -251,7 +253,7 @@ func SetupForTest(t testing.TB) redispool.KeyValue {
|
||||
|
||||
// If we are not on CI, skip the test if our redis connection fails.
|
||||
if os.Getenv("CI") == "" {
|
||||
if err := testStore.Ping(); err != nil {
|
||||
if err := testStore.Ping(ctx); err != nil {
|
||||
t.Skip("could not connect to redis", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ go_test(
|
||||
"requires-network",
|
||||
],
|
||||
deps = [
|
||||
"//internal/tenant",
|
||||
"//lib/errors",
|
||||
"@com_github_gomodule_redigo//redis",
|
||||
"@com_github_sourcegraph_log//logtest",
|
||||
|
||||
@ -39,20 +39,22 @@ type KeyValue interface {
|
||||
HSet(key, field string, value any) error
|
||||
HDel(key, field string) Value
|
||||
|
||||
LPush(key string, value any) error
|
||||
LTrim(key string, start, stop int) error
|
||||
LLen(key string) (int, error)
|
||||
LRange(key string, start, stop int) Values
|
||||
LPush(ctx context.Context, key string, value any) error
|
||||
LTrim(ctx context.Context, key string, start, stop int) error
|
||||
LLen(ctx context.Context, key string) (int, error)
|
||||
LRange(ctx context.Context, key string, start, stop int) Values
|
||||
|
||||
// Ping checks the connection to the redis server.
|
||||
Ping() error
|
||||
Ping(ctx context.Context) error
|
||||
|
||||
// Keys returns all keys matching the glob pattern. NOTE: this command takes time
|
||||
// linear in the number of keys, and should not be run over large keyspaces.
|
||||
Keys(pattern string) ([]string, error)
|
||||
|
||||
// WithContext will return a KeyValue that should respect ctx for all
|
||||
// blocking operations.
|
||||
// WithContext will return a KeyValue that should respect ctx for all blocking operations.
|
||||
//
|
||||
// DEPRECATED: We are in the process of adding context to each individual operation (Get, Set, etc.)
|
||||
// Once that is complete, this method will be removed.
|
||||
WithContext(ctx context.Context) KeyValue
|
||||
WithLatencyRecorder(r LatencyRecorder) KeyValue
|
||||
|
||||
@ -169,33 +171,33 @@ type redisKeyValue struct {
|
||||
recorder *LatencyRecorder
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) Ping() error {
|
||||
func (r *redisKeyValue) Ping(ctx context.Context) error {
|
||||
// The 'ping' command takes no arguments
|
||||
return r.do("PING", []string{}, []any{}).err
|
||||
return r.do(ctx, "PING", []string{}, []any{}).err
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) Get(key string) Value {
|
||||
return r.doSimple("GET", key)
|
||||
return r.doWithoutContext("GET", []string{key}, []any{})
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) GetSet(key string, val any) Value {
|
||||
return r.doSimple("GETSET", key, val)
|
||||
return r.doWithoutContext("GETSET", []string{key}, []any{val})
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) MGet(keys []string) Values {
|
||||
return Values(r.do("MGET", keys, []any{}))
|
||||
return Values(r.doWithoutContext("MGET", keys, []any{}))
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) Set(key string, val any) error {
|
||||
return r.doSimple("SET", key, val).err
|
||||
return r.doWithoutContext("SET", []string{key}, []any{val}).err
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) SetEx(key string, ttlSeconds int, val any) error {
|
||||
return r.doSimple("SETEX", key, ttlSeconds, val).err
|
||||
return r.doWithoutContext("SETEX", []string{key}, []any{ttlSeconds, val}).err
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) SetNx(key string, val any) (bool, error) {
|
||||
_, err := r.doSimple("SET", key, val, "NX").String()
|
||||
_, err := r.doWithoutContext("SET", []string{key}, []any{val, "NX"}).String()
|
||||
if err == redis.ErrNil {
|
||||
return false, nil
|
||||
}
|
||||
@ -203,61 +205,62 @@ func (r *redisKeyValue) SetNx(key string, val any) (bool, error) {
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) Incr(key string) (int, error) {
|
||||
return r.doSimple("INCR", key).Int()
|
||||
return r.doWithoutContext("INCR", []string{key}, []any{}).Int()
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) Incrby(key string, value int) (int, error) {
|
||||
return r.doSimple("INCRBY", key, value).Int()
|
||||
return r.doWithoutContext("INCRBY", []string{key}, []any{value}).Int()
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) IncrByInt64(key string, value int64) (int64, error) {
|
||||
return r.doSimple("INCRBY", key, value).Int64()
|
||||
return r.doWithoutContext("INCRBY", []string{key}, []any{value}).Int64()
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) DecrByInt64(key string, value int64) (int64, error) {
|
||||
return r.doSimple("DECRBY", key, value).Int64()
|
||||
return r.doWithoutContext("DECRBY", []string{key}, []any{value}).Int64()
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) Del(key string) error {
|
||||
return r.doSimple("DEL", key).err
|
||||
return r.doWithoutContext("DEL", []string{key}, []any{}).err
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) TTL(key string) (int, error) {
|
||||
return r.doSimple("TTL", key).Int()
|
||||
return r.doWithoutContext("TTL", []string{key}, []any{}).Int()
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) Expire(key string, ttlSeconds int) error {
|
||||
return r.doSimple("EXPIRE", key, ttlSeconds).err
|
||||
return r.doWithoutContext("EXPIRE", []string{key}, []any{ttlSeconds}).err
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) HGet(key, field string) Value {
|
||||
return r.doSimple("HGET", key, field)
|
||||
return r.doWithoutContext("HGET", []string{key}, []any{field})
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) HGetAll(key string) Values {
|
||||
return Values(r.doSimple("HGETALL", key))
|
||||
return Values(r.doWithoutContext("HGETALL", []string{key}, []any{}))
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) HSet(key, field string, val any) error {
|
||||
return r.doSimple("HSET", key, field, val).err
|
||||
return r.doWithoutContext("HSET", []string{key}, []any{field, val}).err
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) HDel(key, field string) Value {
|
||||
return r.doSimple("HDEL", key, field)
|
||||
return r.doWithoutContext("HDEL", []string{key}, []any{field})
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) LPush(key string, value any) error {
|
||||
return r.doSimple("LPUSH", key, value).err
|
||||
func (r *redisKeyValue) LPush(ctx context.Context, key string, value any) error {
|
||||
return r.do(ctx, "LPUSH", []string{key}, []any{value}).err
|
||||
}
|
||||
func (r *redisKeyValue) LTrim(key string, start, stop int) error {
|
||||
return r.doSimple("LTRIM", key, start, stop).err
|
||||
func (r *redisKeyValue) LTrim(ctx context.Context, key string, start, stop int) error {
|
||||
return r.do(ctx, "LTRIM", []string{key}, []any{start, stop}).err
|
||||
}
|
||||
func (r *redisKeyValue) LLen(key string) (int, error) {
|
||||
raw := r.doSimple("LLEN", key)
|
||||
func (r *redisKeyValue) LLen(ctx context.Context, key string) (int, error) {
|
||||
raw := r.do(ctx, "LLEN", []string{key}, []any{})
|
||||
return redis.Int(raw.reply, raw.err)
|
||||
}
|
||||
func (r *redisKeyValue) LRange(key string, start, stop int) Values {
|
||||
return Values(r.doSimple("LRANGE", key, start, stop))
|
||||
|
||||
func (r *redisKeyValue) LRange(ctx context.Context, key string, start, stop int) Values {
|
||||
return Values(r.do(ctx, "LRANGE", []string{key}, []any{start, stop}))
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) WithContext(ctx context.Context) KeyValue {
|
||||
@ -286,27 +289,21 @@ func (r *redisKeyValue) WithPrefix(prefix string) KeyValue {
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) Keys(pattern string) ([]string, error) {
|
||||
return Values(r.doSimple("KEYS", pattern)).Strings()
|
||||
return Values(r.doWithoutContext("KEYS", []string{pattern}, []any{})).Strings()
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) Pool() *redis.Pool {
|
||||
return r.pool
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) doSimple(commandName string, key string, args ...any) Value {
|
||||
return r.do(commandName, []string{key}, args)
|
||||
func (r *redisKeyValue) doWithoutContext(commandName string, keys []string, args []any) Value {
|
||||
return r.do(context.Background(), commandName, keys, args)
|
||||
}
|
||||
|
||||
func (r *redisKeyValue) do(commandName string, keys []string, args []any) Value {
|
||||
var c redis.Conn
|
||||
if r.ctx != nil {
|
||||
var err error
|
||||
c, err = r.pool.GetContext(r.ctx)
|
||||
if err != nil {
|
||||
return Value{err: err}
|
||||
}
|
||||
} else {
|
||||
c = r.pool.Get()
|
||||
func (r *redisKeyValue) do(ctx context.Context, commandName string, keys []string, args []any) Value {
|
||||
c, err := r.pool.GetContext(ctx)
|
||||
if err != nil {
|
||||
return Value{err: err}
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
|
||||
@ -11,11 +11,13 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/redispool"
|
||||
"github.com/sourcegraph/sourcegraph/internal/tenant"
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
)
|
||||
|
||||
func TestKeyValue(t *testing.T) {
|
||||
kv := redisKeyValueForTest(t)
|
||||
ctx := tenant.TestContext()
|
||||
errWrongType := errors.New("WRONGTYPE")
|
||||
|
||||
// "strings" is the name of the classic group of commands in redis (get, set, ttl, etc). We call it classic since that is less confusing.
|
||||
@ -127,53 +129,53 @@ func TestKeyValue(t *testing.T) {
|
||||
|
||||
// Redis behaviour on unset lists
|
||||
require.ListLen(kv, "list-unset-0", 0)
|
||||
require.AllEqual(kv.LRange("list-unset-1", 0, 10), bytes())
|
||||
require.Works(kv.LTrim("list-unset-2", 0, 10))
|
||||
require.AllEqual(kv.LRange(ctx, "list-unset-1", 0, 10), bytes())
|
||||
require.Works(kv.LTrim(ctx, "list-unset-2", 0, 10))
|
||||
|
||||
require.Works(kv.LPush("list", "4"))
|
||||
require.Works(kv.LPush("list", "3"))
|
||||
require.Works(kv.LPush("list", "2"))
|
||||
require.Works(kv.LPush("list", "1"))
|
||||
require.Works(kv.LPush("list", "0"))
|
||||
require.Works(kv.LPush(ctx, "list", "4"))
|
||||
require.Works(kv.LPush(ctx, "list", "3"))
|
||||
require.Works(kv.LPush(ctx, "list", "2"))
|
||||
require.Works(kv.LPush(ctx, "list", "1"))
|
||||
require.Works(kv.LPush(ctx, "list", "0"))
|
||||
|
||||
// Different ways we get the full list back
|
||||
require.AllEqual(kv.LRange("list", 0, 10), []string{"0", "1", "2", "3", "4"})
|
||||
require.AllEqual(kv.LRange("list", 0, 10), bytes("0", "1", "2", "3", "4"))
|
||||
require.AllEqual(kv.LRange("list", 0, -1), bytes("0", "1", "2", "3", "4"))
|
||||
require.AllEqual(kv.LRange("list", -5, -1), bytes("0", "1", "2", "3", "4"))
|
||||
require.AllEqual(kv.LRange("list", 0, 4), bytes("0", "1", "2", "3", "4"))
|
||||
require.AllEqual(kv.LRange(ctx, "list", 0, 10), []string{"0", "1", "2", "3", "4"})
|
||||
require.AllEqual(kv.LRange(ctx, "list", 0, 10), bytes("0", "1", "2", "3", "4"))
|
||||
require.AllEqual(kv.LRange(ctx, "list", 0, -1), bytes("0", "1", "2", "3", "4"))
|
||||
require.AllEqual(kv.LRange(ctx, "list", -5, -1), bytes("0", "1", "2", "3", "4"))
|
||||
require.AllEqual(kv.LRange(ctx, "list", 0, 4), bytes("0", "1", "2", "3", "4"))
|
||||
|
||||
// If stop < start we return nothing
|
||||
require.AllEqual(kv.LRange("list", -1, 0), bytes())
|
||||
require.AllEqual(kv.LRange(ctx, "list", -1, 0), bytes())
|
||||
|
||||
// Subsets
|
||||
require.AllEqual(kv.LRange("list", 1, 3), bytes("1", "2", "3"))
|
||||
require.AllEqual(kv.LRange("list", 1, -2), bytes("1", "2", "3"))
|
||||
require.AllEqual(kv.LRange("list", -4, 3), bytes("1", "2", "3"))
|
||||
require.AllEqual(kv.LRange("list", -4, -2), bytes("1", "2", "3"))
|
||||
require.AllEqual(kv.LRange(ctx, "list", 1, 3), bytes("1", "2", "3"))
|
||||
require.AllEqual(kv.LRange(ctx, "list", 1, -2), bytes("1", "2", "3"))
|
||||
require.AllEqual(kv.LRange(ctx, "list", -4, 3), bytes("1", "2", "3"))
|
||||
require.AllEqual(kv.LRange(ctx, "list", -4, -2), bytes("1", "2", "3"))
|
||||
|
||||
// Trim noop
|
||||
require.Works(kv.LTrim("list", 0, 10))
|
||||
require.AllEqual(kv.LRange("list", 0, 4), bytes("0", "1", "2", "3", "4"))
|
||||
require.Works(kv.LTrim(ctx, "list", 0, 10))
|
||||
require.AllEqual(kv.LRange(ctx, "list", 0, 4), bytes("0", "1", "2", "3", "4"))
|
||||
|
||||
// Trim popback
|
||||
require.Works(kv.LTrim("list", 0, -2))
|
||||
require.AllEqual(kv.LRange("list", 0, 4), bytes("0", "1", "2", "3"))
|
||||
require.Works(kv.LTrim(ctx, "list", 0, -2))
|
||||
require.AllEqual(kv.LRange(ctx, "list", 0, 4), bytes("0", "1", "2", "3"))
|
||||
require.ListLen(kv, "list", 4)
|
||||
|
||||
// Trim popfront
|
||||
require.Works(kv.LTrim("list", 1, 10))
|
||||
require.AllEqual(kv.LRange("list", 0, 4), bytes("1", "2", "3"))
|
||||
require.Works(kv.LTrim(ctx, "list", 1, 10))
|
||||
require.AllEqual(kv.LRange(ctx, "list", 0, 4), bytes("1", "2", "3"))
|
||||
require.ListLen(kv, "list", 3)
|
||||
|
||||
// Trim all
|
||||
require.Works(kv.LTrim("list", -1, -2))
|
||||
require.AllEqual(kv.LRange("list", 0, 4), bytes())
|
||||
require.Works(kv.LTrim(ctx, "list", -1, -2))
|
||||
require.AllEqual(kv.LRange(ctx, "list", 0, 4), bytes())
|
||||
require.ListLen(kv, "list", 0)
|
||||
|
||||
require.Works(kv.LPush("funky2D", []byte{100, 255}))
|
||||
require.Works(kv.LPush("funky2D", []byte{0, 10}))
|
||||
require.AllEqual(kv.LRange("funky2D", 0, -1), [][]byte{{0, 10}, {100, 255}})
|
||||
require.Works(kv.LPush(ctx, "funky2D", []byte{100, 255}))
|
||||
require.Works(kv.LPush(ctx, "funky2D", []byte{0, 10}))
|
||||
require.AllEqual(kv.LRange(ctx, "funky2D", 0, -1), [][]byte{{0, 10}, {100, 255}})
|
||||
})
|
||||
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
@ -191,9 +193,9 @@ func TestKeyValue(t *testing.T) {
|
||||
|
||||
// List group. Once empty we should be able to doSimple a Get without a
|
||||
// wrongtype error.
|
||||
require.Works(kv.LPush("empty-list", "here today gone tomorrow"))
|
||||
require.Works(kv.LPush(ctx, "empty-list", "here today gone tomorrow"))
|
||||
require.Equal(kv.Get("empty-list"), errWrongType)
|
||||
require.Works(kv.LTrim("empty-list", -1, -2))
|
||||
require.Works(kv.LTrim(ctx, "empty-list", -1, -2))
|
||||
require.Equal(kv.Get("empty-list"), nil)
|
||||
})
|
||||
|
||||
@ -285,20 +287,20 @@ func TestKeyValue(t *testing.T) {
|
||||
require := require{TB: t}
|
||||
|
||||
// Hash mutations keep expire
|
||||
require.Works(kv.LPush("expires-unset-list", "1"))
|
||||
require.Works(kv.LPush("expires-set-list", "1"))
|
||||
require.Works(kv.LPush(ctx, "expires-unset-list", "1"))
|
||||
require.Works(kv.LPush(ctx, "expires-set-list", "1"))
|
||||
require.Works(kv.Expire("expires-set-list", 60))
|
||||
require.TTL(kv, "expires-unset-list", -1)
|
||||
require.TTL(kv, "expires-set-list", 60)
|
||||
require.AllEqual(kv.LRange("expires-unset-list", 0, -1), []string{"1"})
|
||||
require.AllEqual(kv.LRange("expires-set-list", 0, -1), []string{"1"})
|
||||
require.AllEqual(kv.LRange(ctx, "expires-unset-list", 0, -1), []string{"1"})
|
||||
require.AllEqual(kv.LRange(ctx, "expires-set-list", 0, -1), []string{"1"})
|
||||
|
||||
require.Works(kv.LPush("expires-unset-list", "2"))
|
||||
require.Works(kv.LPush("expires-set-list", "2"))
|
||||
require.Works(kv.LPush(ctx, "expires-unset-list", "2"))
|
||||
require.Works(kv.LPush(ctx, "expires-set-list", "2"))
|
||||
require.TTL(kv, "expires-unset-list", -1)
|
||||
require.TTL(kv, "expires-set-list", 60)
|
||||
require.AllEqual(kv.LRange("expires-unset-list", 0, -1), []string{"2", "1"})
|
||||
require.AllEqual(kv.LRange("expires-set-list", 0, -1), []string{"2", "1"})
|
||||
require.AllEqual(kv.LRange(ctx, "expires-unset-list", 0, -1), []string{"2", "1"})
|
||||
require.AllEqual(kv.LRange(ctx, "expires-set-list", 0, -1), []string{"2", "1"})
|
||||
|
||||
// Check expiration happens on hashes
|
||||
require.Works(kv.Expire("expires-set-list", 1))
|
||||
@ -320,7 +322,7 @@ func TestKeyValue(t *testing.T) {
|
||||
|
||||
require.Works(kv.Set("wrongtype-string", "1"))
|
||||
require.Works(kv.HSet("wrongtype-hash", "1", "1"))
|
||||
require.Works(kv.LPush("wrongtype-list", "1"))
|
||||
require.Works(kv.LPush(ctx, "wrongtype-list", "1"))
|
||||
|
||||
for _, k := range []string{"wrongtype-string", "wrongtype-hash", "wrongtype-list"} {
|
||||
// Ensure we fail Get when used against non string group
|
||||
@ -341,11 +343,11 @@ func TestKeyValue(t *testing.T) {
|
||||
|
||||
// Ensure we fail lists when used against non lists.
|
||||
if k != "wrongtype-list" {
|
||||
_, err := kv.LLen(k)
|
||||
_, err := kv.LLen(ctx, k)
|
||||
requireWrongType(err)
|
||||
requireWrongType(kv.LPush(k, "1"))
|
||||
requireWrongType(kv.LTrim(k, 1, 2))
|
||||
require.Equal(redispool.Value(kv.LRange(k, 1, 2)), errWrongType)
|
||||
requireWrongType(kv.LPush(ctx, k, "1"))
|
||||
requireWrongType(kv.LTrim(ctx, k, 1, 2))
|
||||
require.Equal(redispool.Value(kv.LRange(ctx, k, 1, 2)), errWrongType)
|
||||
}
|
||||
|
||||
// Ensure we can always override values with set
|
||||
@ -357,13 +359,13 @@ func TestKeyValue(t *testing.T) {
|
||||
t.Run("ping", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require{TB: t}
|
||||
require.Works(kv.Ping())
|
||||
require.Works(kv.Ping(ctx))
|
||||
|
||||
brokenKv := redispool.NewKeyValue("nonexistent-redis-server:6379", &redis.Pool{
|
||||
MaxIdle: 3,
|
||||
IdleTimeout: 5 * time.Second,
|
||||
})
|
||||
if brokenKv.Ping() == nil {
|
||||
if brokenKv.Ping(ctx) == nil {
|
||||
t.Fatalf("ping: expected error, but did not receive one")
|
||||
}
|
||||
})
|
||||
@ -416,12 +418,13 @@ func TestKeyValueWithPrefix(t *testing.T) {
|
||||
func redisKeyValueForTest(t *testing.T) redispool.KeyValue {
|
||||
t.Helper()
|
||||
|
||||
ctx := tenant.TestContext()
|
||||
kv := redispool.NewTestKeyValue()
|
||||
prefix := "__test__" + t.Name()
|
||||
|
||||
// If we are not on CI, skip the test if our redis connection fails.
|
||||
if os.Getenv("CI") == "" {
|
||||
if err := kv.Ping(); err != nil {
|
||||
if err := kv.Ping(ctx); err != nil {
|
||||
t.Skip("could not connect to redis", err)
|
||||
}
|
||||
}
|
||||
@ -526,7 +529,7 @@ func (t require) AllEqual(got redispool.Values, want any) {
|
||||
}
|
||||
func (t require) ListLen(kv redispool.KeyValue, key string, want int) {
|
||||
t.Helper()
|
||||
got, err := kv.LLen(key)
|
||||
got, err := kv.LLen(tenant.TestContext(), key)
|
||||
if err != nil {
|
||||
t.Fatal("LLen returned error", err)
|
||||
}
|
||||
|
||||
@ -170,22 +170,22 @@ func NewMockKeyValue() *MockKeyValue {
|
||||
},
|
||||
},
|
||||
LLenFunc: &KeyValueLLenFunc{
|
||||
defaultHook: func(string) (r0 int, r1 error) {
|
||||
defaultHook: func(context.Context, string) (r0 int, r1 error) {
|
||||
return
|
||||
},
|
||||
},
|
||||
LPushFunc: &KeyValueLPushFunc{
|
||||
defaultHook: func(string, interface{}) (r0 error) {
|
||||
defaultHook: func(context.Context, string, interface{}) (r0 error) {
|
||||
return
|
||||
},
|
||||
},
|
||||
LRangeFunc: &KeyValueLRangeFunc{
|
||||
defaultHook: func(string, int, int) (r0 Values) {
|
||||
defaultHook: func(context.Context, string, int, int) (r0 Values) {
|
||||
return
|
||||
},
|
||||
},
|
||||
LTrimFunc: &KeyValueLTrimFunc{
|
||||
defaultHook: func(string, int, int) (r0 error) {
|
||||
defaultHook: func(context.Context, string, int, int) (r0 error) {
|
||||
return
|
||||
},
|
||||
},
|
||||
@ -195,7 +195,7 @@ func NewMockKeyValue() *MockKeyValue {
|
||||
},
|
||||
},
|
||||
PingFunc: &KeyValuePingFunc{
|
||||
defaultHook: func() (r0 error) {
|
||||
defaultHook: func(context.Context) (r0 error) {
|
||||
return
|
||||
},
|
||||
},
|
||||
@ -312,22 +312,22 @@ func NewStrictMockKeyValue() *MockKeyValue {
|
||||
},
|
||||
},
|
||||
LLenFunc: &KeyValueLLenFunc{
|
||||
defaultHook: func(string) (int, error) {
|
||||
defaultHook: func(context.Context, string) (int, error) {
|
||||
panic("unexpected invocation of MockKeyValue.LLen")
|
||||
},
|
||||
},
|
||||
LPushFunc: &KeyValueLPushFunc{
|
||||
defaultHook: func(string, interface{}) error {
|
||||
defaultHook: func(context.Context, string, interface{}) error {
|
||||
panic("unexpected invocation of MockKeyValue.LPush")
|
||||
},
|
||||
},
|
||||
LRangeFunc: &KeyValueLRangeFunc{
|
||||
defaultHook: func(string, int, int) Values {
|
||||
defaultHook: func(context.Context, string, int, int) Values {
|
||||
panic("unexpected invocation of MockKeyValue.LRange")
|
||||
},
|
||||
},
|
||||
LTrimFunc: &KeyValueLTrimFunc{
|
||||
defaultHook: func(string, int, int) error {
|
||||
defaultHook: func(context.Context, string, int, int) error {
|
||||
panic("unexpected invocation of MockKeyValue.LTrim")
|
||||
},
|
||||
},
|
||||
@ -337,7 +337,7 @@ func NewStrictMockKeyValue() *MockKeyValue {
|
||||
},
|
||||
},
|
||||
PingFunc: &KeyValuePingFunc{
|
||||
defaultHook: func() error {
|
||||
defaultHook: func(context.Context) error {
|
||||
panic("unexpected invocation of MockKeyValue.Ping")
|
||||
},
|
||||
},
|
||||
@ -1832,23 +1832,23 @@ func (c KeyValueKeysFuncCall) Results() []interface{} {
|
||||
// KeyValueLLenFunc describes the behavior when the LLen method of the
|
||||
// parent MockKeyValue instance is invoked.
|
||||
type KeyValueLLenFunc struct {
|
||||
defaultHook func(string) (int, error)
|
||||
hooks []func(string) (int, error)
|
||||
defaultHook func(context.Context, string) (int, error)
|
||||
hooks []func(context.Context, string) (int, error)
|
||||
history []KeyValueLLenFuncCall
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// LLen delegates to the next hook function in the queue and stores the
|
||||
// parameter and result values of this invocation.
|
||||
func (m *MockKeyValue) LLen(v0 string) (int, error) {
|
||||
r0, r1 := m.LLenFunc.nextHook()(v0)
|
||||
m.LLenFunc.appendCall(KeyValueLLenFuncCall{v0, r0, r1})
|
||||
func (m *MockKeyValue) LLen(v0 context.Context, v1 string) (int, error) {
|
||||
r0, r1 := m.LLenFunc.nextHook()(v0, v1)
|
||||
m.LLenFunc.appendCall(KeyValueLLenFuncCall{v0, v1, r0, r1})
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SetDefaultHook sets function that is called when the LLen method of the
|
||||
// parent MockKeyValue instance is invoked and the hook queue is empty.
|
||||
func (f *KeyValueLLenFunc) SetDefaultHook(hook func(string) (int, error)) {
|
||||
func (f *KeyValueLLenFunc) SetDefaultHook(hook func(context.Context, string) (int, error)) {
|
||||
f.defaultHook = hook
|
||||
}
|
||||
|
||||
@ -1856,7 +1856,7 @@ func (f *KeyValueLLenFunc) SetDefaultHook(hook func(string) (int, error)) {
|
||||
// LLen method of the parent MockKeyValue instance invokes the hook at the
|
||||
// front of the queue and discards it. After the queue is empty, the default
|
||||
// hook function is invoked for any future action.
|
||||
func (f *KeyValueLLenFunc) PushHook(hook func(string) (int, error)) {
|
||||
func (f *KeyValueLLenFunc) PushHook(hook func(context.Context, string) (int, error)) {
|
||||
f.mutex.Lock()
|
||||
f.hooks = append(f.hooks, hook)
|
||||
f.mutex.Unlock()
|
||||
@ -1865,19 +1865,19 @@ func (f *KeyValueLLenFunc) PushHook(hook func(string) (int, error)) {
|
||||
// SetDefaultReturn calls SetDefaultHook with a function that returns the
|
||||
// given values.
|
||||
func (f *KeyValueLLenFunc) SetDefaultReturn(r0 int, r1 error) {
|
||||
f.SetDefaultHook(func(string) (int, error) {
|
||||
f.SetDefaultHook(func(context.Context, string) (int, error) {
|
||||
return r0, r1
|
||||
})
|
||||
}
|
||||
|
||||
// PushReturn calls PushHook with a function that returns the given values.
|
||||
func (f *KeyValueLLenFunc) PushReturn(r0 int, r1 error) {
|
||||
f.PushHook(func(string) (int, error) {
|
||||
f.PushHook(func(context.Context, string) (int, error) {
|
||||
return r0, r1
|
||||
})
|
||||
}
|
||||
|
||||
func (f *KeyValueLLenFunc) nextHook() func(string) (int, error) {
|
||||
func (f *KeyValueLLenFunc) nextHook() func(context.Context, string) (int, error) {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
||||
@ -1912,7 +1912,10 @@ func (f *KeyValueLLenFunc) History() []KeyValueLLenFuncCall {
|
||||
type KeyValueLLenFuncCall struct {
|
||||
// Arg0 is the value of the 1st argument passed to this method
|
||||
// invocation.
|
||||
Arg0 string
|
||||
Arg0 context.Context
|
||||
// Arg1 is the value of the 2nd argument passed to this method
|
||||
// invocation.
|
||||
Arg1 string
|
||||
// Result0 is the value of the 1st result returned from this method
|
||||
// invocation.
|
||||
Result0 int
|
||||
@ -1924,7 +1927,7 @@ type KeyValueLLenFuncCall struct {
|
||||
// Args returns an interface slice containing the arguments of this
|
||||
// invocation.
|
||||
func (c KeyValueLLenFuncCall) Args() []interface{} {
|
||||
return []interface{}{c.Arg0}
|
||||
return []interface{}{c.Arg0, c.Arg1}
|
||||
}
|
||||
|
||||
// Results returns an interface slice containing the results of this
|
||||
@ -1936,23 +1939,23 @@ func (c KeyValueLLenFuncCall) Results() []interface{} {
|
||||
// KeyValueLPushFunc describes the behavior when the LPush method of the
|
||||
// parent MockKeyValue instance is invoked.
|
||||
type KeyValueLPushFunc struct {
|
||||
defaultHook func(string, interface{}) error
|
||||
hooks []func(string, interface{}) error
|
||||
defaultHook func(context.Context, string, interface{}) error
|
||||
hooks []func(context.Context, string, interface{}) error
|
||||
history []KeyValueLPushFuncCall
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// LPush delegates to the next hook function in the queue and stores the
|
||||
// parameter and result values of this invocation.
|
||||
func (m *MockKeyValue) LPush(v0 string, v1 interface{}) error {
|
||||
r0 := m.LPushFunc.nextHook()(v0, v1)
|
||||
m.LPushFunc.appendCall(KeyValueLPushFuncCall{v0, v1, r0})
|
||||
func (m *MockKeyValue) LPush(v0 context.Context, v1 string, v2 interface{}) error {
|
||||
r0 := m.LPushFunc.nextHook()(v0, v1, v2)
|
||||
m.LPushFunc.appendCall(KeyValueLPushFuncCall{v0, v1, v2, r0})
|
||||
return r0
|
||||
}
|
||||
|
||||
// SetDefaultHook sets function that is called when the LPush method of the
|
||||
// parent MockKeyValue instance is invoked and the hook queue is empty.
|
||||
func (f *KeyValueLPushFunc) SetDefaultHook(hook func(string, interface{}) error) {
|
||||
func (f *KeyValueLPushFunc) SetDefaultHook(hook func(context.Context, string, interface{}) error) {
|
||||
f.defaultHook = hook
|
||||
}
|
||||
|
||||
@ -1960,7 +1963,7 @@ func (f *KeyValueLPushFunc) SetDefaultHook(hook func(string, interface{}) error)
|
||||
// LPush method of the parent MockKeyValue instance invokes the hook at the
|
||||
// front of the queue and discards it. After the queue is empty, the default
|
||||
// hook function is invoked for any future action.
|
||||
func (f *KeyValueLPushFunc) PushHook(hook func(string, interface{}) error) {
|
||||
func (f *KeyValueLPushFunc) PushHook(hook func(context.Context, string, interface{}) error) {
|
||||
f.mutex.Lock()
|
||||
f.hooks = append(f.hooks, hook)
|
||||
f.mutex.Unlock()
|
||||
@ -1969,19 +1972,19 @@ func (f *KeyValueLPushFunc) PushHook(hook func(string, interface{}) error) {
|
||||
// SetDefaultReturn calls SetDefaultHook with a function that returns the
|
||||
// given values.
|
||||
func (f *KeyValueLPushFunc) SetDefaultReturn(r0 error) {
|
||||
f.SetDefaultHook(func(string, interface{}) error {
|
||||
f.SetDefaultHook(func(context.Context, string, interface{}) error {
|
||||
return r0
|
||||
})
|
||||
}
|
||||
|
||||
// PushReturn calls PushHook with a function that returns the given values.
|
||||
func (f *KeyValueLPushFunc) PushReturn(r0 error) {
|
||||
f.PushHook(func(string, interface{}) error {
|
||||
f.PushHook(func(context.Context, string, interface{}) error {
|
||||
return r0
|
||||
})
|
||||
}
|
||||
|
||||
func (f *KeyValueLPushFunc) nextHook() func(string, interface{}) error {
|
||||
func (f *KeyValueLPushFunc) nextHook() func(context.Context, string, interface{}) error {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
||||
@ -2016,10 +2019,13 @@ func (f *KeyValueLPushFunc) History() []KeyValueLPushFuncCall {
|
||||
type KeyValueLPushFuncCall struct {
|
||||
// Arg0 is the value of the 1st argument passed to this method
|
||||
// invocation.
|
||||
Arg0 string
|
||||
Arg0 context.Context
|
||||
// Arg1 is the value of the 2nd argument passed to this method
|
||||
// invocation.
|
||||
Arg1 interface{}
|
||||
Arg1 string
|
||||
// Arg2 is the value of the 3rd argument passed to this method
|
||||
// invocation.
|
||||
Arg2 interface{}
|
||||
// Result0 is the value of the 1st result returned from this method
|
||||
// invocation.
|
||||
Result0 error
|
||||
@ -2028,7 +2034,7 @@ type KeyValueLPushFuncCall struct {
|
||||
// Args returns an interface slice containing the arguments of this
|
||||
// invocation.
|
||||
func (c KeyValueLPushFuncCall) Args() []interface{} {
|
||||
return []interface{}{c.Arg0, c.Arg1}
|
||||
return []interface{}{c.Arg0, c.Arg1, c.Arg2}
|
||||
}
|
||||
|
||||
// Results returns an interface slice containing the results of this
|
||||
@ -2040,23 +2046,23 @@ func (c KeyValueLPushFuncCall) Results() []interface{} {
|
||||
// KeyValueLRangeFunc describes the behavior when the LRange method of the
|
||||
// parent MockKeyValue instance is invoked.
|
||||
type KeyValueLRangeFunc struct {
|
||||
defaultHook func(string, int, int) Values
|
||||
hooks []func(string, int, int) Values
|
||||
defaultHook func(context.Context, string, int, int) Values
|
||||
hooks []func(context.Context, string, int, int) Values
|
||||
history []KeyValueLRangeFuncCall
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// LRange delegates to the next hook function in the queue and stores the
|
||||
// parameter and result values of this invocation.
|
||||
func (m *MockKeyValue) LRange(v0 string, v1 int, v2 int) Values {
|
||||
r0 := m.LRangeFunc.nextHook()(v0, v1, v2)
|
||||
m.LRangeFunc.appendCall(KeyValueLRangeFuncCall{v0, v1, v2, r0})
|
||||
func (m *MockKeyValue) LRange(v0 context.Context, v1 string, v2 int, v3 int) Values {
|
||||
r0 := m.LRangeFunc.nextHook()(v0, v1, v2, v3)
|
||||
m.LRangeFunc.appendCall(KeyValueLRangeFuncCall{v0, v1, v2, v3, r0})
|
||||
return r0
|
||||
}
|
||||
|
||||
// SetDefaultHook sets function that is called when the LRange method of the
|
||||
// parent MockKeyValue instance is invoked and the hook queue is empty.
|
||||
func (f *KeyValueLRangeFunc) SetDefaultHook(hook func(string, int, int) Values) {
|
||||
func (f *KeyValueLRangeFunc) SetDefaultHook(hook func(context.Context, string, int, int) Values) {
|
||||
f.defaultHook = hook
|
||||
}
|
||||
|
||||
@ -2064,7 +2070,7 @@ func (f *KeyValueLRangeFunc) SetDefaultHook(hook func(string, int, int) Values)
|
||||
// LRange method of the parent MockKeyValue instance invokes the hook at the
|
||||
// front of the queue and discards it. After the queue is empty, the default
|
||||
// hook function is invoked for any future action.
|
||||
func (f *KeyValueLRangeFunc) PushHook(hook func(string, int, int) Values) {
|
||||
func (f *KeyValueLRangeFunc) PushHook(hook func(context.Context, string, int, int) Values) {
|
||||
f.mutex.Lock()
|
||||
f.hooks = append(f.hooks, hook)
|
||||
f.mutex.Unlock()
|
||||
@ -2073,19 +2079,19 @@ func (f *KeyValueLRangeFunc) PushHook(hook func(string, int, int) Values) {
|
||||
// SetDefaultReturn calls SetDefaultHook with a function that returns the
|
||||
// given values.
|
||||
func (f *KeyValueLRangeFunc) SetDefaultReturn(r0 Values) {
|
||||
f.SetDefaultHook(func(string, int, int) Values {
|
||||
f.SetDefaultHook(func(context.Context, string, int, int) Values {
|
||||
return r0
|
||||
})
|
||||
}
|
||||
|
||||
// PushReturn calls PushHook with a function that returns the given values.
|
||||
func (f *KeyValueLRangeFunc) PushReturn(r0 Values) {
|
||||
f.PushHook(func(string, int, int) Values {
|
||||
f.PushHook(func(context.Context, string, int, int) Values {
|
||||
return r0
|
||||
})
|
||||
}
|
||||
|
||||
func (f *KeyValueLRangeFunc) nextHook() func(string, int, int) Values {
|
||||
func (f *KeyValueLRangeFunc) nextHook() func(context.Context, string, int, int) Values {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
||||
@ -2120,13 +2126,16 @@ func (f *KeyValueLRangeFunc) History() []KeyValueLRangeFuncCall {
|
||||
type KeyValueLRangeFuncCall struct {
|
||||
// Arg0 is the value of the 1st argument passed to this method
|
||||
// invocation.
|
||||
Arg0 string
|
||||
Arg0 context.Context
|
||||
// Arg1 is the value of the 2nd argument passed to this method
|
||||
// invocation.
|
||||
Arg1 int
|
||||
Arg1 string
|
||||
// Arg2 is the value of the 3rd argument passed to this method
|
||||
// invocation.
|
||||
Arg2 int
|
||||
// Arg3 is the value of the 4th argument passed to this method
|
||||
// invocation.
|
||||
Arg3 int
|
||||
// Result0 is the value of the 1st result returned from this method
|
||||
// invocation.
|
||||
Result0 Values
|
||||
@ -2135,7 +2144,7 @@ type KeyValueLRangeFuncCall struct {
|
||||
// Args returns an interface slice containing the arguments of this
|
||||
// invocation.
|
||||
func (c KeyValueLRangeFuncCall) Args() []interface{} {
|
||||
return []interface{}{c.Arg0, c.Arg1, c.Arg2}
|
||||
return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3}
|
||||
}
|
||||
|
||||
// Results returns an interface slice containing the results of this
|
||||
@ -2147,23 +2156,23 @@ func (c KeyValueLRangeFuncCall) Results() []interface{} {
|
||||
// KeyValueLTrimFunc describes the behavior when the LTrim method of the
|
||||
// parent MockKeyValue instance is invoked.
|
||||
type KeyValueLTrimFunc struct {
|
||||
defaultHook func(string, int, int) error
|
||||
hooks []func(string, int, int) error
|
||||
defaultHook func(context.Context, string, int, int) error
|
||||
hooks []func(context.Context, string, int, int) error
|
||||
history []KeyValueLTrimFuncCall
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// LTrim delegates to the next hook function in the queue and stores the
|
||||
// parameter and result values of this invocation.
|
||||
func (m *MockKeyValue) LTrim(v0 string, v1 int, v2 int) error {
|
||||
r0 := m.LTrimFunc.nextHook()(v0, v1, v2)
|
||||
m.LTrimFunc.appendCall(KeyValueLTrimFuncCall{v0, v1, v2, r0})
|
||||
func (m *MockKeyValue) LTrim(v0 context.Context, v1 string, v2 int, v3 int) error {
|
||||
r0 := m.LTrimFunc.nextHook()(v0, v1, v2, v3)
|
||||
m.LTrimFunc.appendCall(KeyValueLTrimFuncCall{v0, v1, v2, v3, r0})
|
||||
return r0
|
||||
}
|
||||
|
||||
// SetDefaultHook sets function that is called when the LTrim method of the
|
||||
// parent MockKeyValue instance is invoked and the hook queue is empty.
|
||||
func (f *KeyValueLTrimFunc) SetDefaultHook(hook func(string, int, int) error) {
|
||||
func (f *KeyValueLTrimFunc) SetDefaultHook(hook func(context.Context, string, int, int) error) {
|
||||
f.defaultHook = hook
|
||||
}
|
||||
|
||||
@ -2171,7 +2180,7 @@ func (f *KeyValueLTrimFunc) SetDefaultHook(hook func(string, int, int) error) {
|
||||
// LTrim method of the parent MockKeyValue instance invokes the hook at the
|
||||
// front of the queue and discards it. After the queue is empty, the default
|
||||
// hook function is invoked for any future action.
|
||||
func (f *KeyValueLTrimFunc) PushHook(hook func(string, int, int) error) {
|
||||
func (f *KeyValueLTrimFunc) PushHook(hook func(context.Context, string, int, int) error) {
|
||||
f.mutex.Lock()
|
||||
f.hooks = append(f.hooks, hook)
|
||||
f.mutex.Unlock()
|
||||
@ -2180,19 +2189,19 @@ func (f *KeyValueLTrimFunc) PushHook(hook func(string, int, int) error) {
|
||||
// SetDefaultReturn calls SetDefaultHook with a function that returns the
|
||||
// given values.
|
||||
func (f *KeyValueLTrimFunc) SetDefaultReturn(r0 error) {
|
||||
f.SetDefaultHook(func(string, int, int) error {
|
||||
f.SetDefaultHook(func(context.Context, string, int, int) error {
|
||||
return r0
|
||||
})
|
||||
}
|
||||
|
||||
// PushReturn calls PushHook with a function that returns the given values.
|
||||
func (f *KeyValueLTrimFunc) PushReturn(r0 error) {
|
||||
f.PushHook(func(string, int, int) error {
|
||||
f.PushHook(func(context.Context, string, int, int) error {
|
||||
return r0
|
||||
})
|
||||
}
|
||||
|
||||
func (f *KeyValueLTrimFunc) nextHook() func(string, int, int) error {
|
||||
func (f *KeyValueLTrimFunc) nextHook() func(context.Context, string, int, int) error {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
||||
@ -2227,13 +2236,16 @@ func (f *KeyValueLTrimFunc) History() []KeyValueLTrimFuncCall {
|
||||
type KeyValueLTrimFuncCall struct {
|
||||
// Arg0 is the value of the 1st argument passed to this method
|
||||
// invocation.
|
||||
Arg0 string
|
||||
Arg0 context.Context
|
||||
// Arg1 is the value of the 2nd argument passed to this method
|
||||
// invocation.
|
||||
Arg1 int
|
||||
Arg1 string
|
||||
// Arg2 is the value of the 3rd argument passed to this method
|
||||
// invocation.
|
||||
Arg2 int
|
||||
// Arg3 is the value of the 4th argument passed to this method
|
||||
// invocation.
|
||||
Arg3 int
|
||||
// Result0 is the value of the 1st result returned from this method
|
||||
// invocation.
|
||||
Result0 error
|
||||
@ -2242,7 +2254,7 @@ type KeyValueLTrimFuncCall struct {
|
||||
// Args returns an interface slice containing the arguments of this
|
||||
// invocation.
|
||||
func (c KeyValueLTrimFuncCall) Args() []interface{} {
|
||||
return []interface{}{c.Arg0, c.Arg1, c.Arg2}
|
||||
return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3}
|
||||
}
|
||||
|
||||
// Results returns an interface slice containing the results of this
|
||||
@ -2355,23 +2367,23 @@ func (c KeyValueMGetFuncCall) Results() []interface{} {
|
||||
// KeyValuePingFunc describes the behavior when the Ping method of the
|
||||
// parent MockKeyValue instance is invoked.
|
||||
type KeyValuePingFunc struct {
|
||||
defaultHook func() error
|
||||
hooks []func() error
|
||||
defaultHook func(context.Context) error
|
||||
hooks []func(context.Context) error
|
||||
history []KeyValuePingFuncCall
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// Ping delegates to the next hook function in the queue and stores the
|
||||
// parameter and result values of this invocation.
|
||||
func (m *MockKeyValue) Ping() error {
|
||||
r0 := m.PingFunc.nextHook()()
|
||||
m.PingFunc.appendCall(KeyValuePingFuncCall{r0})
|
||||
func (m *MockKeyValue) Ping(v0 context.Context) error {
|
||||
r0 := m.PingFunc.nextHook()(v0)
|
||||
m.PingFunc.appendCall(KeyValuePingFuncCall{v0, r0})
|
||||
return r0
|
||||
}
|
||||
|
||||
// SetDefaultHook sets function that is called when the Ping method of the
|
||||
// parent MockKeyValue instance is invoked and the hook queue is empty.
|
||||
func (f *KeyValuePingFunc) SetDefaultHook(hook func() error) {
|
||||
func (f *KeyValuePingFunc) SetDefaultHook(hook func(context.Context) error) {
|
||||
f.defaultHook = hook
|
||||
}
|
||||
|
||||
@ -2379,7 +2391,7 @@ func (f *KeyValuePingFunc) SetDefaultHook(hook func() error) {
|
||||
// Ping method of the parent MockKeyValue instance invokes the hook at the
|
||||
// front of the queue and discards it. After the queue is empty, the default
|
||||
// hook function is invoked for any future action.
|
||||
func (f *KeyValuePingFunc) PushHook(hook func() error) {
|
||||
func (f *KeyValuePingFunc) PushHook(hook func(context.Context) error) {
|
||||
f.mutex.Lock()
|
||||
f.hooks = append(f.hooks, hook)
|
||||
f.mutex.Unlock()
|
||||
@ -2388,19 +2400,19 @@ func (f *KeyValuePingFunc) PushHook(hook func() error) {
|
||||
// SetDefaultReturn calls SetDefaultHook with a function that returns the
|
||||
// given values.
|
||||
func (f *KeyValuePingFunc) SetDefaultReturn(r0 error) {
|
||||
f.SetDefaultHook(func() error {
|
||||
f.SetDefaultHook(func(context.Context) error {
|
||||
return r0
|
||||
})
|
||||
}
|
||||
|
||||
// PushReturn calls PushHook with a function that returns the given values.
|
||||
func (f *KeyValuePingFunc) PushReturn(r0 error) {
|
||||
f.PushHook(func() error {
|
||||
f.PushHook(func(context.Context) error {
|
||||
return r0
|
||||
})
|
||||
}
|
||||
|
||||
func (f *KeyValuePingFunc) nextHook() func() error {
|
||||
func (f *KeyValuePingFunc) nextHook() func(context.Context) error {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
||||
@ -2433,6 +2445,9 @@ func (f *KeyValuePingFunc) History() []KeyValuePingFuncCall {
|
||||
// KeyValuePingFuncCall is an object that describes an invocation of method
|
||||
// Ping on an instance of MockKeyValue.
|
||||
type KeyValuePingFuncCall struct {
|
||||
// Arg0 is the value of the 1st argument passed to this method
|
||||
// invocation.
|
||||
Arg0 context.Context
|
||||
// Result0 is the value of the 1st result returned from this method
|
||||
// invocation.
|
||||
Result0 error
|
||||
@ -2441,7 +2456,7 @@ type KeyValuePingFuncCall struct {
|
||||
// Args returns an interface slice containing the arguments of this
|
||||
// invocation.
|
||||
func (c KeyValuePingFuncCall) Args() []interface{} {
|
||||
return []interface{}{}
|
||||
return []interface{}{c.Arg0}
|
||||
}
|
||||
|
||||
// Results returns an interface slice containing the results of this
|
||||
|
||||
@ -8,6 +8,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/sourcegraph/log/logtest"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/tenant"
|
||||
)
|
||||
|
||||
func TestSchemeMatcher(t *testing.T) {
|
||||
@ -38,11 +40,12 @@ func TestMain(m *testing.M) {
|
||||
func TestDeleteAllKeysWithPrefix(t *testing.T) {
|
||||
t.Helper()
|
||||
|
||||
ctx := tenant.TestContext()
|
||||
kv := NewTestKeyValue()
|
||||
|
||||
// If we are not on CI, skip the test if our redis connection fails.
|
||||
if os.Getenv("CI") == "" {
|
||||
if err := kv.Ping(); err != nil {
|
||||
if err := kv.Ping(ctx); err != nil {
|
||||
t.Skip("could not connect to redis", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@ go_test(
|
||||
deps = [
|
||||
":wrexec",
|
||||
"//internal/rcache",
|
||||
"//internal/tenant",
|
||||
"//lib/errors",
|
||||
"@com_github_google_go_cmp//cmp",
|
||||
"@com_github_sourcegraph_log//:log",
|
||||
|
||||
@ -113,7 +113,7 @@ func (rc *RecordingCmd) WithRedactorFunc(f RedactorFunc) *RecordingCmd {
|
||||
return rc
|
||||
}
|
||||
|
||||
func (rc *RecordingCmd) after(_ context.Context, logger log.Logger, cmd *exec.Cmd) {
|
||||
func (rc *RecordingCmd) after(ctx context.Context, logger log.Logger, cmd *exec.Cmd) {
|
||||
// ensure we don't record ourselves twice if the caller calls Wait() twice for example.
|
||||
defer func() { rc.done = true }()
|
||||
if rc.done {
|
||||
@ -163,7 +163,7 @@ func (rc *RecordingCmd) after(_ context.Context, logger log.Logger, cmd *exec.Cm
|
||||
return
|
||||
}
|
||||
|
||||
_ = rc.store.Insert(data)
|
||||
_ = rc.store.Insert(ctx, data)
|
||||
}
|
||||
|
||||
// RecordingCommandFactory stores a ShouldRecord that will be used to create a new RecordingCommand
|
||||
|
||||
@ -11,13 +11,14 @@ import (
|
||||
"github.com/sourcegraph/log/logtest"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/rcache"
|
||||
"github.com/sourcegraph/sourcegraph/internal/tenant"
|
||||
"github.com/sourcegraph/sourcegraph/internal/wrexec"
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
)
|
||||
|
||||
func listSize(t *testing.T, store *rcache.FIFOList) int {
|
||||
t.Helper()
|
||||
size, err := store.Size()
|
||||
size, err := store.Size(tenant.TestContext())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get size of FIFOList: %s", err)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user